/* To ensure that min and max rank nodes always have the intended rank * assignment, reverse any incompatible edges. */ static point minmax_edges(graph_t * g) { node_t *n; edge_t *e; point slen; slen.x = slen.y = 0; if ((GD_maxset(g) == NULL) && (GD_minset(g) == NULL)) return slen; if (GD_minset(g) != NULL) GD_minset(g) = UF_find(GD_minset(g)); if (GD_maxset(g) != NULL) GD_maxset(g) = UF_find(GD_maxset(g)); if ((n = GD_maxset(g))) { slen.y = (ND_ranktype(GD_maxset(g)) == SINKRANK); while ((e = ND_out(n).list[0])) { assert(aghead(e) == UF_find(aghead(e))); reverse_edge(e); } } if ((n = GD_minset(g))) { slen.x = (ND_ranktype(GD_minset(g)) == SOURCERANK); while ((e = ND_in(n).list[0])) { assert(agtail(e) == UF_find(agtail(e))); reverse_edge(e); } } return slen; }
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 } } }
node_t * UF_union(node_t *u, node_t *v) { if (u == v) return u; if (u->u.UF_parent == NULL) {u->u.UF_parent = u; u->u.UF_size = 1;} else u = UF_find(u); if (v->u.UF_parent == NULL) {v->u.UF_parent = v; v->u.UF_size = 1;} else v = UF_find(v); if (u->id > v->id) { u->u.UF_parent = v; v->u.UF_size += u->u.UF_size;} else {v->u.UF_parent = u; u->u.UF_size += v->u.UF_size; v = u;} return v; }
void UF_setname(node_t *u, node_t *v) { assert(u == UF_find(u)); u->u.UF_parent = v; v->u.UF_size += u->u.UF_size; }
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; }
node_t *UF_union(node_t * u, node_t * v) { if (u == v) return u; if (ND_UF_parent(u) == NULL) { ND_UF_parent(u) = u; ND_UF_size(u) = 1; } else u = UF_find(u); if (ND_UF_parent(v) == NULL) { ND_UF_parent(v) = v; ND_UF_size(v) = 1; } else v = UF_find(v); if (u->id > v->id) { ND_UF_parent(u) = v; ND_UF_size(v) += ND_UF_size(u); } else { ND_UF_parent(v) = u; ND_UF_size(u) += ND_UF_size(v); v = u; } return v; }
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); }
/* * Assigns ranks of non-leader nodes. * Expands same, min, max rank sets. * Leaf sets and clusters remain merged. * Sets minrank and maxrank appropriately. */ static void expand_ranksets(graph_t * g, aspect_t* asp) { int c; node_t *n, *leader; if ((n = agfstnode(g))) { GD_minrank(g) = MAXSHORT; GD_maxrank(g) = -1; while (n) { leader = UF_find(n); /* The following works because ND_rank(n) == 0 if n is not in a * cluster, and ND_rank(n) = the local rank offset if n is in * a cluster. */ if ((leader != n) && (!asp || (ND_rank(n) == 0))) ND_rank(n) += ND_rank(leader); 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 (ND_ranktype(n) && (ND_ranktype(n) != LEAFSET)) UF_singleton(n); n = agnxtnode(g, n); } if (g == dot_root(g)) { if (CL_type == LOCAL) { for (c = 1; c <= GD_n_cluster(g); c++) set_minmax(GD_clust(g)[c]); } else { find_clusters(g); } } } else { GD_minrank(g) = GD_maxrank(g) = 0; } }
void UF_setname(node_t * u, node_t * v) { assert(u == UF_find(u)); ND_UF_parent(u) = v; ND_UF_size(v) += ND_UF_size(u); }
void class2(graph_t* g) { int c; node_t *n,*t,*h; edge_t *e,*prev,*opp; g->u.nlist = NULL; g->u.n_nodes = 0; /* new */ mark_clusters(g); for (c = 1; c <= g->u.n_cluster; c++) build_skeleton(g,g->u.clust[c]); for (n = agfstnode(g); n; n = agnxtnode(g,n)) for (e = agfstout(g,n); e; e = agnxtout(g,e)) { if (e->head->u.weight_class <= 2) e->head->u.weight_class++; if (e->tail->u.weight_class <= 2) e->tail->u.weight_class++; } for (n = agfstnode(g); n; n = agnxtnode(g,n)) { if ((n->u.clust == NULL) && (n == UF_find(n))) {fast_node(g,n); g->u.n_nodes++;} prev = NULL; for (e = agfstout(g,n); e; e = agnxtout(g,e)) { /* already processed */ if (e->u.to_virt) continue; /* edges involving sub-clusters of g */ if (is_cluster_edge(e)) { /* following is new cluster multi-edge code */ if (mergeable(prev,e)) { if (prev->u.to_virt) { merge_chain(g,e,prev->u.to_virt,FALSE); other_edge(e); } else if (e->tail->u.rank == e->head->u.rank) { merge_oneway(e,prev); other_edge(e); } /* else is an intra-cluster edge */ continue; } interclrep(g,e); prev = e; continue; } /* merge multi-edges */ if (prev && (e->tail == prev->tail) && (e->head == prev->head)) { if (e->tail->u.rank == e->head->u.rank) { merge_oneway(e,prev); other_edge(e); continue; } if ((e->u.label == NULL) && (prev->u.label == NULL) && ports_eq(e,prev)) { if (Concentrate) e->u.edge_type = IGNORED; else{ merge_chain(g,e,prev->u.to_virt,TRUE); other_edge(e); } continue; } /* parallel edges with different labels fall through here */ } /* self edges */ if (e->tail == e->head) { other_edge(e); prev = e; continue; } t = UF_find(e->tail); h = UF_find(e->head); /* non-leader leaf nodes */ if ((e->tail != t) || (e->head != h)) { /* ### need to merge stuff */ continue; } /* flat edges */ if (e->tail->u.rank == e->head->u.rank) { flat_edge(g,e); prev = e; continue; } /* forward edges */ if (e->head->u.rank > e->tail->u.rank) { make_chain(g,e->tail,e->head,e); prev = e; continue; } /* backward edges */ else { /*other_edge(e);*/ if ((opp = agfindedge(g,e->head,e->tail))) { /* shadows a forward edge */ if (opp->u.to_virt == NULL) make_chain(g,opp->tail,opp->head,opp); if ((e->u.label == NULL) && (opp->u.label == NULL) && ports_eq(e,opp)) { if (Concentrate) { e->u.edge_type = IGNORED; opp->u.conc_opp_flag = TRUE; } else{ /* see above. this is getting out of hand */ other_edge(e); merge_chain(g,e,opp->u.to_virt,TRUE); } continue; } } make_chain(g,e->head,e->tail,e); prev = e; } } } /* since decompose() is not called on subgraphs */ if (g != g->root) { g->u.comp.list = ALLOC(1,g->u.comp.list,node_t*); g->u.comp.list[0] = g->u.nlist; }