int main(int argc, char* argv[]) { struct marsopts opts = init(argc, argv); Agraph_t* g = agread(opts.fin, (Agdisc_t*)NULL); Agnode_t* n; mat z; init_graph(g); z = mars(g, opts); mat_scalar_mult(z, opts.scale); if(opts.viewer) { viewer(argc, argv); } else { for(n = agfstnode(g); n; n = agnxtnode(g,n)) { int id = getid(n); char* s = pos_to_str(&z->m[mindex(id, 0, z)], z->c); agset(n,"pos",s); free(s); } agwrite(g, opts.fout); } mat_free(z); clean_up(g); agclose(g); return 0; }
int main(int argc, char* argv[]) { if(argc != 3) usage(); float scale = atof(argv[1]); FILE* fin = fopen(argv[2],"r"); Agraph_t* g = agread(fin, (Agdisc_t*)NULL); Agnode_t* n; for(n = agfstnode(g); n; n = agnxtnode(g,n)) { char* pos = agget(n,"pos"); double x,y; sscanf(pos,"%lf,%lf",&x,&y); x *= scale; y *= scale; char* s = pos_to_str(x,y); agset(n,"pos",s); free(s); } agwrite(g,stdout); agclose(g); return 0; }
int main(int argc, char **argv) { Agraph_t *g; Agnode_t *n; ingraph_state ig; int i = 0; int code = 0; Dict_t *Q; init(argc, argv); newIngraph(&ig, Files, gread); Q = dtopen(&MyDisc, Dtoset); while ((g = nextGraph(&ig)) != 0) { dtclear(Q); if ((n = agnode(g, Nodes[i], 0))) dijkstra(Q, g, n); else { fprintf(stderr, "%s: no node %s in graph %s in %s\n", CmdName, Nodes[i], agnameof(g), fileName(&ig)); code = 1; } agwrite(g, stdout); fflush(stdout); agclose(g); i++; } exit(code); }
int main(int argc, char *argv[]) { Agraph_t *g; Agnode_t *n; int rv = 0; init(argc, argv); if ((g = agread(inFile)) != 0) { if (AG_IS_DIRECTED(g)) { for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (ND_mark(n) == 0) rv |= dfs(g, n, 0); } if (doWrite) { agwrite(g, outFile); fflush(outFile); } if (Verbose) { if (rv) fprintf(stderr, "Graph %s has cycles\n", g->name); else fprintf(stderr, "Graph %s is acyclic\n", g->name); } } else { rv = 2; if (Verbose) fprintf(stderr, "Graph %s is undirected\n", g->name); } exit(rv); } else exit(-1); }
int main(int argc, char *argv[]) { Agraph_t *g; Agnode_t *n; int rv = 0; init(argc, argv); if ((g = agread(inFile, (Agdisc_t *) 0)) != 0) { if (agisdirected (g)) { aginit(g, AGNODE, "info", sizeof(Agnodeinfo_t), TRUE); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (ND_mark(n) == 0) rv |= dfs(g, n, 0); } if (doWrite) { agwrite(g, outFile); fflush(outFile); } if (Verbose) { if (rv) fprintf(stderr, "Graph \"%s\" has cycles; %d reversed edges\n", graphName(g), num_rev); else fprintf(stderr, "Graph \"%s\" is acyclic\n", graphName(g)); } } else { rv = -1; if (Verbose) fprintf(stderr, "Graph \"%s\" is undirected\n", graphName(g)); } exit(rv); } else exit(-1); }
static void do_it(Agraph_t * g, int dostat) { if (dostat) agflatten(g, TRUE); agwrite(g, stdout); if (dostat) prstats(g, dostat > 1); }
bool write(Agraph_t *g, FILE *f) { int err; if (!g) return false; err = agwrite(g, f); return (! err); }
int fwriteFile(Expr_t * ex, Agraph_t * g, int fd) { Sfio_t *sp; if (fd < 0 || fd >= elementsof(ex->file) || !((sp = ex->file[fd]))) { exerror("fwriteG: %d: invalid descriptor", fd); return 0; } return agwrite(g, sp); }
grafo escreve_grafo(FILE *output, grafo g){ if(!g || !output) return NULL; Agraph_t *ag; Agsym_t *peso; char peso_s[MAX_STRING_SIZE]; //criando a string "peso" char p_str[5]; strcpy(p_str, "peso"); //cria uma string vazia pra usar como valor default do atributo peso char default_s[1]; default_s[0] = '\0'; if(g->direcionado) ag = agopen(g->nome, Agstrictdirected, NULL); else ag= agopen(g->nome, Agstrictundirected, NULL); if(g->ponderado) peso = agattr(ag, AGEDGE, p_str, default_s); Agnode_t **nodes = malloc(g->n_vertices * sizeof(Agnode_t*)); for(unsigned int i = 0; i < g->n_vertices; i++) nodes[g->vertices[i]->id] = agnode(ag, g->vertices[i]->nome, TRUE); for(unsigned int i = 0; i < g->n_vertices; i++){ vertice v = g->vertices[i]; for(no n = primeiro_no(v->adjacencias_saida); n != NULL; n = proximo_no(n)){ adjacencia viz = conteudo(n); Agedge_t *ae = agedge(ag, nodes[v->id], nodes[viz->v_destino->id], NULL, TRUE); if(g->ponderado){ sprintf(peso_s, "%ld", viz->peso); agxset(ae, peso, peso_s); } } } free(nodes); agwrite(ag, output); agclose(ag); agfree(ag, NULL); return g; }
static void gwrite(Agraph_t * g, int ng, int nb) { FILE *outf; char *name; if (silent) return; if (!outfile) { agwrite(g, stdout); fflush(stdout); } else { name = getName(ng, nb); outf = fopen(name, "w"); if (!outf) { fprintf(stderr, "Could not open %s for writing\n", name); perror("bcomps"); exit(1); } agwrite(g, outf); fclose(outf); } }
int main(int argc, char **argv) { Agraph_t *g; ingraph_state ig; char **files; files = scanargs(argc, argv); newIngraph(&ig, files, gread); while ((g = nextGraph(&ig))) { transform(g); agwrite(g, outFile); } return 0; }
bool write(Agraph_t *g, const char *filename) { FILE *f; int err; if (!g) return false; f = fopen(filename, "w"); if (!f) return false; err = agwrite(g, f); fclose(f); return (! err); }
int main(int argc, char **argv) { Agraph_t *g; ingraph_state ig; init(argc, argv); newIngraph(&ig, Files, gread); while ((g = nextGraph(&ig)) != 0) { if (!chkOnly) agwrite(g, stdout); agclose(g); } return(ig.errors | agerrors()); }
/* sfioWrite: * If the graph is passed in from a library, its output discipline * might not use sfio. In this case, we push an sfio discipline on * the graph, write it, and then pop it off. */ int sfioWrite(Agraph_t * g, Sfio_t* fp, Agiodisc_t* dfltDisc) { Agiodisc_t* saveio = NULL; int rv; if (g->clos->disc.io != dfltDisc) { saveio = g->clos->disc.io; g->clos->disc.io = dfltDisc; } rv = agwrite (g, fp); if (g->clos->disc.io != dfltDisc) { g->clos->disc.io = saveio; } return rv; }
static void dot_end_graph(GVJ_t *job) { graph_t *g = job->obj->u.g; Agiodisc_t* io_save; static Agiodisc_t io; if (io.afread == NULL) { io.afread = AgIoDisc.afread; io.putstr = (putstrfn)gvputs; io.flush = (flushfn)gvflush; } io_save = g->clos->disc.io; g->clos->disc.io = &io; switch (job->render.id) { case FORMAT_PLAIN: write_plain(job, g, (FILE*)job, FALSE); break; case FORMAT_PLAIN_EXT: write_plain(job, g, (FILE*)job, TRUE); break; case FORMAT_DOT: case FORMAT_CANON: if (!(job->flags & OUTPUT_NOT_REQUIRED)) agwrite(g, (FILE*)job); break; case FORMAT_XDOT: case FORMAT_XDOT12: case FORMAT_XDOT14: xdot_end_graph(g); if (!(job->flags & OUTPUT_NOT_REQUIRED)) agwrite(g, (FILE*)job); break; } g->clos->disc.io = io_save; }
int main(int argc,char **argv) { Agraph_t* g; ingraph_state ig; init (argc, argv); newIngraph (&ig, Files, gread); while ((g = nextGraph(&ig)) != 0) { agwrite(g,stdout); agclose (g); } exit(0); }
int main(int argc, char **argv) { Agraph_t *g; Agnode_t *u, *v; int rv; g = agread(stdin,0); if (argc >= 3) { u = agnode(g,argv[1],FALSE); v = agnode(g,argv[2],FALSE); rv = agnodebefore(u,v); fprintf(stderr,"agnodebefore returns %d\n",rv); fprintf(stderr,"dtsize %d\n",dtsize(g->n_seq)); } agwrite(g,stdout); }
/* writeFile: * Write graph into file f. * Return 0 on success */ int writeFile(Agraph_t * g, char *f) { int rv; Sfio_t *fp; if (!f) { error(1, "NULL string passed to writeG"); return 1; } fp = sfopen(0, f, "w"); if (!fp) { error(1, "Could not open %s for writing in writeG", f); return 1; } rv = agwrite(g, fp); sfclose(fp); return rv; }
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; }
int main(int argc, char *argv[]) { Agraph_t *g = 0, *prevg = 0; ingraph_state ig; opts_t opts; init(argc, argv, &opts); newIngraph (&ig, opts.infiles, gread); while ((g = nextGraph (&ig)) != 0) { if (prevg) agclose (prevg); clusterGraph (g, opts.maxcluster, opts.clustering_method); agwrite(g, opts.outfp); prevg = g; } return 0; }
int main(int argc, char **argv) { Agraph_t *g; Agnode_t *n, *m; Agedge_t *e; Agsym_t *a; #ifdef NO_LAYOUT_OR_RENDERING aginit(); #else /* set up a graphviz context - but only once even for multiple graphs */ static GVC_t *gvc; if (!gvc) gvc = gvContext(); #endif /* Create a simple digraph */ g = agopen("g", AGDIGRAPH); n = agnode(g, "n"); m = agnode(g, "m"); e = agedge(g, n, m); /* Set an attribute - in this case one that affects the visible rendering */ agsafeset(n, "color", "red", ""); #ifdef NO_LAYOUT_OR_RENDERING /* Just write the graph without layout */ agwrite(g, stdout); #else /* Use the directed graph layout engine */ gvLayout(gvc, g, "dot"); /* Output in .dot format */ gvRender(gvc, g, "dot", stdout); gvFreeLayout(gvc, g); #endif agclose(g); return 0; }
main() { Agraph_t *g; Agnode_t *n; Agedge_t *e; Agsym_t *sym; char *val; while (g = agread(stdin, NIL(Agdisc_t *))) { for (n = agfstnode(g); n; n = agnxtnode(n)) { /*fprintf(stderr,"%s\n", agnameof(n)); */ for (sym = agnxtattr(g, AGNODE, 0); sym; sym = agnxtattr(g, AGNODE, sym)) { val = agxget(n, sym); /*fprintf(stderr,"\t%s=%s\n",sym->name,val); */ } } agwrite(g, stdout); } }
/** * \brief Show a graph on the prompt * \param graph The graph to show. * */ void graph__show(Agraph_t *graph) { FILE* file; if((file = fopen(TMP_FILENAME, "r")) != NULL) { fclose(file); fprintf(stderr, "Error: %s file already exists\n", TMP_FILENAME); return; } file = fopen(TMP_FILENAME, "w+"); agwrite(graph, file); char buffer[MAX_SIZE] = ""; rewind(file); fgets(buffer, MAX_SIZE, file); while(fgets(buffer, MAX_SIZE, file) != NULL) { if(strncmp(buffer, "}", 1) != 0) printf("%s", buffer); } fclose(file); remove(TMP_FILENAME); }
int main(int argc, char **argv) { Agraph_t *G; Agraph_t *prev = 0; initargs(argc, argv); if (act == ToGXL) { ingraph_state ig; newIngraph(&ig, Files, gread); while ((G = nextGraph(&ig))) { if (prev) agclose(prev); prev = G; gv_to_gxl(G, outFile); fflush(outFile); } } else { #ifdef HAVE_EXPAT FILE *inFile; while ((inFile = getFile())) { while ((G = gxl_to_gv(inFile))) { if (prev) agclose(prev); prev = G; agwrite(G, outFile); fflush(outFile); } } #else fputs("cvtgxl: not configured for conversion from GXL to GV\n", stderr); exit(1); #endif } exit(0); }
static void process(Agraph_t* G) { Agnode_t* n; Agraph_t* map; int nc = 0; float nontree_frac; int Maxdegree; 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); for (n = agfstnode(G); n; n = agnxtnode(n)) 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); }
main() { Agraph_t *g; Agnode_t *n; Agedge_t *e; Agsym_t *sym; char *val; while (g = agread(stdin, NIL(Agdisc_t *))) { #ifdef NOTDEF for (n = agfstnode(g); n; n = agnxtnode(g, n)) { fprintf(stderr, "%s\n", agnameof(n)); for (sym = agnxtattr(g, AGNODE, 0); sym; sym = agnxtattr(g, AGNODE, sym)) { val = agxget(n, sym); fprintf(stderr, "\t%s=%s\n", sym->name, val); } } #endif sym = agattr(g, AGRAPH, "nonsense", "junk"); fprintf(stderr,"sym = %x, %s\n", sym, sym? sym->defval : "(none)"); agwrite(g, stdout); } }
int main(int argc, char **argv) { int c; char *progname; ingraph_state ig; Agraph_t *graph; Agnode_t *node; Agedge_t *edge; Agedge_t *nexte; Agsym_t *attr; char **files; generic_list_t *attr_list; generic_list_t *node_list; unsigned long i, j; opterr = 0; progname = strrchr(argv[0], '/'); if (progname == NULL) { progname = argv[0]; } else { progname++; /* character after last '/' */ } attr_list = new_generic_list(16); node_list = new_generic_list(16); while ((c = getopt(argc, argv, "hvn:N:")) != -1) { switch (c) { case 'N': { attr_list = addattr(attr_list, optarg); break; } case 'n': { node_list = addnode(node_list, optarg); break; } case 'h': { help_message(progname); exit(EXIT_SUCCESS); break; } case 'v': { verbose = 1; break; } case '?': if (isprint(optopt)) { fprintf(stderr, "Unknown option `-%c'.\n", optopt); } else { fprintf(stderr, "Unknown option character `\\x%X'.\n", optopt); } exit(EXIT_FAILURE); break; default: help_message(progname); exit(EXIT_FAILURE); break; } } /* Any arguments left? */ if (optind < argc) { files = &argv[optind]; } else { files = NULL; } newIngraph(&ig, files, gread); while ((graph = nextGraph(&ig)) != NULL) { if (agisdirected(graph) == 0) { fprintf(stderr, "*** Error: Graph is undirected! Pruning works only with directed graphs!\n"); exit(EXIT_FAILURE); } /* attach node data for marking to all nodes */ aginit(graph, AGNODE, NDNAME, sizeof(ndata), 1); /* prune all nodes specified on the commandline */ for (i = 0; i < node_list->used; i++) { if (verbose == 1) fprintf(stderr, "Pruning node %s\n", (char *) node_list->data[i]); /* check whether a node of that name exists at all */ node = agnode(graph, (char *) node_list->data[i], 0); if (node == NULL) { fprintf(stderr, "*** Warning: No such node: %s -- gracefully skipping this one\n", (char *) node_list->data[i]); } else { MARK(node); /* Avoid cycles */ /* Iterate over all outgoing edges */ for (edge = agfstout(node); edge; edge = nexte) { nexte = agnxtout(edge); if (aghead(edge) != node) { /* non-loop edges */ if (verbose == 1) fprintf(stderr, "Processing descendant: %s\n", agnameof(aghead(edge))); remove_child(graph, aghead(edge)); agdelete(graph, edge); } } UNMARK(node); /* Unmark so that it can be removed in later passes */ /* Change attribute (e.g. border style) to show that node has been pruneed */ for (j = 0; j < attr_list->used; j++) { /* create attribute if it doesn't exist and set it */ attr = agattr(graph, AGNODE, ((strattr_t *) attr_list->data[j])->n, ""); if (attr == NULL) { fprintf(stderr, "Couldn't create attribute: %s\n", ((strattr_t *) attr_list->data[j])->n); exit(EXIT_FAILURE); } agxset(node, attr, ((strattr_t *) attr_list->data[j])->v); } } } agwrite(graph, stdout); agclose(graph); } free(attr_list); free(node_list); exit(EXIT_SUCCESS); }
/** * \brief Save the graph structure into a file * \param graph The graph to save. * \param filename The output file. * \return The result of the agwrite call. * */ int graph__save(Agraph_t * graph, char * filename){ FILE * f = fopen(filename, "w"); int i = agwrite(graph, f); fclose(f); return i; }
int ggen_write_graph(igraph_t *g, FILE *output) { Agraph_t *cg; Agnode_t *f,*t; Agedge_t *edge; igraph_vector_ptr_t vertices; igraph_eit_t eit; int err; unsigned long i,j; unsigned long vcount = igraph_vcount(g); igraph_integer_t from,to; char name[GGEN_DEFAULT_NAME_SIZE]; char *str = NULL; igraph_strvector_t gnames,vnames,enames; igraph_vector_t gtypes,vtypes,etypes; Agsym_t *attr; /* see warning below */ igraph_error_handler_t *error_handler; err = igraph_vector_ptr_init(&vertices,vcount); if(err) return 1; /* WARNING: this should be changed if igraph-0.6 gets * stable. * We need to ignore some igraph_cattribute errors * because we try to retrieve special attributes (ggen specifics). * igraph version 0.6 include a cattribute_has_attr that should be * used instead of ignoring errors. */ error_handler = igraph_set_error_handler(igraph_error_handler_ignore); /* open graph * its name is saved in __ggen_graph_name if it exists */ str =(char *) GAS(g,GGEN_GRAPH_NAME_ATTR); if(!str) cg = agopen(GGEN_DEFAULT_GRAPH_NAME,Agdirected,NULL); else cg = agopen(str,Agdirected,NULL); if(!cg) { err = 1; goto d_v; } /* save a pointer to each vertex */ for(i = 0; i < vcount; i++) { /* find a vertex name */ str = vid2vname_unsafe(name,g,i); if(!str) f = agnode(cg,name,1); else f = agnode(cg,str,1); VECTOR(vertices)[i] = (void *)f; } /* We have finished with dangerous attributes accesses */ igraph_set_error_handler(error_handler); /* now loop through edges in the igraph */ err = igraph_eit_create(g,igraph_ess_all(IGRAPH_EDGEORDER_ID),&eit); if(err) goto c_ag; for(IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { err = igraph_edge(g,IGRAPH_EIT_GET(eit),&from,&to); if(err) goto d_eit; f = (Agnode_t *) VECTOR(vertices)[(unsigned long)from]; t = (Agnode_t *) VECTOR(vertices)[(unsigned long)to]; agedge(cg,f,t,NULL,1); } /* find all properties */ igraph_strvector_init(&gnames,1); igraph_strvector_init(&vnames,vcount); igraph_strvector_init(&enames,igraph_ecount(g)); igraph_vector_init(>ypes,1); igraph_vector_init(&vtypes,vcount); igraph_vector_init(&etypes,igraph_ecount(g)); err = igraph_cattribute_list(g,&gnames,>ypes,&vnames,&vtypes,&enames,&etypes); if(err) goto d_eit; /* add graph properties */ for(i = 0; i < igraph_strvector_size(&gnames); i++) { if(strcmp(GGEN_GRAPH_NAME_ATTR,STR(gnames,i))) { if(VECTOR(gtypes)[i]==IGRAPH_ATTRIBUTE_NUMERIC) { snprintf(name,GGEN_DEFAULT_NAME_SIZE,"%f", (double)GAN(g,STR(gnames,i))); agattr(cg,AGRAPH,(char *)STR(gnames,i),name); } else agattr(cg,AGRAPH,(char *)STR(gnames,i), (char *)GAS(g,STR(gnames,i))); } } /* add vertex properties */ for(i = 0; i < igraph_strvector_size(&vnames); i++) { if(strcmp(GGEN_VERTEX_NAME_ATTR,STR(vnames,i))) { /* creates the attribute but we still need to set it for each vertex */ attr = agattr(cg,AGNODE,(char *)STR(vnames,i),GGEN_CGRAPH_DEFAULT_VALUE); for(j = 0; j < vcount; j++) { f = (Agnode_t *) VECTOR(vertices)[j]; if(VECTOR(vtypes)[i]==IGRAPH_ATTRIBUTE_NUMERIC) { snprintf(name,GGEN_DEFAULT_NAME_SIZE,"%f", (double)VAN(g,STR(vnames,i),j)); agxset(f,attr,name); } else agxset(f,attr,(char *)VAS(g,STR(vnames,i),j)); } } } /* add edges properties */ for(i = 0; i < igraph_strvector_size(&enames); i++) { /* creates the attribute but we still need to set it for each edge */ attr = agattr(cg,AGEDGE,(char *)STR(enames,i),GGEN_CGRAPH_DEFAULT_VALUE); for(j = 0; j < igraph_ecount(g); j++) { igraph_edge(g,j,&from,&to); f = (Agnode_t *) VECTOR(vertices)[(unsigned long)from]; t = (Agnode_t *) VECTOR(vertices)[(unsigned long)to]; edge = agedge(cg,f,t,NULL,0); if(VECTOR(etypes)[i]==IGRAPH_ATTRIBUTE_NUMERIC) { snprintf(name,GGEN_DEFAULT_NAME_SIZE,"%f", (double)EAN(g,STR(enames,i),j)); agxset(edge,attr,name); } else agxset(edge,attr,(char *)EAS(g,STR(enames,i),j)); } } /* write the graph */ err = agwrite(cg,(void *)output); d_eit: igraph_eit_destroy(&eit); c_ag: agclose(cg); d_v: igraph_vector_ptr_destroy(&vertices); return err; }
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); }