static void dot_init_node(node_t * n) { common_init_node(n); dot_nodesize(n, GD_flip(n->graph)); alloc_elist(4, ND_in(n)); alloc_elist(4, ND_out(n)); alloc_elist(2, ND_flat_in(n)); alloc_elist(2, ND_flat_out(n)); alloc_elist(2, ND_other(n)); ND_UF_size(n) = 1; }
static void dot_init_node(node_t * n) { agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //graph custom data common_init_node(n); gv_nodesize(n, GD_flip(agraphof(n))); alloc_elist(4, ND_in(n)); alloc_elist(4, ND_out(n)); alloc_elist(2, ND_flat_in(n)); alloc_elist(2, ND_flat_out(n)); alloc_elist(2, ND_other(n)); ND_UF_size(n) = 1; }
node_t *virtual_node(graph_t * g) { node_t *n; n = NEW(node_t); n->name = "virtual"; n->graph = g; ND_node_type(n) = VIRTUAL; ND_lw_i(n) = ND_rw_i(n) = 1; ND_ht_i(n) = 1; ND_UF_size(n) = 1; alloc_elist(4, ND_in(n)); alloc_elist(4, ND_out(n)); fast_node(g, n); GD_n_nodes(g)++; return n; }
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; } }
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; }
/* 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)--; } }
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 UF_singleton(node_t * u) { ND_UF_size(u) = 1; ND_UF_parent(u) = NULL; ND_ranktype(u) = NORMAL; }
void UF_remove(node_t * u, node_t * v) { assert(ND_UF_size(u) == 1); ND_UF_parent(u) = u; ND_UF_size(v) -= ND_UF_size(u); }