void build_skeleton(graph_t *g, graph_t *subg) { int r; node_t *v,*prev,*rl; edge_t *e; prev = NULL; subg->u.rankleader = N_NEW(subg->u.maxrank + 2,node_t*); for (r = subg->u.minrank; r <= subg->u.maxrank; r++) { v = subg->u.rankleader[r] = virtual_node(g); v->u.rank = r; v->u.ranktype = CLUSTER; v->u.clust = subg; if (prev) { e = virtual_edge(prev,v,NULL); e->u.xpenalty *= CL_CROSS; } prev = v; } /* set the counts on virtual edges of the cluster skeleton */ for (v = agfstnode(subg); v; v = agnxtnode(subg,v)) { rl = subg->u.rankleader[v->u.rank]; rl->u.UF_size++; for (e = agfstout(subg,v); e; e = agnxtout(subg,e)) { for (r = e->tail->u.rank; r < e->head->u.rank; r++) { rl->u.out.list[0]->u.count++; } } } for (r = subg->u.minrank; r <= subg->u.maxrank; r++) { rl = subg->u.rankleader[r]; if (rl->u.UF_size > 1) rl->u.UF_size--; } }
node_t * clone_vn(graph_t* g, node_t* vn) { node_t *rv; int r; r = vn->u.rank; make_slots(g,r,vn->u.order,2); rv = virtual_node(g); rv->u.lw = vn->u.lw; rv->u.rw = vn->u.rw; rv->u.rank = vn->u.rank; rv->u.order = vn->u.order + 1; g->u.rank[r].v[rv->u.order] = rv; return rv; }
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 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 (e->tail->u.clust) t_rank = e->tail->u.rank - e->tail->u.clust->u.leader->u.rank; else t_rank = 0; if (e->head->u.clust) h_rank = e->head->u.rank - e->head->u.clust->u.leader->u.rank; else h_rank = 0; offset = e->u.minlen + t_rank - h_rank; if (offset > 0) {t_len = 0; h_len = offset;} else {t_len = -offset; h_len = 0;} v = virtual_node(g); v->u.node_type = SLACKNODE; t0 = UF_find(t); h0 = UF_find(h); rt = make_aux_edge(v,t0,t_len,CL_BACK*e->u.weight); rh = make_aux_edge(v,h0,h_len,e->u.weight); rt->u.to_orig = rh->u.to_orig = e; }
/* make d slots starting at position pos (where 1 already exists) */ static void make_slots(graph_t * root, int r, int pos, int d) { int i; node_t *v, **vlist; #ifndef WITH_CGRAPH vlist = ND_rank(root)[r].v; #else /* WITH_CGRAPH */ vlist = GD_rank(root)[r].v; #endif /* WITH_CGRAPH */ if (d <= 0) { #ifndef WITH_CGRAPH for (i = pos - d + 1; i < ND_rank(root)[r].n; i++) { #else /* WITH_CGRAPH */ for (i = pos - d + 1; i < GD_rank(root)[r].n; i++) { #endif /* WITH_CGRAPH */ v = vlist[i]; ND_order(v) = i + d - 1; vlist[ND_order(v)] = v; } #ifndef WITH_CGRAPH for (i = ND_rank(root)[r].n + d - 1; i < ND_rank(root)[r].n; i++) #else /* WITH_CGRAPH */ for (i = GD_rank(root)[r].n + d - 1; i < GD_rank(root)[r].n; i++) #endif /* WITH_CGRAPH */ vlist[i] = NULL; } else { /*assert(ND_rank(root)[r].n + d - 1 <= ND_rank(root)[r].an);*/ #ifndef WITH_CGRAPH for (i = ND_rank(root)[r].n - 1; i > pos; i--) { #else /* WITH_CGRAPH */ for (i = GD_rank(root)[r].n - 1; i > pos; i--) { #endif /* WITH_CGRAPH */ v = vlist[i]; ND_order(v) = i + d - 1; vlist[ND_order(v)] = v; } for (i = pos + 1; i < pos + d; i++) vlist[i] = NULL; } #ifndef WITH_CGRAPH ND_rank(root)[r].n += d - 1; #else /* WITH_CGRAPH */ GD_rank(root)[r].n += d - 1; #endif /* WITH_CGRAPH */ } static node_t* clone_vn(graph_t * g, node_t * vn) { node_t *rv; int r; r = ND_rank(vn); make_slots(g, r, ND_order(vn), 2); rv = virtual_node(g); ND_lw(rv) = ND_lw(vn); ND_rw(rv) = ND_rw(vn); ND_rank(rv) = ND_rank(vn); ND_order(rv) = ND_order(vn) + 1; GD_rank(g)[r].v[ND_order(rv)] = rv; 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)--; } }