#include "dot.h"
+static node_t*
+label_vnode(graph_t * g, edge_t * orig)
+{
+ node_t *v;
+ pointf dimen;
+
+ dimen = ED_label(orig)->dimen;
+ v = virtual_node(g);
+ ND_label(v) = ED_label(orig);
+ ND_lw_i(v) = GD_nodesep(v->graph);
+ if (!ED_label_ontop(orig)) {
+ if (GD_flip(g)) {
+ ND_ht_i(v) = dimen.x;
+ ND_rw_i(v) = dimen.y;
+ } else {
+ ND_ht_i(v) = dimen.y;
+ ND_rw_i(v) = dimen.x;
+ }
+ }
+ return v;
+}
+
+static void
+incr_width(graph_t * g, node_t * v)
+{
+ int width = GD_nodesep(g) / 2;
+ ND_lw_i(v) += width;
+ ND_rw_i(v) += width;
+}
+
+static node_t*
+plain_vnode(graph_t * g, edge_t * orig)
+{
+ node_t *v;
+ orig = orig;
+ v = virtual_node(g);
+ incr_width(g, v);
+ return v;
+}
+
+static node_t*
+leader_of(graph_t * g, node_t * v)
+{
+ graph_t *clust;
+ node_t *rv;
+
+ if (ND_ranktype(v) != CLUSTER) {
+ /*assert(v == UF_find(v)); could be leaf, so comment out */
+ rv = UF_find(v);
+ } else {
+ clust = ND_clust(v);
+ rv = GD_rankleader(clust)[ND_rank(v)];
+ }
+ return rv;
+}
+
+static void
+make_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
+{
+ int r, label_rank;
+ node_t *u, *v;
+ edge_t *e;
+
+ u = from;
+ if (ED_label(orig))
+ label_rank = (ND_rank(from) + ND_rank(to)) / 2;
+ else
+ label_rank = -1;
+ assert(ED_to_virt(orig) == NULL);
+ for (r = ND_rank(from) + 1; r <= ND_rank(to); r++) {
+ if (r < ND_rank(to)) {
+ if (r == label_rank)
+ v = label_vnode(g, orig);
+ else
+ v = plain_vnode(g, orig);
+ ND_rank(v) = r;
+ } else
+ v = to;
+ e = virtual_edge(u, v, orig);
+ virtual_weight(e);
+ u = v;
+ }
+ assert(ED_to_virt(orig) != NULL);
+}
+
+static void
+interclrep(graph_t * g, edge_t * e)
+{
+ node_t *t, *h;
+ edge_t *ve;
+
+ t = leader_of(g, e->tail);
+ h = leader_of(g, e->head);
+ if (ND_rank(t) > ND_rank(h)) {
+ node_t *t0 = t;
+ t = h;
+ h = t0;
+ }
+ if (ND_clust(t) != ND_clust(h)) {
+ if ((ve = find_fast_edge(t, h))) {
+ merge_chain(g, e, ve, TRUE);
+ return;
+ }
+ if (ND_rank(t) == ND_rank(h))
+ return;
+ make_chain(g, t, h, e);
+
+ /* mark as cluster edge */
+ for (ve = ED_to_virt(e); ve && (ND_rank(ve->head) <= ND_rank(h));
+ ve = ND_out(ve->head).list[0])
+ ED_edge_type(ve) = CLUSTER_EDGE;
+ }
+ /* else ignore intra-cluster edges at this point */
+}
+
+static int
+is_cluster_edge(edge_t * e)
+{
+ return ((ND_ranktype(e->tail) == CLUSTER)
+ || (ND_ranktype(e->head) == CLUSTER));
+}
+
+void merge_chain(graph_t * g, edge_t * e, edge_t * f, int flag)
+{
+ edge_t *rep;
+ int lastrank = MAX(ND_rank(e->tail), ND_rank(e->head));
+
+ assert(ED_to_virt(e) == NULL);
+ ED_to_virt(e) = f;
+ rep = f;
+ do {
+ /* interclust multi-edges are not counted now */
+ if (flag)
+ ED_count(rep) += ED_count(e);
+ ED_xpenalty(rep) += ED_xpenalty(e);
+ ED_weight(rep) += ED_weight(e);
+ if (ND_rank(rep->head) == lastrank)
+ break;
+ incr_width(g, rep->head);
+ rep = ND_out(rep->head).list[0];
+ } while (rep);
+}
+
+int mergeable(edge_t * e, edge_t * f)
+{
+ if (e && f && (e->tail == f->tail) && (e->head == f->head) &&
+ (ED_label(e) == ED_label(f)) && ports_eq(e, f))
+ return TRUE;
+ return FALSE;
+}
void class2(graph_t * g)
{
}
}
-node_t *label_vnode(graph_t * g, edge_t * orig)
-{
- node_t *v;
- pointf dimen;
-
- dimen = ED_label(orig)->dimen;
- v = virtual_node(g);
- ND_label(v) = ED_label(orig);
- ND_lw_i(v) = GD_nodesep(v->graph);
- if (!ED_label_ontop(orig)) {
- if (GD_flip(g)) {
- ND_ht_i(v) = dimen.x;
- ND_rw_i(v) = dimen.y;
- } else {
- ND_ht_i(v) = dimen.y;
- ND_rw_i(v) = dimen.x;
- }
- }
- return v;
-}
-
-node_t *plain_vnode(graph_t * g, edge_t * orig)
-{
- node_t *v;
- orig = orig;
- v = virtual_node(g);
- incr_width(g, v);
- return v;
-}
-
-void incr_width(graph_t * g, node_t * v)
-{
- int width = GD_nodesep(g) / 2;
- ND_lw_i(v) += width;
- ND_rw_i(v) += width;
-}
-
-void make_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
-{
- int r, label_rank;
- node_t *u, *v;
- edge_t *e;
-
- u = from;
- if (ED_label(orig))
- label_rank = (ND_rank(from) + ND_rank(to)) / 2;
- else
- label_rank = -1;
- assert(ED_to_virt(orig) == NULL);
- for (r = ND_rank(from) + 1; r <= ND_rank(to); r++) {
- if (r < ND_rank(to)) {
- if (r == label_rank)
- v = label_vnode(g, orig);
- else
- v = plain_vnode(g, orig);
- ND_rank(v) = r;
- } else
- v = to;
- e = virtual_edge(u, v, orig);
- virtual_weight(e);
- u = v;
- }
- assert(ED_to_virt(orig) != NULL);
-}
-
-void merge_chain(graph_t * g, edge_t * e, edge_t * f, int flag)
-{
- edge_t *rep;
- int lastrank = MAX(ND_rank(e->tail), ND_rank(e->head));
-
- assert(ED_to_virt(e) == NULL);
- ED_to_virt(e) = f;
- rep = f;
- do {
- /* interclust multi-edges are not counted now */
- if (flag)
- ED_count(rep) += ED_count(e);
- ED_xpenalty(rep) += ED_xpenalty(e);
- ED_weight(rep) += ED_weight(e);
- if (ND_rank(rep->head) == lastrank)
- break;
- incr_width(g, rep->head);
- rep = ND_out(rep->head).list[0];
- } while (rep);
-}
-
-node_t *leader_of(graph_t * g, node_t * v)
-{
- graph_t *clust;
- node_t *rv;
-
- if (ND_ranktype(v) != CLUSTER) {
- /*assert(v == UF_find(v)); could be leaf, so comment out */
- rv = UF_find(v);
- } else {
- clust = ND_clust(v);
- rv = GD_rankleader(clust)[ND_rank(v)];
- }
- return rv;
-}
-
-void interclrep(graph_t * g, edge_t * e)
-{
- node_t *t, *h;
- edge_t *ve;
-
- t = leader_of(g, e->tail);
- h = leader_of(g, e->head);
- if (ND_rank(t) > ND_rank(h)) {
- node_t *t0 = t;
- t = h;
- h = t0;
- }
- if (ND_clust(t) != ND_clust(h)) {
- if ((ve = find_fast_edge(t, h))) {
- merge_chain(g, e, ve, TRUE);
- return;
- }
- if (ND_rank(t) == ND_rank(h))
- return;
- make_chain(g, t, h, e);
-
- /* mark as cluster edge */
- for (ve = ED_to_virt(e); ve && (ND_rank(ve->head) <= ND_rank(h));
- ve = ND_out(ve->head).list[0])
- ED_edge_type(ve) = CLUSTER_EDGE;
- }
- /* else ignore intra-cluster edges at this point */
-}
-
-int is_cluster_edge(edge_t * e)
-{
- return ((ND_ranktype(e->tail) == CLUSTER)
- || (ND_ranktype(e->head) == CLUSTER));
-}
-
-int mergeable(edge_t * e, edge_t * f)
-{
- if (e && f && (e->tail == f->tail) && (e->head == f->head) &&
- (ED_label(e) == ED_label(f)) && ports_eq(e, f))
- return TRUE;
- return FALSE;
-}
#include "dot.h"
-
-/* delete virtual nodes of a cluster, and install real nodes or sub-clusters */
-void expand_cluster(graph_t * subg)
-{
- /* build internal structure of the cluster */
- class2(subg);
- GD_comp(subg).size = 1;
- GD_comp(subg).list[0] = GD_nlist(subg);
- allocate_ranks(subg);
- build_ranks(subg, 0);
- merge_ranks(subg);
-
- /* build external structure of the cluster */
- interclexp(subg);
- remove_rankleaders(subg);
-}
-
-/* this function marks every node in <g> with its top-level cluster under <g> */
-void mark_clusters(graph_t * g)
-{
- int c;
- node_t *n, *vn;
- edge_t *orig, *e;
- graph_t *clust;
-
- /* remove sub-clusters below this level */
- for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
- if (ND_ranktype(n) == CLUSTER)
- UF_singleton(n);
- ND_clust(n) = NULL;
- }
-
- for (c = 1; c <= GD_n_cluster(g); c++) {
- clust = GD_clust(g)[c];
- for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
- if (ND_ranktype(n) != NORMAL) {
- agerr(AGWARN,
- "%s was already in a rankset, ignored in cluster %s\n",
- n->name, g->name);
- continue;
- }
- UF_setname(n, GD_leader(clust));
- ND_clust(n) = clust;
- ND_ranktype(n) = CLUSTER;
-
- /* here we mark the vnodes of edges in the cluster */
- for (orig = agfstout(clust, n); orig;
- orig = agnxtout(clust, orig)) {
- if ((e = ED_to_virt(orig))) {
- while (e && (vn = e->head)->u.node_type == VIRTUAL) {
- ND_clust(vn) = clust;
- e = ND_out(e->head).list[0];
- /* trouble if concentrators and clusters are mixed */
- }
- }
- }
- }
- }
-}
-
-void build_skeleton(graph_t * g, graph_t * subg)
+static node_t*
+map_interclust_node(node_t * n)
{
- int r;
- node_t *v, *prev, *rl;
- edge_t *e;
-
- prev = NULL;
- GD_rankleader(subg) = N_NEW(GD_maxrank(subg) + 2, node_t *);
- for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
- v = GD_rankleader(subg)[r] = virtual_node(g);
- ND_rank(v) = r;
- ND_ranktype(v) = CLUSTER;
- ND_clust(v) = subg;
- if (prev) {
- e = virtual_edge(prev, v, NULL);
- ED_xpenalty(e) *= CL_CROSS;
- }
- prev = v;
- }
-
- /* set the counts on virtual edges of the cluster skeleton */
- for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
- rl = GD_rankleader(subg)[ND_rank(v)];
- ND_UF_size(rl)++;
- for (e = agfstout(subg, v); e; e = agnxtout(subg, e)) {
- for (r = ND_rank(e->tail); r < ND_rank(e->head); r++) {
- ED_count(ND_out(rl).list[0])++;
- }
- }
- }
- for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
- rl = GD_rankleader(subg)[r];
- if (ND_UF_size(rl) > 1)
- ND_UF_size(rl)--;
- }
-}
-
-void merge_ranks(graph_t * subg)
-{
- int i, d, r, pos, ipos;
- node_t *v;
- graph_t *root;
+ node_t *rv;
- root = subg->root;
- if (GD_minrank(subg) > 0)
- ND_rank(root)[GD_minrank(subg) - 1].valid = FALSE;
- for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
- d = GD_rank(subg)[r].n;
- ipos = pos = GD_rankleader(subg)[r]->u.order;
- make_slots(root, r, pos, d);
- for (i = 0; i < GD_rank(subg)[r].n; i++) {
- v = ND_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i];
- ND_order(v) = pos++;
- v->graph = subg->root;
- delete_fast_node(subg, v);
- fast_node(subg->root, v);
- GD_n_nodes(subg->root)++;
- }
- GD_rank(subg)[r].v = ND_rank(root)[r].v + ipos;
- ND_rank(root)[r].valid = FALSE;
- }
- if (r < GD_maxrank(root))
- GD_rank(root)[r].valid = FALSE;
- GD_expanded(subg) = TRUE;
+ if ((ND_clust(n) == NULL) || (ND_clust(n)->u.expanded))
+ rv = n;
+ else
+ rv = ND_clust(n)->u.rankleader[ND_rank(n)];
+ return rv;
}
/* make d slots starting at position pos (where 1 already exists) */
-void make_slots(graph_t * root, int r, int pos, int d)
+static void
+make_slots(graph_t * root, int r, int pos, int d)
{
int i;
node_t *v, **vlist;
ND_rank(root)[r].n += d - 1;
}
-/*
- * attach and install edges between clusters.
- * essentially, class2() for interclust edges.
- */
-void interclexp(graph_t * subg)
-{
- graph_t *g;
- node_t *n;
- edge_t *e, *prev;
-
- g = subg->root;
- for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
-
- /* N.B. n may be in a sub-cluster of subg */
- prev = NULL;
- for (e = agfstedge(subg->root, n); e;
- e = agnxtedge(subg->root, e, n)) {
- if (agcontains(subg, e))
- continue;
-
- /* short/flat multi edges */
- if (mergeable(prev, e)) {
- if (ND_rank(e->tail) == ND_rank(e->head))
- ED_to_virt(e) = prev;
- else
- ED_to_virt(e) = NULL;
- if (ED_to_virt(prev) == NULL)
- continue; /* internal edge */
- merge_chain(subg, e, ED_to_virt(prev), FALSE);
- safe_other_edge(e);
- continue;
- }
-
- /* flat edges */
- if (ND_rank(e->tail) == ND_rank(e->head)) {
- if (find_flat_edge(e->tail, e->head) == NULL) {
- flat_edge(g, e);
- prev = e;
- } else
- prev = NULL;
- continue;
- }
-
- assert(ED_to_virt(e) != NULL);
-
- /* forward edges */
- if (ND_rank(e->head) > ND_rank(e->tail)) {
- make_interclust_chain(g, e->tail, e->head, e);
- prev = e;
- continue;
- }
-
- /* backward edges */
- else {
-/*
-I think that make_interclust_chain should create call other_edge(e) anyway
- if (agcontains(subg,e->tail)
- && agfindedge(subg->root,e->head,e->tail)) other_edge(e);
-*/
- make_interclust_chain(g, e->head, e->tail, e);
- prev = e;
- }
- }
- }
-}
-
-node_t *map_interclust_node(node_t * n)
-{
- node_t *rv;
-
- if ((ND_clust(n) == NULL) || (ND_clust(n)->u.expanded))
- rv = n;
- else
- rv = ND_clust(n)->u.rankleader[ND_rank(n)];
- return rv;
-}
-
-void make_interclust_chain(graph_t * g, node_t * from, node_t * to,
- edge_t * orig)
-{
- int newtype;
- node_t *u, *v;
-
- u = map_interclust_node(from);
- v = map_interclust_node(to);
- if ((u == from) && (v == to))
- newtype = VIRTUAL;
- else
- newtype = CLUSTER_EDGE;
- map_path(u, v, orig, ED_to_virt(orig), newtype);
-}
-
-node_t *clone_vn(graph_t * g, node_t * vn)
+static node_t*
+clone_vn(graph_t * g, node_t * vn)
{
node_t *rv;
int r;
return rv;
}
-void map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve,
- int type)
+static void
+map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve, int type)
{
int r;
node_t *u, *v;
}
}
-void install_cluster(graph_t * g, node_t * n, int pass, queue * q)
+static void
+make_interclust_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
{
- int r;
- graph_t *clust;
+ int newtype;
+ node_t *u, *v;
- clust = ND_clust(n);
- if (GD_installed(clust) != pass + 1) {
- for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
- install_in_rank(g, GD_rankleader(clust)[r]);
- for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
- enqueue_neighbors(q, GD_rankleader(clust)[r], pass);
- GD_installed(clust) = pass + 1;
+ u = map_interclust_node(from);
+ v = map_interclust_node(to);
+ if ((u == from) && (v == to))
+ newtype = VIRTUAL;
+ else
+ newtype = CLUSTER_EDGE;
+ map_path(u, v, orig, ED_to_virt(orig), newtype);
+}
+
+/*
+ * attach and install edges between clusters.
+ * essentially, class2() for interclust edges.
+ */
+void interclexp(graph_t * subg)
+{
+ graph_t *g;
+ node_t *n;
+ edge_t *e, *prev;
+
+ g = subg->root;
+ for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
+
+ /* N.B. n may be in a sub-cluster of subg */
+ prev = NULL;
+ for (e = agfstedge(subg->root, n); e;
+ e = agnxtedge(subg->root, e, n)) {
+ if (agcontains(subg, e))
+ continue;
+
+ /* short/flat multi edges */
+ if (mergeable(prev, e)) {
+ if (ND_rank(e->tail) == ND_rank(e->head))
+ ED_to_virt(e) = prev;
+ else
+ ED_to_virt(e) = NULL;
+ if (ED_to_virt(prev) == NULL)
+ continue; /* internal edge */
+ merge_chain(subg, e, ED_to_virt(prev), FALSE);
+ safe_other_edge(e);
+ continue;
+ }
+
+ /* flat edges */
+ if (ND_rank(e->tail) == ND_rank(e->head)) {
+ if (find_flat_edge(e->tail, e->head) == NULL) {
+ flat_edge(g, e);
+ prev = e;
+ } else
+ prev = NULL;
+ continue;
+ }
+
+ assert(ED_to_virt(e) != NULL);
+
+ /* forward edges */
+ if (ND_rank(e->head) > ND_rank(e->tail)) {
+ make_interclust_chain(g, e->tail, e->head, e);
+ prev = e;
+ continue;
+ }
+
+ /* backward edges */
+ else {
+/*
+I think that make_interclust_chain should create call other_edge(e) anyway
+ if (agcontains(subg,e->tail)
+ && agfindedge(subg->root,e->head,e->tail)) other_edge(e);
+*/
+ make_interclust_chain(g, e->head, e->tail, e);
+ prev = e;
+ }
+ }
}
}
-void remove_rankleaders(graph_t * g)
+static void
+merge_ranks(graph_t * subg)
+{
+ int i, d, r, pos, ipos;
+ node_t *v;
+ graph_t *root;
+
+ root = subg->root;
+ if (GD_minrank(subg) > 0)
+ ND_rank(root)[GD_minrank(subg) - 1].valid = FALSE;
+ for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
+ d = GD_rank(subg)[r].n;
+ ipos = pos = GD_rankleader(subg)[r]->u.order;
+ make_slots(root, r, pos, d);
+ for (i = 0; i < GD_rank(subg)[r].n; i++) {
+ v = ND_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i];
+ ND_order(v) = pos++;
+ v->graph = subg->root;
+ delete_fast_node(subg, v);
+ fast_node(subg->root, v);
+ GD_n_nodes(subg->root)++;
+ }
+ GD_rank(subg)[r].v = ND_rank(root)[r].v + ipos;
+ ND_rank(root)[r].valid = FALSE;
+ }
+ if (r < GD_maxrank(root))
+ GD_rank(root)[r].valid = FALSE;
+ GD_expanded(subg) = TRUE;
+}
+
+static void
+remove_rankleaders(graph_t * g)
{
int r;
node_t *v;
}
}
+/* delete virtual nodes of a cluster, and install real nodes or sub-clusters */
+void expand_cluster(graph_t * subg)
+{
+ /* build internal structure of the cluster */
+ class2(subg);
+ GD_comp(subg).size = 1;
+ GD_comp(subg).list[0] = GD_nlist(subg);
+ allocate_ranks(subg);
+ build_ranks(subg, 0);
+ merge_ranks(subg);
+
+ /* build external structure of the cluster */
+ interclexp(subg);
+ remove_rankleaders(subg);
+}
+
+/* this function marks every node in <g> with its top-level cluster under <g> */
+void mark_clusters(graph_t * g)
+{
+ int c;
+ node_t *n, *vn;
+ edge_t *orig, *e;
+ graph_t *clust;
+
+ /* remove sub-clusters below this level */
+ for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+ if (ND_ranktype(n) == CLUSTER)
+ UF_singleton(n);
+ ND_clust(n) = NULL;
+ }
+
+ for (c = 1; c <= GD_n_cluster(g); c++) {
+ clust = GD_clust(g)[c];
+ for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
+ if (ND_ranktype(n) != NORMAL) {
+ agerr(AGWARN,
+ "%s was already in a rankset, ignored in cluster %s\n",
+ n->name, g->name);
+ continue;
+ }
+ UF_setname(n, GD_leader(clust));
+ ND_clust(n) = clust;
+ ND_ranktype(n) = CLUSTER;
+
+ /* here we mark the vnodes of edges in the cluster */
+ for (orig = agfstout(clust, n); orig;
+ orig = agnxtout(clust, orig)) {
+ if ((e = ED_to_virt(orig))) {
+ while (e && (vn = e->head)->u.node_type == VIRTUAL) {
+ ND_clust(vn) = clust;
+ e = ND_out(e->head).list[0];
+ /* trouble if concentrators and clusters are mixed */
+ }
+ }
+ }
+ }
+ }
+}
+
+void build_skeleton(graph_t * g, graph_t * subg)
+{
+ int r;
+ node_t *v, *prev, *rl;
+ edge_t *e;
+
+ prev = NULL;
+ GD_rankleader(subg) = N_NEW(GD_maxrank(subg) + 2, node_t *);
+ for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
+ v = GD_rankleader(subg)[r] = virtual_node(g);
+ ND_rank(v) = r;
+ ND_ranktype(v) = CLUSTER;
+ ND_clust(v) = subg;
+ if (prev) {
+ e = virtual_edge(prev, v, NULL);
+ ED_xpenalty(e) *= CL_CROSS;
+ }
+ prev = v;
+ }
+
+ /* set the counts on virtual edges of the cluster skeleton */
+ for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
+ rl = GD_rankleader(subg)[ND_rank(v)];
+ ND_UF_size(rl)++;
+ for (e = agfstout(subg, v); e; e = agnxtout(subg, e)) {
+ for (r = ND_rank(e->tail); r < ND_rank(e->head); r++) {
+ ED_count(ND_out(rl).list[0])++;
+ }
+ }
+ }
+ for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
+ rl = GD_rankleader(subg)[r];
+ if (ND_UF_size(rl) > 1)
+ ND_UF_size(rl)--;
+ }
+}
+
+void install_cluster(graph_t * g, node_t * n, int pass, queue * q)
+{
+ int r;
+ graph_t *clust;
+
+ clust = ND_clust(n);
+ if (GD_installed(clust) != pass + 1) {
+ for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
+ install_in_rank(g, GD_rankleader(clust)[r]);
+ for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
+ enqueue_neighbors(q, GD_rankleader(clust)[r], pass);
+ GD_installed(clust) = pass + 1;
+ }
+}
+
static void mark_lowcluster_basic(Agraph_t * g);
void mark_lowclusters(Agraph_t * root)
{