static int dfs(Agnode_t * n, Agedge_t * link, int warn) { Agedge_t *e; Agedge_t *f; Agraph_t *g = agrootof(n); MARK(n) = 1; for (e = agfstin(g, n); e; e = f) { f = agnxtin(g, e); if (e == link) continue; if (MARK(agtail(e))) agdelete(g, e); } for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (MARK(aghead(e))) { if (!warn) { warn++; fprintf(stderr, "warning: %s has cycle(s), transitive reduction not unique\n", agnameof(g)); fprintf(stderr, "cycle involves edge %s -> %s\n", agnameof(agtail(e)), agnameof(aghead(e))); } } else warn = dfs(aghead(e), AGOUT2IN(e), warn); } MARK(n) = 0; return warn; }
/*-------------------------------------------------------------------------*\ * Method: n.degree(self, what) * Determines degree of a node. * Returns number of in-edges (what='*i'), out-edges (what='*o') or the sum * of all edges (what='*a') to/from/of a node. * Example: * rv, err = n:degree("*i") \*-------------------------------------------------------------------------*/ int gr_degree(lua_State *L) { int count = 0; Agedge_t *e; Agraph_t *g; Agnode_t *n; gr_node_t *ud = tonode(L, 1, STRICT); char *flag = (char *) luaL_optstring(L, 2, "*a"); int indeg = TRUE; int outdeg = TRUE; n = ud->n; g = agroot(ud->n); if (*flag != '*'){ luaL_error(L, "invalid format specifier"); return 0; } switch(*(flag+1)){ case 'i': outdeg = FALSE; break; case 'o': indeg = FALSE; break; } if (indeg){ for (e = agfstin(g, n); e; e = agnxtin(g, e)){ count++; } } if (outdeg){ for (e = agfstout(g, n); e; e = agnxtout(g, e)){ count++; } } lua_pushnumber(L, count); return 1; }
static int in_cross(node_t *v,node_t *w) { register edge_t *e1,*e2; register int inv, cross = 0, t; for (e2 = agfstin(w->graph,w); e2; e2 = agnxtin(w->graph,e2)) { register int cnt = ED_xpenalty(e2); inv = ND_order(e2->tail); for (e1 = agfstin(v->graph,v); e1; e1 = agnxtin(v->graph,e1)) { t = ND_order(e1->tail) - inv; if ((t > 0) || ((t == 0) && (ED_tailport(e1).p.x > ED_tailport(e2).p.x))) cross += ED_xpenalty(e1) * cnt; } } return cross; }
void remove_child(Agraph_t * graph, Agnode_t * node) { Agedge_t *edge; Agedge_t *nexte; /* Avoid cycles */ if MARKED (node) return; MARK(node); /* Skip nodes with more than one parent */ edge = agfstin(node); if (edge && (agnxtin(edge) != NULL)) { UNMARK(node); return; } /* recursively remove children */ for (edge = agfstout(node); edge; edge = nexte) { nexte = agnxtout(edge); if (aghead(edge) != node) { if (verbose) fprintf(stderr, "Processing descendant: %s\n", agnameof(aghead(edge))); remove_child(graph, aghead(edge)); agdeledge(edge); } } agdelnode(node); return; }
/* populates rank lists of g. there are some key details: 1) the input graph ordering must be respected (in left to right initialization) 2) connected components are separated and marked with indices 3) series-parallel graphs (includes trees, obviously) must not have crossings */ static void build_ranks(Agraph_t *g, boolean down) { queue *q; component_t c; int r; Agnode_t *n; Agedge_t *e; c = build_components(g, down); /* process each each component */ q = new_queue(agnnodes(g)+1); for (r = 0; r < c.r; r++) { enqueue(q,c.root[r]); if ((r + 1 >= c.r)||(ND_component(c.root[r])!=ND_component(c.root[r+1]))) { while ((n = dequeue(q))) { install(g,n); if (down) { for (e = agfstout(g,n); e; e = agnxtout(g,e)) if (--ND_priority(e->head) == 0) enqueue(q,e->head); } else { for (e = agfstin(g,n); e; e = agnxtin(g,e)) if (--ND_priority(e->tail) == 0) enqueue(q,e->head); } } } } free_queue(q); }
/* * defines ND_sortweight of each node in r0 w.r.t. r1 * returns... */ static boolean medians(Agraph_t *g, int r0, int r1) { static int *list; static int list_extent; int i,j,lm,rm,lspan,rspan; node_t *n,**v; edge_t *e; boolean hasfixed = FALSE; if (list_extent < GD_maxinoutdeg(g->root)) { list_extent = GD_maxinoutdeg(g->root); if (!list) list = realloc(list,sizeof(list[0])*list_extent); else list = realloc(list,sizeof(list[0])*list_extent); } v = GD_rank(g)[r0].v; for (i = leftmost(g,r0); i <= rightmost(g,r0); i++) { n = v[i]; j = 0; if (r1 > r0) for (e = agfstout(g,n); e; e = agnxtout(g,e)) {if (ED_xpenalty(e) > 0) list[j++] = VAL(e->head,ED_headport(e));} else for (e = agfstin(g,n); e; e = agnxtin(g,e)) {if (ED_xpenalty(e) > 0) list[j++] = VAL(e->tail,ED_tailport(e));} switch(j) { case 0: ND_sortweight(n) = -1; /* no neighbor - median undefined */ break; case 1: ND_sortweight(n) = list[0]; break; case 2: ND_sortweight(n) = (list[0] + list[1])/2; break; default: qsort(list,j,sizeof(int),int_cmpf); if (j % 2) ND_sortweight(n) = list[j/2]; else { /* weighted median */ rm = j/2; lm = rm - 1; rspan = list[j-1] - list[rm]; lspan = list[lm] - list[0]; if (lspan == rspan) ND_sortweight(n) = (list[lm] + list[rm])/2; else { int w = list[lm]*rspan + list[rm]*lspan; ND_sortweight(n) = w / (lspan + rspan); } } } } #ifdef NOTDEF /* this code was in the old mincross */ for (i = 0; i < GD_rank(g)[r0].n; i++) { n = v[i]; if ((ND_out(n).size == 0) && (ND_in(n).size == 0)) hasfixed |= flat_sortweight(n); } #endif return hasfixed; }
static int indegree (graph_t * g, node_t *n) { edge_t *e; int cnt = 0; for (e = agfstin(g,n); e; e = agnxtin(g,e)) cnt++; return cnt; }
Agedge_t *agfstedge(Agraph_t * g, Agnode_t * n) { Agedge_t *rv; rv = agfstout(g, n); if (rv == NILedge) rv = agfstin(g, n); return rv; }
Agedge_t *firstin(Agraph_t *g) { Agnode_t *n; if (!g) return NULL; n = agfstnode(g); if (!n) return NULL; return agfstin(g, n); }
static void search_component(Agraph_t *g, Agnode_t *n, int c) { Agedge_t *e; ND_component(n) = c; for (e = agfstout(g,n); e; e = agnxtout(g,e)) if (ND_component(e->head) < 0) search_component(g,e->head,c); for (e = agfstin(g,n); e; e = agnxtin(g,e)) if (ND_component(e->tail) < 0) search_component(g,e->tail,c); }
Agnode_t *firsttail(Agnode_t *n) { Agedge_t *e; if (!n) return NULL; e = agfstin(agraphof(n), n); if (!e) return NULL; return agtail(e); }
static void transform(Agraph_t * g) { Agnode_t *n; Agedge_t *e; char *str; Agsym_t *m_ix, *s_ix; int cnt, d; m_ix = bindedgeattr(g, "minlen"); s_ix = bindedgeattr(g, "style"); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { d = myindegree(n) + myoutdegree(n); if (d == 0) { if (ChainLimit < 1) continue; if (ChainNode) { e = agedge(g, ChainNode, n, "", TRUE); agxset(e, s_ix, "invis"); ChainSize++; if (ChainSize < ChainLimit) ChainNode = n; else { ChainNode = NULL; ChainSize = 0; } } else ChainNode = n; } else if (d > 1) { if (MaxMinlen < 1) continue; cnt = 0; for (e = agfstin(g, n); e; e = agnxtin(g, e)) { if (isleaf(agtail(e))) { str = agxget(e, m_ix); if (str[0] == 0) { adjustlen(e, m_ix, (cnt % MaxMinlen) + 1); cnt++; } } } cnt = 0; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (isleaf(e->node) || (Do_fans && ischainnode(e->node))) { str = agxget(e, m_ix); if (str[0] == 0) adjustlen(e, m_ix, (cnt % MaxMinlen) + 1); cnt++; } } } } }
Agnode_t *firsttail(Agnode_t *n) { Agedge_t *e; if (!n) return NULL; e = agfstin(n->graph, n); if (!e) return NULL; return e->tail; }
Agedge_t *agnxtedge(Agraph_t * g, Agedge_t * e, Agnode_t * n) { Agedge_t *rv; if (n == AGTAIL(e)) { rv = agnxtout(g, e); if (rv == NILedge) rv = agfstin(g, n); } else rv = agnxtin(g, e); return rv; }
int agdegree(Agnode_t * n, int want_in, int want_out) { Agedge_t *e; int rv = 0; if (want_in) for (e = agfstin(n); e; e = agnxtin(e)) rv++; if (want_out) for (e = agfstout(n); e; e = agnxtout(e)) rv++; return rv; }
/* place_node: * Add n to list. By construction, n is not in list at start. */ static void place_node(Agraph_t * g, Agnode_t * n, nodelist_t * list) { Agedge_t *e; int placed = 0; nodelist_t *neighbors = mkNodelist(); nodelistitem_t *one, *two; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { appendNodelist(neighbors, NULL, e->head); SET_NEIGHBOR(e->head); } for (e = agfstin(g, n); e; e = agnxtin(g, e)) { appendNodelist(neighbors, NULL, e->tail); SET_NEIGHBOR(e->tail); } /* Look for 2 neighbors consecutive on list */ if (sizeNodelist(neighbors) >= 2) { for (one = list->first; one; one = one->next) { if (one == list->last) two = list->first; else two = one->next; if (NEIGHBOR(one->curr) && NEIGHBOR(two->curr)) { appendNodelist(list, one, n); placed = 1; break; } } } /* Find any neighbor on list */ if (!placed && sizeNodelist(neighbors) > 0) { for (one = list->first; one; one = one->next) { if (NEIGHBOR(one->curr)) { appendNodelist(list, one, n); placed = 1; break; } } } if (!placed) appendNodelist(list, NULL, n); for (one = neighbors->first; one; one = one->next) UNSET_NEIGHBOR(one->curr); freeNodelist(neighbors); }
Agedge_t *nextin(Agraph_t *g, Agedge_t *e) { Agnode_t *n; Agedge_t *ne; if (!g || !e) return NULL; ne = agnxtin(g, e); if (ne) return (ne); n = agnxtnode(g, n); if (!n) return NULL; return agfstin(g, n); }
int agcountuniqedges(Agraph_t * g, Agnode_t * n, int want_in, int want_out) { Agedge_t *e; Agsubnode_t *sn; int rv = 0; sn = agsubrep(g, n); if (want_out) rv = cnt(g->e_seq,&(sn->out_seq)); if (want_in) { if (!want_out) rv += cnt(g->e_seq,&(sn->in_seq)); /* cheap */ else { /* less cheap */ for (e = agfstin(g, n); e; e = agnxtin(g, e)) if (e->node != n) rv++; /* don't double count loops */ } } return rv; }
/* 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++; } } } }
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; }
Agraph_t *firstsupg(Agraph_t *g) { Agraph_t *mg; Agnode_t *n; Agedge_t *e; if (!g) return NULL; n = g->meta_node; if (!n) return NULL; mg = n->graph; if (!mg) return NULL; e = agfstin(mg, n); if (!e) return NULL; return agusergraph(e->tail); }
/*-------------------------------------------------------------------------*\ * 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; }
void agwrnode(Agraph_t * g, FILE * fp, Agnode_t * n, int full, int indent) { char *myval, *defval; int i, didwrite = FALSE; int nprint = 0; Agdict_t *d = n->graph->univ->nodeattr; Agsym_t *a; if (full) { for (i = 0; i < dtsize(d->dict); i++) { a = d->list[i]; if (a->printed == FALSE) continue; myval = agget(n, a->name); if (g == n->graph) defval = a->value; else defval = agget(g->proto->n, a->name); if (strcmp(defval, myval)) { if (didwrite == FALSE) { tabover(fp, indent); agputs(agcanonical(n->name), fp); didwrite = TRUE; } writeattr(fp, &nprint, a->name, myval); } } if (didwrite) { agputs(nprint > 0 ? "];\n" : ";\n", fp); return; } } if ((agfstout(g, n) == NULL) && (agfstin(g, n) == NULL)) { tabover(fp, indent); agputs(agcanonical(n->name), fp); agputs(";\n", fp); } }
Agedge_t *firstin(Agnode_t *n) { if (!n) return NULL; return agfstin(agraphof(n), n); }
grafo le_grafo(FILE *input) { Agraph_t *ag = agread(input, 0); if(!(ag && agisstrict(ag))) return NULL; // struct grafo *g = malloc(sizeof(struct grafo)); grafo g = malloc(sizeof(struct grafo)); if( !g ) return NULL; g->vertices = constroi_lista(); g->nome = malloc(sizeof(char) * strlen(agnameof(ag)+1)); strcpy(g->nome, agnameof(ag)); g->direcionado = agisdirected(ag); g->n_vertices = (unsigned int)agnnodes(ag); g->n_arestas = (unsigned int)agnedges(ag); g->ponderado = 0; for( Agnode_t *v = agfstnode(ag); v; v = agnxtnode(ag,v) ){ vertice vt = malloc(sizeof(struct vertice)); vt->nome = malloc(sizeof(char) * strlen(agnameof(v))+1); strcpy( vt->nome, agnameof(v) ); vt->visitado = 0; vt->coberto = 0; vt->arestas_saida = constroi_lista(); vt->arestas_entrada = constroi_lista(); insere_lista(vt, g->vertices); } for( Agnode_t *v = agfstnode(ag); v; v = agnxtnode(ag,v) ){ vertice vt = busca_vertice(g->vertices, agnameof(v)); if( g-> direcionado ){ for( Agedge_t *e = agfstout(ag,v); e; e = agnxtout(ag,e) ){ aresta at = cria_aresta(g->vertices, e); if( at->peso != 0 ) g->ponderado = 1; insere_lista(at, vt->arestas_saida); } for( Agedge_t *e = agfstin(ag,v); e; e = agnxtin(ag,e) ){ aresta at = cria_aresta(g->vertices, e); if( at->peso != 0 ) g->ponderado = 1; insere_lista(at, vt->arestas_entrada); } } else { for( Agedge_t *e = agfstedge(ag,v); e; e = agnxtedge(ag,e,v) ){ if( agtail(e) != v ) continue; aresta at = cria_aresta(g->vertices, e); if( at->peso != 0 ) g->ponderado = 1; insere_lista(at, at->origem->arestas_saida); insere_lista(at, at->destino->arestas_saida); } } } if( agclose(ag) ) return NULL; return g; }
Agedge_t *firstin(Agnode_t *n) { if (!n) return NULL; return agfstin(n->graph, n); }
/* could happen with an undirected edge */ char *temp; temp = tp; tp = hp; hp = temp; } if (tp && tp[0]) { agxset(e,TAILX,tp); agstrfree(tp); } if (hp && hp[0]) { agxset(e,HEADX,hp); agstrfree(hp); } } } } } tailptr = SP->list; while (tailptr) { freeptr = tailptr; tailptr = tailptr->link; if (TAG_OF(freeptr->data.obj) == TAG_NODE) free(freeptr); } if (G != SP->subg) abort(); agpopproto(G); In_edge_stmt = SP->in_edge_stmt; old_SP = SP; SP = SP->link; In_decl = FALSE; free(old_SP); Current_class = TAG_GRAPH; } #if 0 /* NOT USED */ static Agraph_t *parent_of(Agraph_t *g) { Agraph_t *rv; rv = agusergraph(agfstin(g->meta_node->graph,g->meta_node)->tail); return rv; }