00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "dot.h"
00019
00020 static node_t*
00021 map_interclust_node(node_t * n)
00022 {
00023 node_t *rv;
00024
00025 if ((ND_clust(n) == NULL) || (ND_clust(n)->u.expanded))
00026 rv = n;
00027 else
00028 rv = ND_clust(n)->u.rankleader[ND_rank(n)];
00029 return rv;
00030 }
00031
00032
00033 static void
00034 make_slots(graph_t * root, int r, int pos, int d)
00035 {
00036 int i;
00037 node_t *v, **vlist;
00038 vlist = ND_rank(root)[r].v;
00039 if (d <= 0) {
00040 for (i = pos - d + 1; i < ND_rank(root)[r].n; i++) {
00041 v = vlist[i];
00042 ND_order(v) = i + d - 1;
00043 vlist[ND_order(v)] = v;
00044 }
00045 for (i = ND_rank(root)[r].n + d - 1; i < ND_rank(root)[r].n; i++)
00046 vlist[i] = NULL;
00047 } else {
00048
00049 for (i = ND_rank(root)[r].n - 1; i > pos; i--) {
00050 v = vlist[i];
00051 ND_order(v) = i + d - 1;
00052 vlist[ND_order(v)] = v;
00053 }
00054 for (i = pos + 1; i < pos + d; i++)
00055 vlist[i] = NULL;
00056 }
00057 ND_rank(root)[r].n += d - 1;
00058 }
00059
00060 static node_t*
00061 clone_vn(graph_t * g, node_t * vn)
00062 {
00063 node_t *rv;
00064 int r;
00065
00066 r = ND_rank(vn);
00067 make_slots(g, r, ND_order(vn), 2);
00068 rv = virtual_node(g);
00069 ND_lw_i(rv) = ND_lw_i(vn);
00070 ND_rw_i(rv) = ND_rw_i(vn);
00071 ND_rank(rv) = ND_rank(vn);
00072 ND_order(rv) = ND_order(vn) + 1;
00073 GD_rank(g)[r].v[ND_order(rv)] = rv;
00074 return rv;
00075 }
00076
00077 static void
00078 map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve, int type)
00079 {
00080 int r;
00081 node_t *u, *v;
00082 edge_t *e;
00083
00084 assert(ND_rank(from) < ND_rank(to));
00085
00086 if ((ve->tail == from) && (ve->head == to))
00087 return;
00088
00089 if (ED_count(ve) > 1) {
00090 ED_to_virt(orig) = NULL;
00091 if (ND_rank(to) - ND_rank(from) == 1) {
00092 if ((e = find_fast_edge(from, to)) && (ports_eq(orig, e))) {
00093 merge_oneway(orig, e);
00094 if ((ND_node_type(from) == NORMAL)
00095 && (ND_node_type(to) == NORMAL))
00096 other_edge(orig);
00097 return;
00098 }
00099 }
00100 u = from;
00101 for (r = ND_rank(from); r < ND_rank(to); r++) {
00102 if (r < ND_rank(to) - 1)
00103 v = clone_vn(from->graph, ve->head);
00104 else
00105 v = to;
00106 e = virtual_edge(u, v, orig);
00107 ED_edge_type(e) = type;
00108 u = v;
00109 ED_count(ve)--;
00110 ve = ND_out(ve->head).list[0];
00111 }
00112 } else {
00113 if (ND_rank(to) - ND_rank(from) == 1) {
00114 if ((ve = find_fast_edge(from, to)) && (ports_eq(orig, ve))) {
00115
00116 ED_to_virt(orig) = ve;
00117 ED_edge_type(ve) = type;
00118 ED_count(ve)++;
00119 if ((ND_node_type(from) == NORMAL)
00120 && (ND_node_type(to) == NORMAL))
00121 other_edge(orig);
00122 } else {
00123 ED_to_virt(orig) = NULL;
00124 ve = virtual_edge(from, to, orig);
00125 ED_edge_type(ve) = type;
00126 }
00127 }
00128 if (ND_rank(to) - ND_rank(from) > 1) {
00129 e = ve;
00130 if (ve->tail != from) {
00131 ED_to_virt(orig) = NULL;
00132 e = ED_to_virt(orig) = virtual_edge(from, ve->head, orig);
00133 delete_fast_edge(ve);
00134 } else
00135 e = ve;
00136 while (ND_rank(e->head) != ND_rank(to))
00137 e = ND_out(e->head).list[0];
00138 if (e->head != to) {
00139 ve = e;
00140 e = virtual_edge(e->tail, to, orig);
00141 ED_edge_type(e) = type;
00142 delete_fast_edge(ve);
00143 }
00144 }
00145 }
00146 }
00147
00148 static void
00149 make_interclust_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
00150 {
00151 int newtype;
00152 node_t *u, *v;
00153
00154 u = map_interclust_node(from);
00155 v = map_interclust_node(to);
00156 if ((u == from) && (v == to))
00157 newtype = VIRTUAL;
00158 else
00159 newtype = CLUSTER_EDGE;
00160 map_path(u, v, orig, ED_to_virt(orig), newtype);
00161 }
00162
00163
00164
00165
00166
00167 void interclexp(graph_t * subg)
00168 {
00169 graph_t *g;
00170 node_t *n;
00171 edge_t *e, *prev;
00172
00173 g = subg->root;
00174 for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
00175
00176
00177 prev = NULL;
00178 for (e = agfstedge(subg->root, n); e;
00179 e = agnxtedge(subg->root, e, n)) {
00180 if (agcontains(subg, e))
00181 continue;
00182
00183
00184 if (mergeable(prev, e)) {
00185 if (ND_rank(e->tail) == ND_rank(e->head))
00186 ED_to_virt(e) = prev;
00187 else
00188 ED_to_virt(e) = NULL;
00189 if (ED_to_virt(prev) == NULL)
00190 continue;
00191 merge_chain(subg, e, ED_to_virt(prev), FALSE);
00192 safe_other_edge(e);
00193 continue;
00194 }
00195
00196
00197 if (ND_rank(e->tail) == ND_rank(e->head)) {
00198 edge_t* fe;
00199 if ((fe = find_flat_edge(e->tail, e->head)) == NULL) {
00200 flat_edge(g, e);
00201 prev = e;
00202 } else if (e != fe) {
00203 safe_other_edge(e);
00204 if (!ED_to_virt(e)) merge_oneway(e, fe);
00205 }
00206 continue;
00207 }
00208
00209 assert(ED_to_virt(e) != NULL);
00210
00211
00212 if (ND_rank(e->head) > ND_rank(e->tail)) {
00213 make_interclust_chain(g, e->tail, e->head, e);
00214 prev = e;
00215 continue;
00216 }
00217
00218
00219 else {
00220
00221
00222
00223
00224
00225 make_interclust_chain(g, e->head, e->tail, e);
00226 prev = e;
00227 }
00228 }
00229 }
00230 }
00231
00232 static void
00233 merge_ranks(graph_t * subg)
00234 {
00235 int i, d, r, pos, ipos;
00236 node_t *v;
00237 graph_t *root;
00238
00239 root = subg->root;
00240 if (GD_minrank(subg) > 0)
00241 ND_rank(root)[GD_minrank(subg) - 1].valid = FALSE;
00242 for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
00243 d = GD_rank(subg)[r].n;
00244 ipos = pos = GD_rankleader(subg)[r]->u.order;
00245 make_slots(root, r, pos, d);
00246 for (i = 0; i < GD_rank(subg)[r].n; i++) {
00247 v = ND_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i];
00248 ND_order(v) = pos++;
00249 v->graph = subg->root;
00250 delete_fast_node(subg, v);
00251 fast_node(subg->root, v);
00252 GD_n_nodes(subg->root)++;
00253 }
00254 GD_rank(subg)[r].v = ND_rank(root)[r].v + ipos;
00255 ND_rank(root)[r].valid = FALSE;
00256 }
00257 if (r < GD_maxrank(root))
00258 GD_rank(root)[r].valid = FALSE;
00259 GD_expanded(subg) = TRUE;
00260 }
00261
00262 static void
00263 remove_rankleaders(graph_t * g)
00264 {
00265 int r;
00266 node_t *v;
00267 edge_t *e;
00268
00269 for (r = GD_minrank(g); r <= GD_maxrank(g); r++) {
00270 v = GD_rankleader(g)[r];
00271
00272
00273 while ((e = ND_out(v).list[0]))
00274 delete_fast_edge(e);
00275 while ((e = ND_in(v).list[0]))
00276 delete_fast_edge(e);
00277 delete_fast_node(g->root, v);
00278 GD_rankleader(g)[r] = NULL;
00279 }
00280 }
00281
00282
00283 void expand_cluster(graph_t * subg)
00284 {
00285
00286 class2(subg);
00287 GD_comp(subg).size = 1;
00288 GD_comp(subg).list[0] = GD_nlist(subg);
00289 allocate_ranks(subg);
00290 build_ranks(subg, 0);
00291 merge_ranks(subg);
00292
00293
00294 interclexp(subg);
00295 remove_rankleaders(subg);
00296 }
00297
00298
00299 void mark_clusters(graph_t * g)
00300 {
00301 int c;
00302 node_t *n, *vn;
00303 edge_t *orig, *e;
00304 graph_t *clust;
00305
00306
00307 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00308 if (ND_ranktype(n) == CLUSTER)
00309 UF_singleton(n);
00310 ND_clust(n) = NULL;
00311 }
00312
00313 for (c = 1; c <= GD_n_cluster(g); c++) {
00314 clust = GD_clust(g)[c];
00315 for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
00316 if (ND_ranktype(n) != NORMAL) {
00317 agerr(AGWARN,
00318 "%s was already in a rankset, ignored in cluster %s\n",
00319 n->name, g->name);
00320 continue;
00321 }
00322 UF_setname(n, GD_leader(clust));
00323 ND_clust(n) = clust;
00324 ND_ranktype(n) = CLUSTER;
00325
00326
00327 for (orig = agfstout(clust, n); orig;
00328 orig = agnxtout(clust, orig)) {
00329 if ((e = ED_to_virt(orig))) {
00330 while (e && (vn = e->head)->u.node_type == VIRTUAL) {
00331 ND_clust(vn) = clust;
00332 e = ND_out(e->head).list[0];
00333
00334 }
00335 }
00336 }
00337 }
00338 }
00339 }
00340
00341 void build_skeleton(graph_t * g, graph_t * subg)
00342 {
00343 int r;
00344 node_t *v, *prev, *rl;
00345 edge_t *e;
00346
00347 prev = NULL;
00348 GD_rankleader(subg) = N_NEW(GD_maxrank(subg) + 2, node_t *);
00349 for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
00350 v = GD_rankleader(subg)[r] = virtual_node(g);
00351 ND_rank(v) = r;
00352 ND_ranktype(v) = CLUSTER;
00353 ND_clust(v) = subg;
00354 if (prev) {
00355 e = virtual_edge(prev, v, NULL);
00356 ED_xpenalty(e) *= CL_CROSS;
00357 }
00358 prev = v;
00359 }
00360
00361
00362 for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
00363 rl = GD_rankleader(subg)[ND_rank(v)];
00364 ND_UF_size(rl)++;
00365 for (e = agfstout(subg, v); e; e = agnxtout(subg, e)) {
00366 for (r = ND_rank(e->tail); r < ND_rank(e->head); r++) {
00367 ED_count(ND_out(rl).list[0])++;
00368 }
00369 }
00370 }
00371 for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
00372 rl = GD_rankleader(subg)[r];
00373 if (ND_UF_size(rl) > 1)
00374 ND_UF_size(rl)--;
00375 }
00376 }
00377
00378 void install_cluster(graph_t * g, node_t * n, int pass, nodequeue * q)
00379 {
00380 int r;
00381 graph_t *clust;
00382
00383 clust = ND_clust(n);
00384 if (GD_installed(clust) != pass + 1) {
00385 for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
00386 install_in_rank(g, GD_rankleader(clust)[r]);
00387 for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
00388 enqueue_neighbors(q, GD_rankleader(clust)[r], pass);
00389 GD_installed(clust) = pass + 1;
00390 }
00391 }
00392
00393 static void mark_lowcluster_basic(Agraph_t * g);
00394 void mark_lowclusters(Agraph_t * root)
00395 {
00396 Agnode_t *n, *vn;
00397 Agedge_t *orig, *e;
00398
00399
00400 for (n = agfstnode(root); n; n = agnxtnode(root, n)) {
00401 ND_clust(n) = NULL;
00402 for (orig = agfstout(root, n); orig; orig = agnxtout(root, orig)) {
00403 if ((e = ED_to_virt(orig))) {
00404 while (e && (vn = e->head)->u.node_type == VIRTUAL) {
00405 ND_clust(vn) = NULL;
00406 e = ND_out(e->head).list[0];
00407 }
00408 }
00409 }
00410 }
00411
00412
00413 mark_lowcluster_basic(root);
00414 }
00415
00416 static void mark_lowcluster_basic(Agraph_t * g)
00417 {
00418 Agraph_t *clust;
00419 Agnode_t *n, *vn;
00420 Agedge_t *orig, *e;
00421 int c;
00422
00423 for (c = 1; c <= GD_n_cluster(g); c++) {
00424 clust = GD_clust(g)[c];
00425 mark_lowcluster_basic(clust);
00426 }
00427
00428 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00429 if (ND_clust(n) == NULL)
00430 ND_clust(n) = g;
00431 for (orig = agfstout(g, n); orig; orig = agnxtout(g, orig)) {
00432 if ((e = ED_to_virt(orig))) {
00433 while (e && (vn = e->head)->u.node_type == VIRTUAL) {
00434 if (ND_clust(vn) == NULL)
00435 ND_clust(vn) = g;
00436 e = ND_out(e->head).list[0];
00437 }
00438 }
00439 }
00440 }
00441 }