Agnode_t *nexthead(Agnode_t *n, Agnode_t *h) { Agedge_t *e; if (!n || !h) return NULL; e = agfindedge(n->graph, n, h); if (!e) return NULL; do { e = agnxtout(n->graph, e); if (!e) return NULL; } while (e->head == h); return e->head; }
Agedge_t *nextout(Agraph_t *g, Agedge_t *e) { Agnode_t *n; Agedge_t *ne; if (!g || !e) return NULL; ne = agnxtout(g, e); if (ne) return (ne); for (n = agnxtnode(g, agtail(e)); n; n = agnxtnode(g, n)) { ne = agfstout(g, n); if (ne) return ne; } return NULL; }
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 (e->u.to_virt) continue; /* skip edges that we want to ignore in this phase */ if (nonconstraint_edge(e)) continue; t = UF_find(e->tail); h = UF_find(e->head); /* skip self, flat, and intra-cluster edges */ if (t == h) continue; /* inter-cluster edges require special treatment */ if (t->u.clust || h->u.clust) { interclust1(g,e->tail,e->head,e); continue; } if ((rep = find_fast_edge(t,h))) merge_oneway(e,rep); else virtual_edge(t,h,e); #ifdef NOTDEF if ((t == e->tail) && (h == e->head)) { 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 && (f->u.to_virt == 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 } } }
/* cloneGraph: * Clone node, edge and subgraph structure from src to tgt. */ static void cloneGraph(Agraph_t * tgt, Agraph_t * src) { Agedge_t *e; Agedge_t *ne; Agnode_t *t; Agraph_t *sg; char* name; Dt_t* emap = dtopen (&edgepair, Dtoset); edgepair_t* data = (edgepair_t*)malloc(sizeof(edgepair_t)*agnedges(src)); edgepair_t* ep = data; for (t = agfstnode(src); t; t = agnxtnode(src, t)) { if (!copy(tgt, OBJ(t))) { exerror("error cloning node %s from graph %s", agnameof(t), agnameof(src)); } } for (t = agfstnode(src); t; t = agnxtnode(src, t)) { for (e = agfstout(src, t); e; e = agnxtout(src, e)) { if (!(ne = (Agedge_t*)copy(tgt, OBJ(e)))) { name = agnameof(AGMKOUT(e)); if (name) exerror("error cloning edge (%s,%s)[%s] from graph %s", agnameof(agtail(e)), agnameof(aghead(e)), name, agnameof(src)); else exerror("error cloning edge (%s,%s) from graph %s", agnameof(agtail(e)), agnameof(aghead(e)), agnameof(src)); return; } ep->key = e; ep->val = ne; dtinsert (emap, ep++); } } for (sg = agfstsubg(src); sg; sg = agnxtsubg(sg)) { if (!cloneSubg(tgt, sg, emap)) { exerror("error cloning subgraph %s from graph %s", agnameof(sg), agnameof(src)); } } dtclose (emap); free (data); }
/* dumpE: */ void dumpE(graph_t * g, int derived) { Agnode_t *n; Agedge_t *e; Agedge_t **ep; Agedge_t *el; int i; int deg; prIndent(); fprintf(stderr, "Graph %s : %d nodes %d edges\n", g->name, agnnodes(g), agnedges(g)); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { deg = 0; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { deg++; prIndent(); fprintf(stderr, " %s -- %s\n", e->tail->name, e->head->name); if (derived) { for (i = 0, ep = (Agedge_t **) ED_to_virt(e); i < ED_count(e); i++, ep++) { el = *ep; prIndent(); fprintf(stderr, " %s -- %s\n", el->tail->name, el->head->name); } } } if (deg == 0) { /* no out edges */ if (!agfstin(g, n)) /* no in edges */ fprintf(stderr, " %s\n", n->name); } } if (!derived) { bport_t *pp; if ((pp = PORTS(g))) { int sz = NPORTS(g); fprintf(stderr, " %d ports\n", sz); while (pp->e) { fprintf(stderr, " %s : %s -- %s\n", pp->n->name, pp->e->tail->name, pp->e->head->name); pp++; } } } }
/* init_node_edge: * initialize node and edge attributes */ static void init_node_edge(Agraph_t * g) { node_t *n; edge_t *e; int nG = agnnodes(g); attrsym_t *N_pos = agfindattr(g->proto->n, "pos"); attrsym_t *N_pin = agfindattr(g->proto->n, "pin"); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); user_pos(N_pos, N_pin, n, nG); /* set user position if given */ } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) common_init_edge(e); } }
static void twopi_init_node_edge(graph_t * g) { node_t *n; edge_t *e; int i = 0; GD_neato_nlist(g) = N_NEW(agnnodes(g) + 1, node_t *); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { GD_neato_nlist(g)[i++] = n; twopi_init_node(n); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { twopi_init_edge(e); } } }
/* 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); }
void drawGraph(Agraph_t * g) { Agnode_t *v; Agedge_t *e; Agraph_t *s; int param = 0; for (s = agfstsubg(g); s; s = agnxtsubg(s)) { OD_SelFlag(s) = 0; if (OD_Selected(s) == 1) param = 1; else param = 0; drawXdotwithattrs(s, param); } for (v = agfstnode(g); v; v = agnxtnode(g, v)) { if (OD_Selected(v) == 1) param = 1; else param = 0; OD_SelFlag(v) = 0; drawXdotwithattr(v, "_draw_", param); //draw primitives drawXdotwithattr(v, "_ldraw_", param);//label drawing for (e = agfstout(g, v); e; e = agnxtout(g, e)) { OD_SelFlag(e) = 0; if (OD_Selected(e) == 1) param = 1; else param = 0; drawXdotwithattrs(e, param); } } if ((view->Selection.Active > 0) && (!view->SignalBlock)) { view->Selection.Active = 0; drawGraph(g); view->SignalBlock = 1; glexpose(); view->SignalBlock = 0; } }
/* mkMCGraph: * Clone original graph. We only need the nodes, edges and clusters. * Copy */ Agraph_t* mkMCGraph (Agraph_t* g) { Agnode_t* t; Agnode_t* newt; Agnode_t* newh; Agedge_t* e; Agedge_t* newe; Agraph_t* sg; edgepair_t* data; edgepair_t* ep; Agraph_t* newg = agopen (agnameof(g), g->desc, 0); Dt_t* emap = dtopen (&edgepair, Dtoset);; data = N_NEW(agnedges(g), edgepair_t); ep = data; for (t = agfstnode(g); t; t = agnxtnode(g, t)) { newt = mkMCNode (newg, STDNODE, agnameof(t)); assert(newt); MND_orig(newt) = t; MND_rank(newt) = ND_rank(t); } for (t = agfstnode(g); t; t = agnxtnode(g, t)) { newt = agnode (newg, agnameof(t), 0); for (e = agfstout(g, t); e; e = agnxtout(g, e)) { newh = agnode (newg, agnameof(aghead(e)), 0); assert(newh); newe = mkMCEdge (newg, newt, newh, agnameof (e), NORMAL, e); assert(newe); ep->key = e; ep->val = newe; dtinsert (emap, ep++); } } for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) { cloneSubg(newg, sg, emap); } dtclose (emap); free (data); return newg; }
/* 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 void add_edge_attr(Agraph_t * g, Agsym_t * attr) { Agnode_t *n; Agedge_t *e; Agproto_t *proto; for (n = agfstnode(g); n; n = agnxtnode(g, n)) for (e = agfstout(g, n); e; e = agnxtout(g, e)) obj_init_attr(e, attr); if (g->meta_node) { for (n = agfstnode(g->meta_node->graph); n; n = agnxtnode(g->meta_node->graph, n)) for (proto = agusergraph(n)->proto; proto; proto = proto->prev) obj_init_attr(proto->e, attr); } else for (proto = g->proto; proto; proto = proto->prev) obj_init_attr(proto->e, attr); }
static void nodeInduce(Agraph_t * g) { Agnode_t *n, *rootn; Agedge_t *e; for (n = agfstnode(g); n; n = agnxtnode(n)) { rootn = agsubnode(agroot(g), n, FALSE); for (e = agfstout(rootn); e; e = agnxtout(e)) { if (agsubnode(g, aghead(e), FALSE)) agsubedge(g, e, TRUE); else { if (getscc(aghead(e)) && getscc(agtail(e))) agedge(getrep(getscc(agtail(e))), getrep(getscc(aghead(e))), NIL(char *), TRUE); } } } }
Agnode_t *nexthead(Agnode_t *n, Agnode_t *h) { Agedge_t *e; Agraph_t *g; if (!n || !h) return NULL; g = agraphof(n); e = agfindedge(g, n, h); if (!e) return NULL; do { e = agnxtout(g, e); if (!e) return NULL; } while (aghead(e) == h); return aghead(e); }
/* 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 void set_attrwf(Agraph_t * g, int toplevel, int value) { Agraph_t *subg; Agnode_t *n; Agedge_t *e; AGATTRWF(g) = value; for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) { set_attrwf(subg, FALSE, value); } if (toplevel) { for (n = agfstnode(g); n; n = agnxtnode(g, n)) { AGATTRWF(n) = value; for (e = agfstout(g, n); e; e = agnxtout(g, e)) AGATTRWF(e) = value; } } }
void rm(Agraph_t *g) { Agedge_t *e; if (g->meta_node) { for (e = agfstout(g->meta_node->graph, g->meta_node); e; e = agnxtout(g->meta_node->graph, e)) { rm(agusergraph(e->head)); } if (g == g->root) { agclose(g); } else { agdelete(g->meta_node->graph, g->meta_node); } } else { fprintf(stderr, "subgraph has no meta_node\n"); } }
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 void circular_init_node_edge(graph_t * g) { node_t *n; edge_t *e; int i = 0; ndata* alg = N_NEW(agnnodes(g), ndata); GD_neato_nlist(g) = N_NEW(agnnodes(g) + 1, node_t *); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); ND_alg(n) = alg + i; GD_neato_nlist(g)[i++] = n; } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { circular_init_edge(e); } } }
static void cl_count (Agraph_t* g) { Agraph_t* mg; Agedge_t* me; Agnode_t* mn; Agraph_t* subg; int sum = 0; mg = g->meta_node->graph; for (me = agfstout(mg,g->meta_node); me; me = agnxtout(mg,me)) { mn = me->head; subg = agusergraph(mn); cl_count(subg); sum += GD_cl_cnt(subg); if (strncmp(subg->name,"cluster",7) == 0) sum++; } GD_cl_cnt(g) = sum; }
/* translate_drawing: * Translate and/or rotate nodes, spline points, and bbox info if * Offset is non-trivial. * Also, if Rankdir, reset ND_lw, ND_rw, and ND_ht to correct value. */ static void translate_drawing(graph_t * g) { node_t *v; edge_t *e; int shift = (Offset.x || Offset.y); if (!shift && !Rankdir) return; for (v = agfstnode(g); v; v = agnxtnode(g, v)) { if (Rankdir) dot_nodesize(v, FALSE); if (shift) { ND_coord_i(v) = map_point(ND_coord_i(v)); if (State == GVSPLINES) for (e = agfstout(g, v); e; e = agnxtout(g, e)) map_edge(e); } } if (shift) translate_bb(g, GD_rankdir(g)); }
Agedge_t *agnxtedge(Agraph_t * g, Agedge_t * e, Agnode_t * n) { Agedge_t *rv; if (AGTYPE(e) == AGOUTEDGE) { rv = agnxtout(g, e); if (rv == NILedge) { do { rv = !rv ? agfstin(g, n) : agnxtin(g,rv); } while (rv && (rv->node == n)); } } else { do { rv = agnxtin(g, e); /* so that we only see each edge once, */ e = rv; } while (rv && (rv->node == n)); /* ignore loops as in-edges */ } return rv; }
static void cleanup_subgs(graph_t * g) { graph_t *mg; edge_t *me; node_t *mn; graph_t *subg; mg = g->meta_node->graph; for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) { mn = me->head; subg = agusergraph(mn); free_label(GD_label(subg)); if (GD_alg(subg)) { free(PORTS(subg)); free(GD_alg(subg)); } cleanup_subgs(subg); } }
static void countup(Agraph_t *g, rank_t *globr) { Agnode_t *n; Agedge_t *e; int r0, r1, low, high, i; for (n = agfstnode(g); n; n = agnxtnode(g,n)) { for (i = 0; i < ND_ranksize(n); i++) globr[ND_rank(n)+i].n += 1; for (e = agfstout(g,n); e; e = agnxtout(g,e)) { r0 = ND_rank(e->tail); r1 = ND_rank(e->head); low = MIN(r0,r1); high = MAX(r0,r1); for (i = low + 1; i < high; i++) globr[i].n += 1; } } }
/*-------------------------------------------------------------------------*\ * Write info about a node to stdout. * Example: * n:info() \*-------------------------------------------------------------------------*/ static int gr_info(lua_State *L) { Agraph_t *g; gr_node_t *ud = tonode(L, 1, STRICT); Agedge_t *se; Agsym_t *sym; g = agraphof(ud->n); printf("INFO NODE '%s' '%s' id=%lu seq=%d\n", agnameof(ud->n), ud->name, (unsigned long) AGID(ud->n), AGSEQ(ud->n)); printf(" ptr: %p\n", ud->n); printf(" Symbols:\n"); se = agfstout(g, ud->n); sym=0; while ((sym = agnxtattr(g,AGNODE,sym))!=NULL) printf(" %s = '%s'\n",sym->name,sym->defval); #if 0 printf(" Out edges: d-out=%d u-out=%d\n", agdegree(g, ud->n, 0, 1), agcountuniqedges(g, ud->n, 0, 1)); #endif while (se) { printf(" name: '%s', head: '%s', tail: '%s' id=%lud, seq=%d %p\n", agnameof(se), agnameof(aghead(se)), agnameof(agtail(se)), (unsigned long) AGID(se), AGSEQ(se), (void*)se); se = agnxtout(g, se); } #if 0 printf(" In edges: d-in=%d u-in=%d\n", agdegree(g, ud->n, 1, 0), agcountuniqedges(g, ud->n, 1, 0)); #endif se = agfstin(g, ud->n); while (se) { printf(" name: '%s', head: '%s', tail: '%s' îd=%lu seq=%d %p\n", agnameof(se), agnameof(aghead(se)), agnameof(agtail(se)), (unsigned long) AGID(se), AGSEQ(se), (void*)se); se = agnxtin(g, se); } #if 0 printf(" Edges: d-io=%d u-io=%d\n", agdegree(g, ud->n, 1, 1), agcountuniqedges(g, ud->n, 1, 1)); #endif se = agfstedge(g, ud->n); while (se) { printf(" name: '%s', head: '%s', tail: '%s' id=%lud seq=%d %p\n", agnameof(se), agnameof(aghead(se)), agnameof(agtail(se)), (unsigned long) AGID(se), AGSEQ(se), (void*)se); se = agnxtedge(g, se, ud->n); } return 0; }
/* dot_compoundEdges: */ void dot_compoundEdges(graph_t * g) { edge_t *e; node_t *n; #ifdef WITH_CGRAPH Dt_t* clustMap = mkClustMap (g); #endif for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { #ifdef WITH_CGRAPH makeCompoundEdge(g, e, clustMap); #else makeCompoundEdge(g, e); #endif } } #ifdef WITH_CGRAPH dtclose(clustMap); #endif }
/* 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 twopi_init_node_edge(graph_t * g) { node_t *n; edge_t *e; int i = 0; int n_nodes = agnnodes(g); rdata* alg; alg = N_NEW(n_nodes, rdata); GD_neato_nlist(g) = N_NEW(n_nodes + 1, node_t *); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); ND_alg(n) = alg + i; GD_neato_nlist(g)[i++] = n; } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { twopi_init_edge(e); } } }
static void sfdp_init_node_edge(graph_t * g) { node_t *n; edge_t *e; #if 0 int nnodes = agnnodes(g); attrsym_t *N_pos = agfindnodeattr(g, "pos"); #endif for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); #if 0 FIX so that user positions works with multiscale user_pos(N_pos, NULL, n, nnodes); #endif } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) sfdp_init_edge(e); } }
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); } } } }