static void nodeInduce(Agraph_t * g, Agraph_t * eg) { Agnode_t *n; Agedge_t *e; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(eg, n); e; e = agnxtout(eg, e)) { if (agsubnode(g, aghead(e), 0)) { agsubedge(g, e, 1); } } } }
/* cloneSubg: * Clone subgraph sg in tgt. */ static Agraph_t *cloneSubg(Agraph_t * tgt, Agraph_t * g, Dt_t* emap) { Agraph_t *ng; Agraph_t *sg; Agnode_t *t; Agnode_t *newt; Agedge_t *e; Agedge_t *newe; char* name; ng = (Agraph_t *) (copy(tgt, OBJ(g))); if (!ng) return 0; for (t = agfstnode(g); t; t = agnxtnode(g, t)) { newt = agnode(tgt, agnameof(t), 0); if (!newt) { exerror("node %s not found in cloned graph %s", agnameof(t), agnameof(tgt)); return 0; } else agsubnode(ng, newt, 1); } for (t = agfstnode(g); t; t = agnxtnode(g, t)) { for (e = agfstout(g, t); e; e = agnxtout(g, e)) { newe = mapEdge (emap, e); if (!newe) { name = agnameof(AGMKOUT(e)); if (name) exerror("edge (%s,%s)[%s] not found in cloned graph %s", agnameof(agtail(e)), agnameof(aghead(e)), name, agnameof(tgt)); else exerror("edge (%s,%s) not found in cloned graph %s", agnameof(agtail(e)), agnameof(aghead(e)), agnameof(tgt)); return 0; } else agsubedge(ng, newe, 1); } } for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) { if (!cloneSubg(ng, sg, emap)) { exerror("error cloning subgraph %s from graph %s", agnameof(sg), agnameof(g)); return 0; } } return ng; }
QGVNode *QGVSubGraph::addNode(const QString &label) { Agnode_t *node = agnode(_sgraph->graph(), NULL, TRUE); if (node == NULL) { qWarning() << "Invalid sub node :" << label; return 0; } agsubnode(_sgraph->graph(), node, TRUE); QGVNode *item = new QGVNode(new QGVNodePrivate(node), _scene); item->setLabel(label); _scene->addItem(item); _scene->_nodes.append(item); _nodes.append(item); return item; }
static void dfs(Agraph_t * g, Agnode_t * n, Agraph_t * out, char *marks) { Agedge_t *e; Agnode_t *other; MARK(n) = 1; #ifndef WITH_CGRAPH aginsert(out, n); #else /* WITH_CGRAPH */ agsubnode(out,n,1); #endif /* WITH_CGRAPH */ for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) { if ((other = agtail(e)) == n) other = aghead(e); if (!MARK(other)) dfs(g, other, out, marks); } }
/* nodeInduce: * Add all edges in root graph connecting two nodes in * selected to selected. */ void nodeInduce(Agraph_t * selected) { Agnode_t *n; Agedge_t *e; Agraph_t *base; if (!selected) return; base = agroot(selected); if (base == selected) return; for (n = agfstnode(selected); n; n = agnxtnode(selected, n)) { for (e = agfstout(base, n); e; e = agnxtout(base, e)) { if (agsubnode(selected, aghead(e), FALSE)) agsubedge(selected, e, TRUE); } } }
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; }
/* cloneSubg: * Clone subgraph sg in tgt. */ static Agraph_t *cloneSubg(Agraph_t * tgt, Agraph_t * g) { Agraph_t *ng; Agraph_t *sg; Agnode_t *t; Agnode_t *newt; Agnode_t *newh; Agedge_t *e; Agedge_t *newe; ng = (Agraph_t *) (copy(tgt, OBJ(g))); if (!ng) return 0; for (t = agfstnode(g); t; t = agnxtnode(t)) { newt = agnode(tgt, agnameof(t), 0); if (!newt) error(ERROR_PANIC, "node %s not found in cloned graph %s", agnameof(t), agnameof(tgt)); agsubnode(ng, newt, 1); } for (t = agfstnode(g); t; t = agnxtnode(t)) { newt = agnode(tgt, agnameof(t), 0); for (e = agfstout(t); e; e = agnxtout(e)) { newh = agnode(tgt, agnameof(aghead(e)), 0); newe = agedge(newt, newh, agnameof(e), 0); if (!newe) error(ERROR_PANIC, "edge (%s,%s)[%s] not found in cloned graph %s", agnameof(agtail(e)), agnameof(aghead(e)), agnameof(e), agnameof(tgt)); agsubedge(ng, newe, 1); } } for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) { if (!cloneSubg(ng, sg)) { error(ERROR_FATAL, "error cloning subgraph %s from graph %s", agnameof(sg), agnameof(g)); } } return ng; }
static void nodeInduce(Agraph_t * g, Agraph_t* map) { Agnode_t *n; Agedge_t *e; Agraph_t* rootg = agroot (g); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(rootg, n); e; e = agnxtout(rootg, e)) { if (agsubnode(g, aghead(e), FALSE)) agsubedge(g, e, TRUE); else { Agraph_t* tscc = getscc(agtail(e)); Agraph_t* hscc = getscc(aghead(e)); if (tscc && hscc) agedge(map, getrep(tscc), getrep(hscc), NIL(char *), TRUE); } } } }
/* The following functions take a graph and a template (node/edge/graph) * and return the object representing the template within the local graph. */ static Agobj_t *subnode_search(Agraph_t * sub, Agobj_t * n) { if (agraphof(n) == sub) return n; return (Agobj_t *) agsubnode(sub, (Agnode_t *) n, FALSE); }
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); }
/* addNode: * Insert node n into subgraph g. * Return image of n */ Agnode_t *addNode(Agraph_t * gp, Agnode_t * np, int doAdd) { if (!sameG(gp, np, "addNode", 0)) return 0; return agsubnode(gp, np, doAdd); }
/* addNode: * Insert node n into subgraph g. * Return image of n */ Agnode_t *addNode(Agraph_t * gp, Agnode_t * np) { if (!sameG(gp, np, "addNode", 0)) return 0; return agsubnode(gp, np, 1); }