/*-------------------------------------------------------------------------*\ * Metamethod: __eq [boolean] * Compare two nodes. * Example: * n1 == n2 or n1 ~= n2 with metamethods \*-------------------------------------------------------------------------*/ static int gr_equal(lua_State *L) { gr_node_t *ud1 = tonode(L, 1, STRICT); gr_node_t *ud2 = tonode(L, 2, STRICT); lua_pushboolean(L, (AGID(ud1->n) == AGID(ud2->n))); return 1; }
/* compare: * Lexicographic ordering of objects. */ int compare(Agobj_t * l, Agobj_t * r) { char lkind, rkind; if (l == NULL) { if (r == NULL) return 0; else return -1; } else if (r == NULL) { return 1; } if (AGID(l) < AGID(r)) return -1; else if (AGID(l) > AGID(r)) return 1; lkind = AGTYPE(l); rkind = AGTYPE(r); if (lkind == 3) lkind = 2; if (rkind == 3) rkind = 2; if (lkind == rkind) return 0; else if (lkind < rkind) return -1; else return 1; }
int agraphidcmpf(Dict_t * d, void *arg0, void *arg1, Dtdisc_t * disc) { ptrdiff_t v; Agraph_t *sg0, *sg1; sg0 = (Agraph_t *) arg0; sg1 = (Agraph_t *) arg1; v = (AGID(sg0) - AGID(sg1)); return ((v==0)?0:(v<0?-1:1)); }
static void tkgen_print_tags(GVJ_t *job) { char *ObjType; unsigned int ObjId; obj_state_t *obj = job->obj; int ObjFlag; switch (obj->emit_state) { case EMIT_NDRAW: ObjType = "node"; ObjFlag = 1; ObjId = AGID(obj->u.n); break; case EMIT_NLABEL: ObjType = "node"; ObjFlag = 0; ObjId = AGID(obj->u.n); break; case EMIT_EDRAW: case EMIT_TDRAW: case EMIT_HDRAW: ObjType = "edge"; ObjFlag = 1; ObjId = AGID(obj->u.e); break; case EMIT_ELABEL: case EMIT_TLABEL: case EMIT_HLABEL: ObjType = "edge"; ObjFlag = 0; ObjId = AGID(obj->u.e); break; case EMIT_GDRAW: ObjType = "graph"; ObjFlag = 1; ObjId = AGID(obj->u.g); break; case EMIT_GLABEL: ObjFlag = 0; ObjType = "graph label"; ObjId = AGID(obj->u.g); break; case EMIT_CDRAW: ObjType = "graph"; ObjFlag = 1; ObjId = AGID(obj->u.sg); break; case EMIT_CLABEL: ObjType = "graph"; ObjFlag = 0; ObjId = AGID(obj->u.sg); break; default: assert (0); break; } gvprintf(job, " -tags {%d%s%p}", ObjFlag, ObjType, ObjId); }
/*-------------------------------------------------------------------------*\ * 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; }
/*-------------------------------------------------------------------------*\ * Method: n.delete(self) * Delete a node. All associated edges are deleted as well. * Returns non-nil on success. * Example: * rv, err = n:delete(h) \*-------------------------------------------------------------------------*/ static int gr_delete(lua_State *L) { Agraph_t *g; gr_node_t *ud = tonode(L, 1, NONSTRICT); if (ud->n != NULL){ /* Delete all associated edges with tail on this node */ Agedge_t *se, *ne; int ix; g = ud->n->graph; se = agfstedge(g, ud->n); while (se){ ne = agnxtedge(g, se, ud->n); ix = get_object(L, se); /* ud, se */ if (!(lua_isnil(L, -ix))){ TRACE("n:delete(): closing subedge: ud=%p 'edge@%d' id=0x%0x e=%p\n", (void *) lua_touserdata(L, -ix), AGID(se), AGID(se), (void *)se); lua_pushcfunction(L, gr_delete_edge); /* ud, se, func */ lua_pushvalue(L, -2); /* ud, se, func, se */ lua_call(L, 1, LUA_MULTRET); /* ud, se */ lua_pop(L, 1); /* ud */ } else { lua_pop(L, 2); /* ud */ } se = ne; } TRACE("n:delete(): ud=%p '%s' id=0x%0x \n", (void *) ud, agnameof(ud->n), AGID(ud->n)); del_object(L, ud->n); agdelete(g, ud->n); ud->n = NULL; if (ud->name){ free(ud->name); ud->name = NULL; } } else { TRACE("n:delete(): ud=%p already closed\n", (void *)ud); } lua_pushnumber(L, 0); return 1; }
char *agnameof(void *obj) { Agraph_t *g; char *rv; char buf[32]; /* perform internal lookup first */ g = agraphof(obj); if ((rv = aginternalmapprint(g, AGTYPE(obj), AGID(obj)))) return rv; if (AGDISC(g, id)->print) { if ((rv = AGDISC(g, id)->print(AGCLOS(g, id), AGTYPE(obj), AGID(obj)))) return rv; } if (AGTYPE(obj) != AGEDGE) sprintf(buf, "%c%ld", LOCALNAMEPREFIX, AGID(obj)); else buf[0] = 0; return agstrdup(g, buf); }
/* isIn: * Return 1 if object objp is in subgraph gp. */ int isIn(Agraph_t * gp, Agobj_t * objp) { if (!sameG(gp, objp, "isIn", 0)) return 0; switch (AGTYPE(objp)) { case AGRAPH: return (agparent((Agraph_t *) objp) == gp); case AGNODE: return (agidnode(gp, AGID(objp), 0) != 0); default: return (agsubedge(gp, (Agedge_t *) objp, 0) != 0); } }
int circuit_model(graph_t * g, int nG) { double **Gm; double **Gm_inv; int rv; long i, j; node_t *v; edge_t *e; Gm = new_array(nG, nG, 0.0); Gm_inv = new_array(nG, nG, 0.0); /* set non-diagonal entries */ for (v = agfstnode(g); v; v = agnxtnode(g, v)) { for (e = agfstedge(g, v); e; e = agnxtedge(g, e, v)) { i = AGID(agtail(e)); j = AGID(aghead(e)); if (i == j) continue; /* conductance is 1/resistance */ Gm[i][j] = Gm[j][i] = -1.0 / ED_dist(e); /* negate */ } } rv = solveCircuit(nG, Gm, Gm_inv); if (rv) for (i = 0; i < nG; i++) { for (j = 0; j < nG; j++) { GD_dist(g)[i][j] = Gm_inv[i][i] + Gm_inv[j][j] - 2.0 * Gm_inv[i][j]; } } free_array(Gm); free_array(Gm_inv); return rv; }
static void cc_dfs(Agraph_t* g, Agraph_t * comp, Agnode_t * n) { Agedge_t *e; Agnode_t *other; CCMARK(n); agidnode(comp, AGID(n), 1); for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) { if (agtail(e) == n) other = aghead(e); else other = agtail(e); if (!CCMARKED(other)) cc_dfs(g, comp, other); } }
/* compOf: * Return connected component of node. */ Agraph_t *compOf(Agraph_t * g, Agnode_t * n) { Agraph_t *cg; Agnode_t *np; static int id; char name[64]; if (!(n = agidnode(g, AGID(n), 0))) return 0; /* n not in g */ for (np = agfstnode(g); np; np = agnxtnode(g, np)) CCUNMARK(np); sprintf(name, "_cc_%d", id++); cg = openSubg(g, name); cc_dfs(g, cg, n); return cg; }
/* * Open a new main graph with the given descriptor (directed, strict, etc.) */ Agraph_t *agopen(char *name, Agdesc_t desc, Agdisc_t * arg_disc) { Agraph_t *g; Agclos_t *clos; unsigned long gid; clos = agclos(arg_disc); g = clos->disc.mem->alloc(clos->state.mem, sizeof(Agraph_t)); AGTYPE(g) = AGRAPH; g->clos = clos; g->desc = desc; g->desc.maingraph = TRUE; g->root = g; g->clos->state.id = g->clos->disc.id->open(g); if (agmapnametoid(g, AGRAPH, name, &gid, TRUE)) AGID(g) = gid; /* else AGID(g) = 0 because we have no alternatives */ return agopen1(g); }
/*-------------------------------------------------------------------------* \ * Method: n.delete(self) * Delete a node. All associated edges are deleted as well. * Returns non-nil on success. * Example: * rv, err = n:delete(h) \*-------------------------------------------------------------------------*/ static int gr_delete(lua_State *L) { Agraph_t *g; gr_node_t *ud = tonode(L, 1, NONSTRICT); if (ud->n != NULL){ /* Delete all associated edges with tail on this node */ g = agraphof(ud->n); if (ud->status == ALIVE){ TRACE(" n.delete(): deleting node '%s' ud=%p id=0x%0lx (%s %d) \n", agnameof(ud->n), (void *) ud, (unsigned long) AGID(ud->n), __FILE__, __LINE__); agdelnode(g, ud->n); } } else { TRACE(" n:delete(): ud=%p already closed (%s %d)\n", (void *)ud, __FILE__, __LINE__); } lua_pushnumber(L, 0); return 1; }
/*-------------------------------------------------------------------------*\ * Method: n.rename(self, name) * Renames a graph. Null name will assign an auto-name 'node@ID'. * Returns old name. * Example: * oldname, err = n:rename("NODENEWNAME") or n:rename() \*-------------------------------------------------------------------------*/ static int gr_rename(lua_State *L) { char sbuf[32]; gr_node_t *ud = tonode(L, 1, STRICT); char *name = (char *) lua_tostring(L, 2); char *oldname = agnameof(ud->n); if (!name){ sprintf(sbuf, "node@%d", AGID(ud->n)); agrename(ud->n, agstrdup(sbuf)); free(ud->name); ud->name = strdup(sbuf); } else { agrename(ud->n, agstrdup(name)); free(ud->name); ud->name = strdup(name); } lua_pushstring(L, oldname); agstrfree(oldname); return 1; }
/*-------------------------------------------------------------------------*\ * Method: e = nextedge(self, prev) * Retrieves next edge of a node. * Returns the next edge of the given node. With nil as prev the first * edge is returned. * Example: * first = n:nextedge(nil) * second = n:nextedge(first) * third = n:nextedge(second) \*-------------------------------------------------------------------------*/ static int gr_nextedge(lua_State *L) { int rv; char sbuf[32]; Agraph_t *g; Agedge_t *e; gr_edge_t *ud_e; gr_node_t *ud_n = tonode(L, 1, STRICT); g = agroot(ud_n->n); if (lua_isnil(L, 2)){ e = agfstedge(g, ud_n->n); } else { ud_e = toedge(L, 2, STRICT); e = agnxtedge(g, ud_e->e, ud_n->n); } if (!e){ /* no more edges */ lua_pushnil(L); return 1; } else { /* Check whether userdata exists .. */ rv = get_object(L, e); if (rv == 1){ /* .. yes: return it */ return rv; } else { /* .. no: create it */ lua_pop(L, rv); ud_e = lua_newuserdata(L, sizeof(gr_edge_t)); ud_e->e = e; sprintf(sbuf, "edge@%lu", (unsigned long) AGID(e)); ud_e->name = strdup(sbuf); ud_e->type = AGEDGE; ud_e->status = ALIVE; set_object(L, e); return new_edge(L); } } }
/*-------------------------------------------------------------------------*\ * Method: e.delete(self) * Delete an edge. * Returns non-nil on success. * Example: * rv, err = n:delete() \*-------------------------------------------------------------------------*/ static int gr_delete(lua_State *L) { int rv = -1; gr_edge_t *ud = toedge(L, 1, NONSTRICT); Agraph_t *g; if (ud->e != NULL){ g = ud->e->tail->graph; TRACE("e.delete(): edge: ud=%p '%s' id=0x%x e=%p\n", (void *) ud, ud->name, AGID(ud->e), (void *)ud->e); del_object(L, ud->e); agdelete(g, ud->e); ud->e = NULL; if (ud->name){ free(ud->name); ud->name = NULL; } } else { TRACE("e:delete(): ud=%p already closed\n", (void *)ud); } lua_pushnumber(L, rv); return 1; }
static int gr_nextinout(lua_State *L, edge_first_iter_t *fst, edge_next_iter_t *nxt) { int rv; Agedge_t *e; char sbuf[32]; gr_edge_t *ud_e; gr_node_t *ud_n = tonode(L, 1, STRICT); Agraph_t *g = agroot(ud_n->n); if (lua_isnil(L, 2)) e = fst(g, ud_n->n); else { ud_e = toedge(L, 2, STRICT); e = nxt(g, ud_e->e); } if (!e){ /* no more nodes */ lua_pushnil(L); return 1; } else { /* Check whether userdata exists .. */ rv = get_object(L, e); if (rv == 1) /* .. yes: return it */ return rv; else { /* .. no: create it */ lua_pop(L, rv); ud_e = lua_newuserdata(L, sizeof(gr_edge_t)); ud_e->e = e; sprintf(sbuf, "edge@%lu", (unsigned long) AGID(e)); ud_e->name = strdup(sbuf); ud_e->type = AGEDGE; set_object(L, e); return new_edge(L); } } }
/*-------------------------------------------------------------------------*\ * Method: e, tail, head = n.edge(self, node, label, flag) * Finds or creates an edge. The given node becomes the tail of the edge. * Label is optional. * The optional flag nocreate=true inhibits auto-creation. * Any node given by name is implicitly created and it's userdata returned * as additional results - even if nocreate is not set. * Example: * e, tail, head = e:node(n2, "edge-1") * e, err = g:edge(...) \*-------------------------------------------------------------------------*/ static int gr_edge(lua_State *L) { Agedge_t *e; gr_edge_t *edge; int rv; char *label; char sbuf[32]; Agraph_t *g; gr_node_t *head; gr_node_t *tail = tonode(L, 1, STRICT); if (lua_isuserdata(L, 2)) head = tonode(L, 2, STRICT); else { /* Create a node given by name */ lua_pushcfunction(L, gr_create_node); /* tail, nhead, (label), func */ get_object(L, tail->n->graph); /* tail, nhead, (label), func, graph */ lua_pushstring(L, (const char *) luaL_checkstring(L, 2)); /* ... func, graph, nhead */ if (lua_isboolean(L, 4)) lua_pushvalue(L, 4); else lua_pushboolean(L, 0); /* g.node(self, name, flag) */ lua_call(L, 3, 1); /* tail, nhead, (label), head */ head = tonode(L, -1, STRICT); lua_pop(L,1); /* tail, nhead, (label) */ } g = tail->n->graph; if (tail->n->graph != head->n->graph){ luaL_error(L, "head/tail not in same graph"); } label = (char *) luaL_optstring(L, 3, ""); /* ud, peer, name, (flag) */ if ((e = agfindedge(g, tail->n, head->n)) != NULL){ /* Edge exists */ rv = get_object(L, e); /* ud, peer, name, (flag), edge */ if (lua_isnil(L, -rv)){ lua_pop(L, rv); /* ud, peer, name, (flag) */ /* Edge not yet registered */ edge = lua_newuserdata(L, sizeof(gr_edge_t)); /* ud, peer, name, (flag), edge */ edge->e = e; if (strlen(label) > 0) agset(e, "label", label); sprintf(sbuf, "edge@%d", AGID(e)); edge->name = strdup(sbuf); edge->type = AGEDGE; set_object(L, e); /* ud, peer, name, (flag), edge */ new_edge(L); lua_pushlightuserdata(L, tail); lua_pushlightuserdata(L, head); /* ud, peer, name, (flag), edge, tail, head */ return 3; } else { /* Edge already registered */ lua_pushlightuserdata(L, tail); lua_pushlightuserdata(L, head); return rv + 2; /* ud, peer, name, (flag), edge, tail, head */ } } else { /* Edge does not exist */ if (lua_toboolean(L, 4)){ lua_pushnil(L); lua_pushstring(L, "edge not found"); return 2; } edge = lua_newuserdata(L, sizeof(gr_edge_t)); if (!(edge->e = agedge(g, tail->n, head->n))){ luaL_error(L, "agedge failed"); return 0; } if (strlen(label) > 0) agset(edge->e, "label", label); sprintf(sbuf, "edge@%d", AGID(edge->e)); edge->name = strdup(sbuf); edge->type = AGEDGE; set_object(L, edge->e); new_edge(L); lua_pushlightuserdata(L, tail); lua_pushlightuserdata(L, head); return 3; } }
/* orthoEdges: * For edges without position information, construct an orthogonal routing. * If doLbls is true, use edge label info when available to guide routing, * and set label pos for those edges for which this info is not available. */ void orthoEdges (Agraph_t* g, int doLbls) { sgraph* sg; maze* mp; int n_edges; route* route_list; int i, gstart; Agnode_t* n; Agedge_t* e; snode* sn; snode* dn; epair_t* es = N_GNEW(agnedges(g), epair_t); cell* start; cell* dest; PointSet* ps; textlabel_t* lbl; if (Concentrate) ps = newPS(); #ifdef DEBUG { char* s = agget(g, "odb"); char c; odb_flags = 0; if (s && (*s != '\0')) { while ((c = *s++)) { switch (c) { case 'c' : odb_flags |= ODB_CHANG; // emit channel graph break; case 'i' : odb_flags |= (ODB_SGRAPH|ODB_IGRAPH); // emit search graphs break; case 'm' : odb_flags |= ODB_MAZE; // emit maze break; case 'r' : odb_flags |= ODB_ROUTE; // emit routes in maze break; case 's' : odb_flags |= ODB_SGRAPH; // emit search graph break; } } } } #endif if (doLbls) { agerr(AGWARN, "Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"); doLbls = 0; } mp = mkMaze (g, doLbls); sg = mp->sg; #ifdef DEBUG if (odb_flags & ODB_SGRAPH) emitSearchGraph (stderr, sg); #endif /* store edges to be routed in es, along with their lengths */ n_edges = 0; for (n = agfstnode (g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g,e)) { if ((Nop == 2) && ED_spl(e)) continue; if (Concentrate) { int ti = AGID(agtail(e)); int hi = AGID(aghead(e)); if (ti <= hi) { if (isInPS (ps,ti,hi)) continue; else addPS (ps,ti,hi); } else { if (isInPS (ps,hi,ti)) continue; else addPS (ps,hi,ti); } } es[n_edges].e = e; es[n_edges].d = edgeLen (e); n_edges++; } } route_list = N_NEW (n_edges, route); qsort((char *)es, n_edges, sizeof(epair_t), (qsort_cmpf) edgecmp); gstart = sg->nnodes; PQgen (sg->nnodes+2); sn = &sg->nodes[gstart]; dn = &sg->nodes[gstart+1]; for (i = 0; i < n_edges; i++) { #ifdef DEBUG if ((i > 0) && (odb_flags & ODB_IGRAPH)) emitSearchGraph (stderr, sg); #endif e = es[i].e; start = CELL(agtail(e)); dest = CELL(aghead(e)); if (doLbls && (lbl = ED_label(e)) && lbl->set) { } else { if (start == dest) addLoop (sg, start, dn, sn); else { addNodeEdges (sg, dest, dn); addNodeEdges (sg, start, sn); } if (shortPath (sg, dn, sn)) goto orthofinish; } route_list[i] = convertSPtoRoute(sg, sn, dn); reset (sg); } PQfree (); mp->hchans = extractHChans (mp); mp->vchans = extractVChans (mp); assignSegs (n_edges, route_list, mp); if (setjmp(jbuf)) goto orthofinish; assignTracks (n_edges, route_list, mp); #ifdef DEBUG if (odb_flags & ODB_ROUTE) emitGraph (stderr, mp, n_edges, route_list, es); #endif attachOrthoEdges (g, mp, n_edges, route_list, &sinfo, es, doLbls); orthofinish: if (Concentrate) freePS (ps); for (i=0; i < n_edges; i++) free (route_list[i].segs); free (route_list); freeMaze (mp); }
/* * Close a graph or subgraph, freeing its storage. */ int agclose(Agraph_t * g) { Agraph_t *subg, *next_subg, *par; Agnode_t *n, *next_n; agflatten(g, FALSE); par = agparent(g); if ((par == NILgraph) && (AGDISC(g, mem)->close)) { /* free entire heap */ agmethod_delete(g, g); /* invoke user callbacks */ agfreeid(g, AGRAPH, AGID(g)); AGDISC(g, mem)->close(AGCLOS(g, mem)); /* whoosh */ return SUCCESS; } for (subg = agfstsubg(g); subg; subg = next_subg) { next_subg = agnxtsubg(subg); agclose(subg); } for (n = agfstnode(g); n; n = next_n) { next_n = agnxtnode(n); agdelnode(n); } aginternalmapclose(g); agmethod_delete(g, g); assert(dtsize(g->n_id) == 0); agdtclose(g, g->n_id); assert(dtsize(g->n_seq) == 0); agdtclose(g, g->n_seq); assert(dtsize(g->e_id) == 0); agdtclose(g, g->e_id); assert(dtsize(g->e_seq) == 0); agdtclose(g, g->e_seq); assert(dtsize(g->g_dict) == 0); agdtclose(g, g->g_dict); if (g->desc.has_attrs) agraphattr_delete(g); agrecclose((Agobj_t *) g); agfreeid(g, AGRAPH, AGID(g)); if (par) { agdelsubg(par, g); agfree(par, g); } else { Agmemdisc_t *memdisc; void *memclos, *clos; while (g->clos->cb) agpopdisc(g, g->clos->cb->f); AGDISC(g, id)->close(AGCLOS(g, id)); agstrclose(g); memdisc = AGDISC(g, mem); memclos = AGCLOS(g, mem); clos = g->clos; (memdisc->free) (memclos, g); (memdisc->free) (memclos, clos); } return SUCCESS; }
/*-------------------------------------------------------------------------*\ * Property: id [number] * Get a node's id. * Example: * n = n.id \*-------------------------------------------------------------------------*/ static int gr_id(lua_State *L) { gr_node_t *ud = tonode(L, 1, STRICT); lua_pushnumber(L, AGID(ud->n)); return 1; }
/*-------------------------------------------------------------------------*\ * Property: id [number] * Get an edge's id. * Example: * n = e.id \*-------------------------------------------------------------------------*/ static int gr_id(lua_State *L) { gr_edge_t *ud = toedge(L, 1, STRICT); lua_pushnumber(L, AGID(ud->e)); return 1; }
int ggen_read_graph(igraph_t *g,FILE *input) { Agraph_t *cg; Agnode_t *v; Agedge_t *e; igraph_vector_t edges; igraph_vector_t vertices; int err; unsigned long esize; unsigned long vsize; unsigned long from, to; igraph_integer_t eid; Agsym_t *att; /* read the graph */ cg = agread((void *)input,NULL); if(!cg) return 1; if(!agisdirected(cg)) { error("Input graph is undirected\n"); err = 1; goto error_d; } /* init edge array */ err = igraph_vector_init(&edges,2*agnedges(cg)); if(err) goto error_d; err = igraph_vector_init(&vertices,agnnodes(cg)); if(err) goto error_de; /* init igraph */ igraph_empty(g,agnnodes(cg),1); /* asign id to each vertex */ vsize = 0; for(v = agfstnode(cg); v; v = agnxtnode(cg,v)) VECTOR(vertices)[vsize++] = AGID(v); /* loop through each edge */ esize = 0; for(v = agfstnode(cg); v; v = agnxtnode(cg,v)) { from = find_id(AGID(v),vertices,vsize); for(e = agfstout(cg,v); e; e = agnxtout(cg,e)) { to = find_id(AGID(aghead(e)),vertices,vsize); VECTOR(edges)[esize++] = from; VECTOR(edges)[esize++] = to; } } /* finish the igraph */ err = igraph_add_edges(g,&edges,NULL); if(err) goto error; /* read graph properties */ att = agnxtattr(cg,AGRAPH,NULL); while(att != NULL) { /* copy this attribute to igraph */ SETGAS(g,att->name,agxget(cg,att)); att = agnxtattr(cg,AGRAPH,att); } /* we keep the graph name using a special attribute */ SETGAS(g,GGEN_GRAPH_NAME_ATTR,agnameof(cg)); /* read vertex properties */ att = agnxtattr(cg,AGNODE,NULL); while(att != NULL) { /* iterate over all vertices for this attribute */ for(v = agfstnode(cg); v; v = agnxtnode(cg,v)) { from = find_id(AGID(v),vertices,vsize); SETVAS(g,att->name,from,agxget(v,att)); } att = agnxtattr(cg,AGNODE,att); } /* we keep each vertex name in a special attribute */ for(v = agfstnode(cg); v; v = agnxtnode(cg,v)) { from = find_id(AGID(v),vertices,vsize); SETVAS(g,GGEN_VERTEX_NAME_ATTR,from,agnameof(v)); } /* read edges properties */ att = agnxtattr(cg,AGEDGE,NULL); while(att != NULL) { /* the only way to iterate over all edges is to iterate * over the vertices */ for(v = agfstnode(cg); v; v = agnxtnode(cg,v)) { from = find_id(AGID(v),vertices,vsize); for(e = agfstout(cg,v); e; e = agnxtout(cg,e)) { to = find_id(AGID(aghead(e)),vertices,vsize); igraph_get_eid(g,&eid,from,to,1,0); SETEAS(g,att->name,eid,agxget(e,att)); } } att = agnxtattr(cg,AGEDGE,att); } goto cleanup; error: igraph_destroy(g); cleanup: igraph_vector_destroy(&vertices); error_de: igraph_vector_destroy(&edges); error_d: agclose(cg); return err; }