00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "dot.h"
00023
00024
00025 #define UP 0
00026 #define DOWN 1
00027
00028 static boolean samedir(edge_t * e, edge_t * f)
00029 {
00030 edge_t *e0, *f0;
00031
00032 for (e0 = e; ED_edge_type(e0) != NORMAL; e0 = ED_to_orig(e0));
00033 for (f0 = f; ED_edge_type(f0) != NORMAL; f0 = ED_to_orig(f0));
00034 if (ED_conc_opp_flag(e0))
00035 return FALSE;
00036 if (ED_conc_opp_flag(f0))
00037 return FALSE;
00038 return ((ND_rank(f0->tail) - ND_rank(f0->head))
00039 * (ND_rank(e0->tail) - ND_rank(e0->head)) > 0);
00040 }
00041
00042 static boolean downcandidate(node_t * v)
00043 {
00044 return ((ND_node_type(v) == VIRTUAL) && (ND_in(v).size == 1)
00045 && (ND_out(v).size == 1) && (ND_label(v) == NULL));
00046 }
00047
00048 static boolean bothdowncandidates(node_t * u, node_t * v)
00049 {
00050 edge_t *e, *f;
00051 e = ND_in(u).list[0];
00052 f = ND_in(v).list[0];
00053 if (downcandidate(v) && (e->tail == f->tail)) {
00054 return samedir(e, f)
00055 && (portcmp(ED_tail_port(e), ED_tail_port(f)) == 0);
00056 }
00057 return FALSE;
00058 }
00059
00060 static boolean upcandidate(node_t * v)
00061 {
00062 return ((ND_node_type(v) == VIRTUAL) && (ND_out(v).size == 1)
00063 && (ND_in(v).size == 1) && (ND_label(v) == NULL));
00064 }
00065
00066 static boolean bothupcandidates(node_t * u, node_t * v)
00067 {
00068 edge_t *e, *f;
00069 e = ND_out(u).list[0];
00070 f = ND_out(v).list[0];
00071 if (upcandidate(v) && (e->head == f->head)) {
00072 return samedir(e, f)
00073 && (portcmp(ED_head_port(e), ED_head_port(f)) == 0);
00074 }
00075 return FALSE;
00076 }
00077
00078 static void mergevirtual(graph_t * g, int r, int lpos, int rpos, int dir)
00079 {
00080 int i, k;
00081 node_t *left, *right;
00082 edge_t *e, *f, *e0;
00083
00084 left = GD_rank(g)[r].v[lpos];
00085
00086 for (i = lpos + 1; i <= rpos; i++) {
00087 right = GD_rank(g)[r].v[i];
00088 if (dir == DOWN) {
00089 while ((e = ND_out(right).list[0])) {
00090 for (k = 0; (f = ND_out(left).list[k]); k++)
00091 if (f->head == e->head)
00092 break;
00093 if (f == NULL)
00094 f = virtual_edge(left, e->head, e);
00095 while ((e0 = ND_in(right).list[0])) {
00096 merge_oneway(e0, f);
00097
00098 delete_fast_edge(e0);
00099 }
00100 delete_fast_edge(e);
00101 }
00102 } else {
00103 while ((e = ND_in(right).list[0])) {
00104 for (k = 0; (f = ND_in(left).list[k]); k++)
00105 if (f->tail == e->tail)
00106 break;
00107 if (f == NULL)
00108 f = virtual_edge(e->tail, left, e);
00109 while ((e0 = ND_out(right).list[0])) {
00110 merge_oneway(e0, f);
00111 delete_fast_edge(e0);
00112 }
00113 delete_fast_edge(e);
00114 }
00115 }
00116 assert(ND_in(right).size + ND_out(right).size == 0);
00117 delete_fast_node(g, right);
00118 }
00119 k = lpos + 1;
00120 i = rpos + 1;
00121 while (i < GD_rank(g)[r].n) {
00122 node_t *n;
00123 n = GD_rank(g)[r].v[k] = GD_rank(g)[r].v[i];
00124 ND_order(n) = k;
00125 k++;
00126 i++;
00127 }
00128 GD_rank(g)[r].n = k;
00129 GD_rank(g)[r].v[k] = NULL;
00130 }
00131
00132 static void infuse(graph_t * g, node_t * n)
00133 {
00134 node_t *lead;
00135
00136 lead = GD_rankleader(g)[ND_rank(n)];
00137 if ((lead == NULL) || (ND_order(lead) > ND_order(n)))
00138 GD_rankleader(g)[ND_rank(n)] = n;
00139 }
00140
00141 static void rebuild_vlists(graph_t * g)
00142 {
00143 int c, i, r, maxi;
00144 node_t *n, *lead;
00145 edge_t *e, *rep;
00146
00147 for (r = GD_minrank(g); r <= GD_maxrank(g); r++)
00148 GD_rankleader(g)[r] = NULL;
00149 dot_scan_ranks(g);
00150 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00151 infuse(g, n);
00152 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
00153 for (rep = e; ED_to_virt(rep); rep = ED_to_virt(rep));
00154 while (ND_rank(rep->head) < ND_rank(e->head)) {
00155 infuse(g, rep->head);
00156 rep = ND_out(rep->head).list[0];
00157 }
00158 }
00159 }
00160
00161 for (r = GD_minrank(g); r <= GD_maxrank(g); r++) {
00162 lead = GD_rankleader(g)[r];
00163 if (ND_rank(g->root)[r].v[ND_order(lead)] != lead)
00164 abort();
00165 GD_rank(g)[r].v =
00166 ND_rank(g->root)[r].v + GD_rankleader(g)[r]->u.order;
00167 maxi = -1;
00168 for (i = 0; i < GD_rank(g)[r].n; i++) {
00169 if ((n = GD_rank(g)[r].v[i]) == NULL)
00170 break;
00171 if (ND_node_type(n) == NORMAL) {
00172 if (agcontains(g, n))
00173 maxi = i;
00174 else
00175 break;
00176 } else {
00177 edge_t *e;
00178 for (e = ND_in(n).list[0]; e && ED_to_orig(e);
00179 e = ED_to_orig(e));
00180 if (e && (agcontains(g, e->tail))
00181 && agcontains(g, e->head))
00182 maxi = i;
00183 }
00184 }
00185 if (maxi == -1)
00186 agerr(AGWARN, "degenerate concentrated rank %s,%d\n", g->name,
00187 r);
00188 GD_rank(g)[r].n = maxi + 1;
00189 }
00190
00191 for (c = 1; c <= GD_n_cluster(g); c++)
00192 rebuild_vlists(GD_clust(g)[c]);
00193 }
00194
00195 void dot_concentrate(graph_t * g)
00196 {
00197 int c, r, leftpos, rightpos;
00198 node_t *left, *right;
00199
00200 if (GD_maxrank(g) - GD_minrank(g) <= 1)
00201 return;
00202
00203 for (r = 1; GD_rank(g)[r + 1].n; r++) {
00204 for (leftpos = 0; leftpos < GD_rank(g)[r].n; leftpos++) {
00205 left = GD_rank(g)[r].v[leftpos];
00206 if (downcandidate(left) == FALSE)
00207 continue;
00208 for (rightpos = leftpos + 1; rightpos < GD_rank(g)[r].n;
00209 rightpos++) {
00210 right = GD_rank(g)[r].v[rightpos];
00211 if (bothdowncandidates(left, right) == FALSE)
00212 break;
00213 }
00214 if (rightpos - leftpos > 1)
00215 mergevirtual(g, r, leftpos, rightpos - 1, DOWN);
00216 }
00217 }
00218
00219 while (r > 0) {
00220 for (leftpos = 0; leftpos < GD_rank(g)[r].n; leftpos++) {
00221 left = GD_rank(g)[r].v[leftpos];
00222 if (upcandidate(left) == FALSE)
00223 continue;
00224 for (rightpos = leftpos + 1; rightpos < GD_rank(g)[r].n;
00225 rightpos++) {
00226 right = GD_rank(g)[r].v[rightpos];
00227 if (bothupcandidates(left, right) == FALSE)
00228 break;
00229 }
00230 if (rightpos - leftpos > 1)
00231 mergevirtual(g, r, leftpos, rightpos - 1, UP);
00232 }
00233 r--;
00234 }
00235 for (c = 1; c <= GD_n_cluster(g); c++)
00236 rebuild_vlists(GD_clust(g)[c]);
00237 }