static void cloneSubg (Agraph_t* parent, Agraph_t* sg, Dt_t* emap) { Agraph_t* subg; Agnode_t* t; Agedge_t* e; Agnode_t* newt; Agedge_t* newe; Agraph_t* newg; if (is_a_cluster(sg)) { newg = agsubg (parent, agnameof(sg), 1); parent = newg; for (t = agfstnode(sg); t; t = agnxtnode(sg, t)) { newt = agnode(newg, agnameof(t), 0); agsubnode(newg, newt, 1); /* if e is in sg, both end points are, so we can use out edges */ for (e = agfstout(sg, t); e; e = agnxtout(sg, e)) { newe = mapEdge (emap, e); agsubedge(newg, newe, 1); } } } for (subg = agfstsubg(sg); subg; subg = agnxtsubg(subg)) { cloneSubg(parent, subg, emap); } }
/* spanning_tree: * Construct spanning forest of g as subgraph */ static Agraph_t *spanning_tree(Agraph_t * g) { Agnode_t *n; Agraph_t *tree; char gname[SMALLBUF]; static int id = 0; sprintf(gname, "_span_%d", id++); tree = agsubg(g, gname); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { aginsert(tree, n); DISTONE(n) = 0; DISTTWO(n) = 0; UNSET_VISITED(n); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (!VISITED(n)) { TPARENT(n) = NULL; dfs(g, n, tree); } } return tree; }
static graph_t *create_test_graph(void) { #define NUMNODES 5 Agnode_t *node[NUMNODES]; Agedge_t *e; Agraph_t *g; Agraph_t *sg; int j, k; char name[10]; /* Create a new graph */ g = agopen("new_graph", Agdirected,NIL(Agdisc_t *)); /* Add nodes */ for (j = 0; j < NUMNODES; j++) { sprintf(name, "%d", j); node[j] = agnode(g, name, 1); agbindrec(node[j], "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data } /* Connect nodes */ for (j = 0; j < NUMNODES; j++) { for (k = j + 1; k < NUMNODES; k++) { e = agedge(g, node[j], node[k], NULL, 1); agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); //edge custom data } } sg = agsubg (g, "cluster1", 1); agsubnode (sg, node[0], 1); return g; }
/* processClusterEdges: * Look for cluster edges. Replace cluster edge endpoints * corresponding to a cluster with special cluster nodes. * Delete original nodes. * Return 0 if no cluster edges; 1 otherwise. */ int processClusterEdges(graph_t * g) { int rv; node_t *n; edge_t *e; graph_t *clg; agxbuf xb; Dt_t *map; unsigned char buf[SMALLBUF]; map = dtopen(&mapDisc, Dtoset); clg = agsubg(g, "__clusternodes"); agxbinit(&xb, SMALLBUF, buf); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { checkCompound(e, clg, &xb, map); } } agxbfree(&xb); dtclose(map); rv = agnnodes(clg); for (n = agfstnode(clg); n; n = agnxtnode(clg, n)) { agdelete(g, n); } agclose(clg); if (rv) SET_CLUST_EDGE(g); return rv; }
/* processClusterEdges: * Look for cluster edges. Replace cluster edge endpoints * corresponding to a cluster with special cluster nodes. * Delete original nodes. * Return 0 if no cluster edges; 1 otherwise. */ int processClusterEdges(graph_t * g) { int rv; node_t *n; node_t *nxt; edge_t *e; graph_t *clg; agxbuf xb; Dt_t *map; Dt_t *cmap = mkClustMap (g); unsigned char buf[SMALLBUF]; map = dtopen(&mapDisc, Dtoset); clg = agsubg(g, "__clusternodes",1); agbindrec(clg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); agxbinit(&xb, SMALLBUF, buf); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (IS_CLUST_NODE(n)) continue; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { checkCompound(e, clg, &xb, map, cmap); } } agxbfree(&xb); dtclose(map); rv = agnnodes(clg); for (n = agfstnode(clg); n; n = nxt) { nxt = agnxtnode(clg, n); agdelete(g, n); } agclose(clg); if (rv) SET_CLUST_EDGE(g); dtclose(cmap); return rv; }
QGVSubGraph *QGVSubGraph::addSubGraph(const QString &name, bool cluster) { Agraph_t *sgraph; if (cluster) sgraph = agsubg(_sgraph->graph(), ("cluster_" + name).toLocal8Bit().data(), TRUE); else sgraph = agsubg(_sgraph->graph(), name.toLocal8Bit().data(), TRUE); if (sgraph == NULL) { qWarning() << "Invalid subGraph :" << name; return 0; } QGVSubGraph *item = new QGVSubGraph(new QGVGraphPrivate(sgraph), _scene); _scene->_subGraphs.append(item); _scene->addItem(item); return item; }
static Agraph_t *makeBlockGraph(Agraph_t * g, circ_state * state) { char name[SMALLBUF]; Agraph_t *subg; sprintf(name, "_block_%d", state->blockCount++); subg = agsubg(g, name); return subg; }
static void anonsubg(void) { char buf[SMALLBUF]; Agraph_t *subg; In_decl = FALSE; anonname(buf); subg = agsubg(G,buf); push_subg(subg); }
/* clone_graph: * Create two copies of the argument graph * One is a subgraph, the other is an actual copy since we will be * adding edges to it. */ static Agraph_t* clone_graph(Agraph_t* ing, Agraph_t** xg) { Agraph_t* clone; Agraph_t* xclone; Agnode_t* n; Agnode_t* xn; Agnode_t* xh; Agedge_t* e; Agedge_t* xe; char gname[SMALLBUF]; static int id = 0; sprintf (gname, "_clone_%d", id++); clone = agsubg(ing, gname); sprintf (gname, "_clone_%d", id++); xclone = agopen(gname, ing->kind); for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) { aginsert (clone, n); xn = agnode (xclone, n->name); CLONE(n) = xn; } for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) { xn = CLONE(n); for(e = agfstout(ing, n); e; e = agnxtout(ing, e)) { aginsert (clone, e); xh = CLONE(e->head); xe = agedge (xclone, xn, xh); ORIGE(xe) = e; DEGREE(xn) += 1; DEGREE(xh) += 1; } } *xg = xclone; #ifdef OLD clone = agopen("clone", root->kind); for(n = agfstnode(root); n; n = agnxtnode(root, n)) { cn = agnode(clone, n->name); ND_alg(cn) = DATA(n); BCDONE(cn) = 0; } for(n = agfstnode(root); n; n = agnxtnode(root, n)) { Agnode_t *t = agnode(clone, n); for(e = agfstout(root, n); e; e = agnxtout(root, e)) { Agnode_t *h = agnode(clone, e->head->name); agedge(clone, t, h); } } #endif return clone; }
static Agraph_t *mkBlock(Agraph_t * g, bcstate * stp) { Agraph_t *sg; stp->nComp++; sg = agsubg(g, blockName(agnameof(g), stp->nComp), 1); agbindrec(sg, "info", sizeof(Agraphinfo_t), TRUE); NEXTBLK(sg) = stp->blks; stp->blks = sg; return sg; }
static void anonsubg(void) { static int anon_id = 0; char buf[SMALLBUF]; Agraph_t *subg; In_decl = FALSE; sprintf(buf,"_anonymous_%d",anon_id++); subg = agsubg(G,buf); push_subg(subg); }
/* undoClusterEdges: * Replace cluster nodes with originals. Make sure original has * no attributes. Replace original edges. Delete cluster nodes, * which will also delete cluster edges. */ void undoClusterEdges(graph_t * g) { node_t *n; edge_t *e; graph_t *clg; clg = agsubg(g, "__clusternodes"); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { undoCompound(e, clg); } } for (n = agfstnode(clg); n; n = agnxtnode(clg, n)) { agdelete(g, n); } agclose(clg); }
/* removeFill: * This removes all of the fill nodes added in mincross. * It appears to be sufficient to remove them only from the * rank array and fast node list of the root graph. */ static void removeFill (Agraph_t * g) { Agnode_t* n; Agnode_t* nxt; Agraph_t* sg = agsubg (g, "_new_rank", 0); if (!sg) return; for (n = agfstnode(sg); n; n = nxt) { nxt = agnxtnode(sg, n); delete_fast_node (g, n); remove_from_rank (g, n); dot_cleanup_node (n); agdelnode(g, n); } agdelsubg (g, sg); }
/* undoClusterEdges: * Replace cluster nodes with originals. Make sure original has * no attributes. Replace original edges. Delete cluster nodes, * which will also delete cluster edges. */ void undoClusterEdges(graph_t * g) { node_t *n; edge_t *e; graph_t *clg; clg = agsubg(g, "__clusternodes",1); agbindrec(clg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { undoCompound(e, clg); } } for (n = agfstnode(clg); n; n = agnxtnode(clg, n)) { agdelete(g, n); } agclose(clg); }
static int visit(Agnode_t *n, Agraph_t* map, Stack* sp, sccstate* st) { unsigned int m,min; Agnode_t* t; Agraph_t* subg; Agedge_t* e; min = ++(st->ID); setval(n,min); push (sp, n); for (e = agfstout(n); e; e = agnxtout(e)) { t = aghead(e); if (getval(t) == 0) m = visit(t,map,sp,st); else m = getval(t); if (m < min) min = m; } if (getval(n) == min) { if (!wantDegenerateComp && (top(sp) == n)) { setval(n,INF); pop(sp); } else { char name[32]; Agraph_t* G = agraphof(n);; sprintf(name,"cluster_%d",(st->Comp)++); subg = agsubg(G,name,TRUE); agbindrec(subg,"scc_graph",sizeof(Agraphinfo_t),TRUE); setrep(subg,agnode(map,name,TRUE)); do { t = pop(sp); agsubnode(subg,t,TRUE); setval(t,INF); setscc(t,subg); st->N_nodes_in_nontriv_SCC++; } while (t != n); nodeInduce(subg); if (!Silent) agwrite(subg,stdout); } } return min; }
static block_t* createOneBlock(Agraph_t * g, circ_state * state) { Agraph_t *subg; char name[SMALLBUF]; block_t *bp; Agnode_t* n; sprintf(name, "_block_%d", state->blockCount++); subg = agsubg(g, name, 1); bp = mkBlock(subg); for (n = agfstnode(g); n; n = agnxtnode(g,n)) { agsubnode(bp->sub_graph, n, 1); BLOCK(n) = bp; } return bp; }
//------------------------------------------------- Agraph_t *graph(Agraph_t *g, char *name) { if (!gvc) return NULL; return agsubg(g, name); }
//------------------------------------------------- Agraph_t *findsubg(Agraph_t *g, char *name) { if (!g || !name) return NULL; return agsubg(g, name, 0); }
// add subgraph static inline Agraph_t* _agsubg(Agraph_t* object, QString name) { return agsubg(object, const_cast<char *>(qPrintable(name))); }
static int visit(Agnode_t * n, Agraph_t * map, Stack * sp, sccstate * st) { unsigned int m, min; Agnode_t *t; Agraph_t *subg; Agedge_t *e; min = ++(st->ID); setval(n, min); push(sp, n); #ifdef USE_CGRAPH for (e = agfstout(n->root, n); e; e = agnxtout(n->root, e)) { #else for (e = agfstout(n); e; e = agnxtout(e)) { #endif t = aghead(e); if (getval(t) == 0) m = visit(t, map, sp, st); else m = getval(t); if (m < min) min = m; } if (getval(n) == min) { if (!wantDegenerateComp && (top(sp) == n)) { setval(n, INF); pop(sp); } else { char name[32]; Agraph_t *G = agraphof(n);; sprintf(name, "cluster_%d", (st->Comp)++); subg = agsubg(G, name, TRUE); agbindrec(subg, "scc_graph", sizeof(Agraphinfo_t), TRUE); setrep(subg, agnode(map, name, TRUE)); do { t = pop(sp); agsubnode(subg, t, TRUE); setval(t, INF); setscc(t, subg); st->N_nodes_in_nontriv_SCC++; } while (t != n); #ifdef USE_CGRAPH nodeInduce(subg, map); #else nodeInduce(subg); #endif if (!Silent) agwrite(subg, stdout); } } return min; } static int label(Agnode_t * n, int nodecnt, int *edgecnt) { Agedge_t *e; setval(n, 1); nodecnt++; #ifdef USE_CGRAPH for (e = agfstedge(n->root, n); e; e = agnxtedge(n->root, e, n)) { #else for (e = agfstedge(n); e; e = agnxtedge(e, n)) { #endif (*edgecnt) += 1; if (e->node == n) e = agopp(e); if (!getval(e->node)) nodecnt = label(e->node, nodecnt, edgecnt); } return nodecnt; } static int countComponents(Agraph_t * g, int *max_degree, float *nontree_frac) { int nc = 0; int sum_edges = 0; int sum_nontree = 0; int deg; int n_edges; int n_nodes; Agnode_t *n; #ifdef USE_CGRAPH for (n = agfstnode(g); n; n = agnxtnode(g, n)) { #else for (n = agfstnode(g); n; n = agnxtnode(n)) { #endif if (!getval(n)) { nc++; n_edges = 0; n_nodes = label(n, 0, &n_edges); sum_edges += n_edges; sum_nontree += (n_edges - n_nodes + 1); } } if (max_degree) { int maxd = 0; #ifdef USE_CGRAPH for (n = agfstnode(g); n; n = agnxtnode(g, n)) { deg = agdegree(g, n, TRUE, TRUE); #else for (n = agfstnode(g); n; n = agnxtnode(n)) { deg = agdegree(n, TRUE, TRUE); #endif if (maxd < deg) maxd = deg; setval(n, 0); } *max_degree = maxd; } if (nontree_frac) { if (sum_edges > 0) *nontree_frac = (float) sum_nontree / (float) sum_edges; else *nontree_frac = 0.0; } return nc; } static void process(Agraph_t * G) { Agnode_t *n; Agraph_t *map; int nc = 0; float nontree_frac = 0; int Maxdegree = 0; Stack stack; sccstate state; aginit(G, AGRAPH, "scc_graph", sizeof(Agraphinfo_t), TRUE); aginit(G, AGNODE, "scc_node", sizeof(Agnodeinfo_t), TRUE); state.Comp = state.ID = 0; state.N_nodes_in_nontriv_SCC = 0; if (Verbose) nc = countComponents(G, &Maxdegree, &nontree_frac); initStack(&stack, agnnodes(G) + 1); map = agopen("scc_map", Agdirected, (Agdisc_t *) 0); #ifdef USE_CGRAPH for (n = agfstnode(G); n; n = agnxtnode(G, n)) #else for (n = agfstnode(G); n; n = agnxtnode(n)) #endif if (getval(n) == 0) visit(n, map, &stack, &state); freeStack(&stack); if (!Silent) agwrite(map, stdout); agclose(map); if (Verbose) fprintf(stderr, "%d %d %d %d %.4f %d %.4f\n", agnnodes(G), agnedges(G), nc, state.Comp, state.N_nodes_in_nontriv_SCC / (double) agnnodes(G), Maxdegree, nontree_frac); else fprintf(stderr, "%d nodes, %d edges, %d strong components\n", agnnodes(G), agnedges(G), state.Comp); } static char *useString = "Usage: %s [-sdv?] <files>\n\ -s - silent\n\ -d - allow degenerate components\n\ -v - verbose\n\ -? - print usage\n\ If no files are specified, stdin is used\n"; static void usage(int v) { printf(useString, CmdName); exit(v); }
//------------------------------------------------- Agraph_t *graph(Agraph_t *g, char *name) { if (!gvc) gv_init(); return agsubg(g, name, 1); }