void class1(graph_t * g) { node_t *n, *t, *h; edge_t *e, *rep; mark_clusters(g); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { /* skip edges already processed */ if (ED_to_virt(e)) continue; /* skip edges that we want to ignore in this phase */ if (nonconstraint_edge(e)) continue; t = UF_find(agtail(e)); h = UF_find(aghead(e)); /* skip self, flat, and intra-cluster edges */ if (t == h) continue; /* inter-cluster edges require special treatment */ if (ND_clust(t) || ND_clust(h)) { interclust1(g, agtail(e), aghead(e), e); continue; } if ((rep = find_fast_edge(t, h))) merge_oneway(e, rep); else virtual_edge(t, h, e); #ifdef NOTDEF if ((t == agtail(e)) && (h == aghead(e))) { if (rep = find_fast_edge(t, h)) merge_oneway(e, rep); else virtual_edge(t, h, e); } else { f = agfindedge(g, t, h); if (f && (ED_to_virt(f) == NULL)) rep = virtual_edge(t, h, f); else rep = find_fast_edge(t, h); if (rep) merge_oneway(e, rep); else virtual_edge(t, h, e); } #endif } } }
static void mergevirtual(graph_t * g, int r, int lpos, int rpos, int dir) { int i, k; node_t *left, *right; edge_t *e, *f, *e0; left = GD_rank(g)[r].v[lpos]; /* merge all right nodes into the leftmost one */ for (i = lpos + 1; i <= rpos; i++) { right = GD_rank(g)[r].v[i]; if (dir == DOWN) { while ((e = ND_out(right).list[0])) { for (k = 0; (f = ND_out(left).list[k]); k++) if (f->head == e->head) break; if (f == NULL) f = virtual_edge(left, e->head, e); while ((e0 = ND_in(right).list[0])) { merge_oneway(e0, f); /*ED_weight(f) += ED_weight(e0); */ delete_fast_edge(e0); } delete_fast_edge(e); } } else { while ((e = ND_in(right).list[0])) { for (k = 0; (f = ND_in(left).list[k]); k++) if (f->tail == e->tail) break; if (f == NULL) f = virtual_edge(e->tail, left, e); while ((e0 = ND_out(right).list[0])) { merge_oneway(e0, f); delete_fast_edge(e0); } delete_fast_edge(e); } } assert(ND_in(right).size + ND_out(right).size == 0); delete_fast_node(g, right); } k = lpos + 1; i = rpos + 1; while (i < GD_rank(g)[r].n) { node_t *n; n = GD_rank(g)[r].v[k] = GD_rank(g)[r].v[i]; ND_order(n) = k; k++; i++; } GD_rank(g)[r].n = k; GD_rank(g)[r].v[k] = NULL; }
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--; } }
static int minmax_edges2(graph_t * g, point slen) { node_t *n; edge_t *e = 0; if ((GD_maxset(g)) || (GD_minset(g))) { for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (n != UF_find(n)) continue; if ((ND_out(n).size == 0) && GD_maxset(g) && (n != GD_maxset(g))) { e = virtual_edge(n, GD_maxset(g), NULL); ED_minlen(e) = slen.y; } if ((ND_in(n).size == 0) && GD_minset(g) && (n != GD_minset(g))) { e = virtual_edge(GD_minset(g), n, NULL); ED_minlen(e) = slen.x; } } } return (e != 0); }
static void restoreVirtualEdges(graph_t *g) { int i; edge_t e; for (i = 0; i < nVirtualEdges; i++) { if (virtualEdgeTailList[i] && virtualEdgeHeadList[i]) { if (Verbose) printf("restoring virtual edge: %s->%s\n", virtualEdgeTailList[i]->name, virtualEdgeHeadList[i]->name); virtual_edge(virtualEdgeTailList[i], virtualEdgeHeadList[i], NULL); } } if (Verbose) printf("restored %d virt edges\n", nVirtualEdges); }
/* 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)--; } }
static void map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve, int type) { int r; node_t *u, *v; edge_t *e; assert(ND_rank(from) < ND_rank(to)); if ((agtail(ve) == from) && (aghead(ve) == to)) return; if (ED_count(ve) > 1) { ED_to_virt(orig) = NULL; if (ND_rank(to) - ND_rank(from) == 1) { if ((e = find_fast_edge(from, to)) && (ports_eq(orig, e))) { merge_oneway(orig, e); if ((ND_node_type(from) == NORMAL) && (ND_node_type(to) == NORMAL)) other_edge(orig); return; } } u = from; for (r = ND_rank(from); r < ND_rank(to); r++) { if (r < ND_rank(to) - 1) v = clone_vn(agraphof(from), aghead(ve)); else v = to; e = virtual_edge(u, v, orig); ED_edge_type(e) = type; u = v; ED_count(ve)--; ve = ND_out(aghead(ve)).list[0]; } } else { if (ND_rank(to) - ND_rank(from) == 1) { if ((ve = find_fast_edge(from, to)) && (ports_eq(orig, ve))) { /*ED_to_orig(ve) = orig; */ ED_to_virt(orig) = ve; ED_edge_type(ve) = type; ED_count(ve)++; if ((ND_node_type(from) == NORMAL) && (ND_node_type(to) == NORMAL)) other_edge(orig); } else { ED_to_virt(orig) = NULL; ve = virtual_edge(from, to, orig); ED_edge_type(ve) = type; } } if (ND_rank(to) - ND_rank(from) > 1) { e = ve; if (agtail(ve) != from) { ED_to_virt(orig) = NULL; e = ED_to_virt(orig) = virtual_edge(from, aghead(ve), orig); delete_fast_edge(ve); } else e = ve; while (ND_rank(aghead(e)) != ND_rank(to)) e = ND_out(aghead(e)).list[0]; if (aghead(e) != to) { ve = e; e = virtual_edge(agtail(e), to, orig); ED_edge_type(e) = type; delete_fast_edge(ve); } } } }
void map_path(node_t *from, node_t *to, edge_t *orig, edge_t *ve, int type) { int r; node_t *u,*v; edge_t *e; assert(from->u.rank < to->u.rank); if ((ve->tail == from) && (ve->head == to)) return; if (ve->u.count > 1) { orig->u.to_virt = NULL; if (to->u.rank - from->u.rank == 1) { if ((e = find_fast_edge(from,to)) && (ports_eq(orig,e))) { merge_oneway(orig,e); if ((from->u.node_type == NORMAL) && (to->u.node_type == NORMAL)) other_edge(orig); return; } } u = from; for (r = from->u.rank; r < to->u.rank; r++) { if (r < to->u.rank - 1) v = clone_vn(from->graph,ve->head); else v = to; e = virtual_edge(u,v,orig); e->u.edge_type = type; u = v; ve->u.count--; ve = ve->head->u.out.list[0]; } } else { if (to->u.rank - from->u.rank == 1) { if ((ve = find_fast_edge(from,to)) && (ports_eq(orig,ve))) { /*ve->u.to_orig = orig;*/ orig->u.to_virt = ve; ve->u.edge_type = type; ve->u.count++; if ((from->u.node_type == NORMAL) && (to->u.node_type == NORMAL)) other_edge(orig); } else { orig->u.to_virt = NULL; ve = virtual_edge(from,to,orig); ve->u.edge_type = type; } } if (to->u.rank - from->u.rank > 1) { e = ve; if (ve->tail != from) { orig->u.to_virt = NULL; e = orig->u.to_virt = virtual_edge(from,ve->head,orig); delete_fast_edge(ve); } else e = ve; while (e->head->u.rank != to->u.rank) e = e->head->u.out.list[0]; if (e->head != to) { ve = e; e = virtual_edge(e->tail,to,orig); e->u.edge_type = type; delete_fast_edge(ve); } } } }