static void dot_cleanup_graph(graph_t * g) { int i, c; graph_t *clust; for (c = 1; c <= GD_n_cluster(g); c++) { clust = GD_clust(g)[c]; GD_cluster_was_collapsed(clust) = FALSE; dot_cleanup(clust); } if (GD_clust(g)) free (GD_clust(g)); if (GD_rankleader(g)) free (GD_rankleader(g)); free_list(GD_comp(g)); if (GD_rank(g)) { for (i = GD_minrank(g); i <= GD_maxrank(g); i++) free(GD_rank(g)[i].av); if (GD_minrank(g) == -1) free(GD_rank(g)-1); else free(GD_rank(g)); } if (g != agroot(g)) #ifndef WITH_CGRAPH memset(&(g->u), 0, sizeof(Agraphinfo_t)); #else /* WITH_CGRAPH */ agclean(g,AGRAPH,"Agraphinfo_t"); #endif /* WITH_CGRAPH */ }
static void infuse(graph_t * g, node_t * n) { node_t *lead; lead = GD_rankleader(g)[ND_rank(n)]; if ((lead == NULL) || (ND_order(lead) > ND_order(n))) GD_rankleader(g)[ND_rank(n)] = n; }
static void rebuild_vlists(graph_t * g) { int c, i, r, maxi; node_t *n, *lead; edge_t *e, *rep; for (r = GD_minrank(g); r <= GD_maxrank(g); r++) GD_rankleader(g)[r] = NULL; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { infuse(g, n); for (e = agfstout(g, n); e; e = agnxtout(g, e)) { for (rep = e; ED_to_virt(rep); rep = ED_to_virt(rep)); while (ND_rank(rep->head) < ND_rank(e->head)) { infuse(g, rep->head); rep = ND_out(rep->head).list[0]; } } } for (r = GD_minrank(g); r <= GD_maxrank(g); r++) { lead = GD_rankleader(g)[r]; if (ND_rank(g->root)[r].v[ND_order(lead)] != lead) abort(); GD_rank(g)[r].v = ND_rank(g->root)[r].v + GD_rankleader(g)[r]->u.order; maxi = -1; for (i = 0; i < GD_rank(g)[r].n; i++) { if ((n = GD_rank(g)[r].v[i]) == NULL) break; if (ND_node_type(n) == NORMAL) { if (agcontains(g, n)) maxi = i; else break; } else { edge_t *e; for (e = ND_in(n).list[0]; e && ED_to_orig(e); e = ED_to_orig(e)); if (e && (agcontains(g, e->tail)) && agcontains(g, e->head)) maxi = i; } } if (maxi == -1) agerr(AGWARN, "degenerate concentrated rank %s,%d\n", g->name, r); GD_rank(g)[r].n = maxi + 1; } for (c = 1; c <= GD_n_cluster(g); c++) rebuild_vlists(GD_clust(g)[c]); }
static void merge_ranks(graph_t * subg) { int i, d, r, pos, ipos; node_t *v; graph_t *root; root = agroot(subg); if (GD_minrank(subg) > 0) #ifndef WITH_CGRAPH ND_rank(root)[GD_minrank(subg) - 1].valid = FALSE; #else /* WITH_CGRAPH */ GD_rank(root)[GD_minrank(subg) - 1].valid = FALSE; #endif /* WITH_CGRAPH */ for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) { d = GD_rank(subg)[r].n; #ifndef WITH_CGRAPH ipos = pos = GD_rankleader(subg)[r]->u.order; #else /* WITH_CGRAPH */ ipos = pos = ND_order(GD_rankleader(subg)[r]); #endif /* WITH_CGRAPH */ make_slots(root, r, pos, d); for (i = 0; i < GD_rank(subg)[r].n; i++) { #ifndef WITH_CGRAPH v = ND_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i]; #else /* WITH_CGRAPH */ v = GD_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i]; #endif /* WITH_CGRAPH */ ND_order(v) = pos++; #ifndef WITH_CGRAPH v->graph = subg->root; #else /* WITH_CGRAPH */ /* real nodes automatically have v->root = root graph */ if (ND_node_type(v) == VIRTUAL) v->root = root; #endif /* WITH_CGRAPH */ delete_fast_node(subg, v); fast_node(agroot(subg), v); GD_n_nodes(agroot(subg))++; } #ifndef WITH_CGRAPH GD_rank(subg)[r].v = ND_rank(root)[r].v + ipos; ND_rank(root)[r].valid = FALSE; #else /* WITH_CGRAPH */ GD_rank(subg)[r].v = GD_rank(root)[r].v + ipos; GD_rank(root)[r].valid = FALSE; #endif /* WITH_CGRAPH */ } if (r < GD_maxrank(root)) GD_rank(root)[r].valid = FALSE; GD_expanded(subg) = TRUE; }
void install_cluster(graph_t * g, node_t * n, int pass, nodequeue * 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 remove_rankleaders(graph_t * g) { int r; node_t *v; edge_t *e; for (r = GD_minrank(g); r <= GD_maxrank(g); r++) { v = GD_rankleader(g)[r]; /* remove the entire chain */ while ((e = ND_out(v).list[0])) delete_fast_edge(e); while ((e = ND_in(v).list[0])) delete_fast_edge(e); delete_fast_node(agroot(g), v); GD_rankleader(g)[r] = NULL; } }
static void dot_cleanup_graph(graph_t * g) { int i; graph_t *subg; for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) { dot_cleanup_graph(subg); } if (GD_clust(g)) free (GD_clust(g)); if (GD_rankleader(g)) free (GD_rankleader(g)); free_list(GD_comp(g)); if (GD_rank(g)) { for (i = GD_minrank(g); i <= GD_maxrank(g); i++) free(GD_rank(g)[i].av); if (GD_minrank(g) == -1) free(GD_rank(g)-1); else free(GD_rank(g)); } if (g != agroot(g)) agdelrec(g,"Agraphinfo_t"); }
static node_t* map_interclust_node(node_t * n) { node_t *rv; #ifndef WITH_CGRAPH if ((ND_clust(n) == NULL) || (ND_clust(n)->u.expanded)) #else /* WITH_CGRAPH */ if ((ND_clust(n) == NULL) || ( GD_expanded(ND_clust(n))) ) #endif /* WITH_CGRAPH */ rv = n; else #ifndef WITH_CGRAPH rv = ND_clust(n)->u.rankleader[ND_rank(n)]; #else /* WITH_CGRAPH */ rv = GD_rankleader(ND_clust(n))[ND_rank(n)]; #endif /* WITH_CGRAPH */ return rv; }
/* 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, *nn, *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 = nn) { nn = agnxtnode(clust,n); if (ND_ranktype(n) != NORMAL) { agerr(AGWARN, "%s was already in a rankset, deleted from cluster %s\n", agnameof(n), agnameof(g)); agdelete(clust,n); 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))) { #ifndef WITH_CGRAPH while (e && (vn = e->head)->u.node_type == VIRTUAL) { #else /* WITH_CGRAPH */ while (e && ND_node_type(vn =aghead(e)) == VIRTUAL) { #endif /* WITH_CGRAPH */ ND_clust(vn) = clust; e = ND_out(aghead(e)).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(agtail(e)); r < ND_rank(aghead(e)); 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)--; } }