static void set_minmax(graph_t * g) { int c; GD_minrank(g) += ND_rank(GD_leader(g)); GD_maxrank(g) += ND_rank(GD_leader(g)); for (c = 1; c <= GD_n_cluster(g); c++) set_minmax(GD_clust(g)[c]); }
int nonconstraint_edge(edge_t * e) { char *constr; #ifndef WITH_CGRAPH if (E_constr && (constr = agxget(e, E_constr->index))) { #else /* WITH_CGRAPH */ if (E_constr && (constr = agxget(e, E_constr))) { #endif /* WITH_CGRAPH */ if (constr[0] && mapbool(constr) == FALSE) return TRUE; } return FALSE; } static void interclust1(graph_t * g, node_t * t, node_t * h, edge_t * e) { node_t *v, *t0, *h0; int offset, t_len, h_len, t_rank, h_rank; edge_t *rt, *rh; if (ND_clust(agtail(e))) t_rank = ND_rank(agtail(e)) - ND_rank(GD_leader(ND_clust(agtail(e)))); else t_rank = 0; if (ND_clust(aghead(e))) h_rank = ND_rank(aghead(e)) - ND_rank(GD_leader(ND_clust(aghead(e)))); else h_rank = 0; offset = ED_minlen(e) + t_rank - h_rank; if (offset > 0) { t_len = 0; h_len = offset; } else { t_len = -offset; h_len = 0; } v = virtual_node(g); ND_node_type(v) = SLACKNODE; t0 = UF_find(t); h0 = UF_find(h); rt = make_aux_edge(v, t0, t_len, CL_BACK * ED_weight(e)); rh = make_aux_edge(v, h0, h_len, ED_weight(e)); ED_to_orig(rt) = ED_to_orig(rh) = e; }
void dot_scan_ranks(graph_t * g) { node_t *n, *leader = NULL; GD_minrank(g) = MAXSHORT; GD_maxrank(g) = -1; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (GD_maxrank(g) < ND_rank(n)) GD_maxrank(g) = ND_rank(n); if (GD_minrank(g) > ND_rank(n)) GD_minrank(g) = ND_rank(n); if (leader == NULL) leader = n; else { if (ND_rank(n) < ND_rank(leader)) leader = n; } } GD_leader(g) = leader; }
static void cluster_leader(graph_t * clust) { node_t *leader, *n; int maxrank = 0; /* find number of ranks and select a leader */ leader = NULL; for (n = GD_nlist(clust); n; n = ND_next(n)) { if ((ND_rank(n) == 0) && (ND_node_type(n) == NORMAL)) leader = n; if (maxrank < ND_rank(n)) maxrank = ND_rank(n); } assert(leader != NULL); GD_leader(clust) = leader; for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) { assert((ND_UF_size(n) <= 1) || (n == leader)); UF_union(n, leader); ND_ranktype(n) = CLUSTER; } }
/* 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)--; } }
/* Execute union commands for "same rank" subgraphs and clusters. */ static void collapse_sets(graph_t *rg, graph_t *g) { int c; graph_t *subg; #ifdef OBSOLETE node_t *n; #endif #ifndef WITH_CGRAPH graph_t *mg; node_t *mn; edge_t *me; mg = g->meta_node->graph; for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) { mn = aghead(me); subg = agusergraph(mn); #else /* WITH_CGRAPH */ for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) { #endif /* WITH_CGRAPH */ c = rank_set_class(subg); if (c) { if ((c == CLUSTER) && CL_type == LOCAL) collapse_cluster(rg, subg); else collapse_rankset(rg, subg, c); } else collapse_sets(rg, subg); #ifdef OBSOLETE Collapsing leaves is currently obsolete /* mark nodes with ordered edges so their leaves are not collapsed */ if (agget(subg, "ordering")) for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) ND_order(n) = 1; #endif } } static void find_clusters(graph_t * g) { graph_t *subg; #ifndef WITH_CGRAPH graph_t *mg; node_t *mn; edge_t *me; mg = g->meta_node->graph; for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) { mn = me->head; subg = agusergraph(mn); #else /* WITH_CGRAPH */ for (subg = agfstsubg(agroot(g)); subg; subg = agnxtsubg(subg)) { #endif /* WITH_CGRAPH */ if (GD_set_type(subg) == CLUSTER) collapse_cluster(g, subg); } } static void set_minmax(graph_t * g) { int c; GD_minrank(g) += ND_rank(GD_leader(g)); GD_maxrank(g) += ND_rank(GD_leader(g)); for (c = 1; c <= GD_n_cluster(g); c++) set_minmax(GD_clust(g)[c]); }