void MERFTag::buildMatchTree(Agraph_t* G,Agnode_t* node,Agedge_t* edge,QMap<Agnode_t *,Agnode_t *>* parentNodeMap,QTreeWidgetItem* parentItem, int& id) { QStringList data; data << "Type" << formula->name; QTreeWidgetItem* newItem = new QTreeWidgetItem(parentItem,data); parentItem = newItem; char * writable = strdup(formula->name.toStdString().c_str()); if(node == NULL) { stringstream strs; strs << id; string temp_str = strs.str(); char* nodeID = strdup(temp_str.c_str()); Agnode_t * newNode = agnode(G,nodeID, 1); agset(G,const_cast<char *>("root"),nodeID); id = id+1; agset(newNode,const_cast<char *>("label"),writable); parentNodeMap->insert(newNode,NULL); node = newNode; } else { stringstream strs; strs << id; string temp_str = strs.str(); char* nodeID = strdup(temp_str.c_str()); Agnode_t * newNode = agnode(G,nodeID, 1); id = id+1; agset(newNode,const_cast<char *>("label"),writable); edge = agedge(G, node, newNode, 0, 1); parentNodeMap->insert(newNode, node); node = newNode; } match->buildMatchTree(G,node,edge,parentNodeMap,parentItem,id); }
/* clone_graph: * Create two copies of the argument graph * One is a subgraph, the other is an actual copy since we will be * adding edges to it. */ static Agraph_t* clone_graph(Agraph_t* ing, Agraph_t** xg) { Agraph_t* clone; Agraph_t* xclone; Agnode_t* n; Agnode_t* xn; Agnode_t* xh; Agedge_t* e; Agedge_t* xe; char gname[SMALLBUF]; static int id = 0; sprintf (gname, "_clone_%d", id++); clone = agsubg(ing, gname); sprintf (gname, "_clone_%d", id++); xclone = agopen(gname, ing->kind); for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) { aginsert (clone, n); xn = agnode (xclone, n->name); CLONE(n) = xn; } for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) { xn = CLONE(n); for(e = agfstout(ing, n); e; e = agnxtout(ing, e)) { aginsert (clone, e); xh = CLONE(e->head); xe = agedge (xclone, xn, xh); ORIGE(xe) = e; DEGREE(xn) += 1; DEGREE(xh) += 1; } } *xg = xclone; #ifdef OLD clone = agopen("clone", root->kind); for(n = agfstnode(root); n; n = agnxtnode(root, n)) { cn = agnode(clone, n->name); ND_alg(cn) = DATA(n); BCDONE(cn) = 0; } for(n = agfstnode(root); n; n = agnxtnode(root, n)) { Agnode_t *t = agnode(clone, n); for(e = agfstout(root, n); e; e = agnxtout(root, e)) { Agnode_t *h = agnode(clone, e->head->name); agedge(clone, t, h); } } #endif return clone; }
/* GVNode */ GVNode::GVNode(GVLayout *l, QString name) : GVItem(l) { #ifdef USE_LIBGRAPH_NOT_LIBCGRAPH this->gv_node = agnode(this->layout->getGVGraph(), name.toUtf8().data()); #else this->gv_node = agnode(this->layout->getGVGraph(), name.toUtf8().data(), TRUE); #endif agsafeset(this->gv_node, (char*)"fixedsize", (char*)"true", (char*)""); agsafeset(this->gv_node, (char*)"shape", (char*)"rectangle", (char*)""); }
int GraphvizAdapterImpl::addNode(std::string id) { #if GRAPHVIZ_CGRAPH Agnode_t * n = agnode(g_, (char*)(id.c_str()), 1); #else Agnode_t * n = agnode(g_, (char*)(id.c_str())); #endif assert(n); ++nCount_; nodes_.insert(std::pair<int, Agnode_t*>(nCount_, n)); return nCount_; }
int main(int argc, char** argv) { Agraph_t *g; Agnode_t *n,*m; Agedge_t *e; Agsym_t *a; GVC_t *gvc; /* set up renderer context */ gvc = gvContext(); /* Accept -T and -o options like dot. * Input files are ignored in this demo. */ dotneato_initialize(gvc, argc,argv); /* 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 */ if (!(a = agfindattr(g->proto->n, "color"))) a = agnodeattr(g, "color", ""); agxset(n, a->index, "red"); /* bind graph to GV context - currently must be done before layout */ gvBindContext(gvc,g); /* Compute a layout */ neato_layout(g); /* twopi_layout(g); */ /* dot_layout(g); */ /* Write the graph according to -T and -o options */ dotneato_write(gvc); /* Clean out layout data */ /* neato_cleanup(g); */ /* twopi_cleanup(g); */ /* dot_cleanup(g); */ /* Free graph structures */ agclose(g); /* Clean up output file and errors */ dotneato_terminate(gvc); return 1; }
static void addCutPts(Agraph_t * tree, Agraph_t * blk) { Agnode_t *n; Agnode_t *bn; Agnode_t *cn; bn = agnode(tree, agnameof(blk), 1); for (n = agfstnode(blk); n; n = agnxtnode(blk, n)) { if (Cut(n)) { cn = agnode(tree, agnameof(n), 1); agedge(tree, bn, cn, 0, 1); } } }
Agnode_t *node(Agraph_t *g, char *name) { // creating a protonode is not permitted if (!gvc || (name[0] == '\001' && strcmp (name, "\001proto") == 0)) return NULL; return agnode(g, name); }
/* clustNode: * Generate a special cluster node representing the end node * of an edge to the cluster cg. n is a node whose name is the same * as the cluster cg. clg is the subgraph of all of * the original nodes, which will be deleted later. */ static node_t *clustNode(node_t * n, graph_t * cg, agxbuf * xb, graph_t * clg) { node_t *cn; static int idx = 0; char num[100]; agxbput(xb, "__"); sprintf(num, "%d", idx++); agxbput(xb, num); agxbputc(xb, ':'); agxbput(xb, agnameof(cg)); cn = agnode(agroot(cg), agxbuse(xb), 1); agbindrec(cn, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); SET_CLUST_NODE(cn); agsubnode(cg,cn,1); //aginsert(cg, cn); agsubnode(clg,n,1); //aginsert(clg, n); /* set attributes */ N_label = setAttr(agraphof(cn), cn, "label", "", N_label); N_style = setAttr(agraphof(cn), cn, "style", "invis", N_style); N_shape = setAttr(agraphof(cn), cn, "shape", "box", N_shape); /* N_width = setAttr (cn->graph, cn, "width", "0.0001", N_width); */ return cn; }
/* mapN: * Convert cluster nodes back to ordinary nodes * If n is already ordinary, return it. * Otherwise, we know node's name is "__i:xxx" * where i is some number and xxx is the nodes's original name. * Create new node of name xxx if it doesn't exist and add n to clg * for later deletion. */ static node_t *mapN(node_t * n, graph_t * clg) { node_t *nn; char *name; graph_t *g = agraphof(n); Agsym_t *sym; if (!(IS_CLUST_NODE(n))) return n; agsubnode(clg, n, 1); name = strchr(agnameof(n), ':'); assert(name); name++; if ((nn = agfindnode(g, name))) return nn; nn = agnode(g, name, 1); agbindrec(nn, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); /* Set all attributes to default */ for (sym = agnxtattr(g, AGNODE, NULL); sym; (sym = agnxtattr(g, AGNODE, sym))) { if (agxget(nn, sym) != sym->defval) agxset(nn, sym, sym->defval); } return nn; }
static void cloneSubg (Agraph_t* parent, Agraph_t* sg, Dt_t* emap) { Agraph_t* subg; Agnode_t* t; Agedge_t* e; Agnode_t* newt; Agedge_t* newe; Agraph_t* newg; if (is_a_cluster(sg)) { newg = agsubg (parent, agnameof(sg), 1); parent = newg; for (t = agfstnode(sg); t; t = agnxtnode(sg, t)) { newt = agnode(newg, agnameof(t), 0); agsubnode(newg, newt, 1); /* if e is in sg, both end points are, so we can use out edges */ for (e = agfstout(sg, t); e; e = agnxtout(sg, e)) { newe = mapEdge (emap, e); agsubedge(newg, newe, 1); } } } for (subg = agfstsubg(sg); subg; subg = agnxtsubg(subg)) { cloneSubg(parent, subg, emap); } }
void ImplemGraphviz::creerListeNodes(Graphe* graph) { tableNodes.clear(); vector<Sommet*> liste=graph->getListeSommets(); for(int i=0; i<liste.size(); i++){ Sommet* som=liste[i]; char* nom=(char*)(som->getNom().toStdString().c_str()); Agnode_t* agnod=agnode(G,nom); char* shape=(char*)"shape"; string forme; QStringList listeChoix=graphe->getListeForme(); QString form=som->getForme(); if(listeChoix.contains(form)) forme=form.toStdString(); else forme="ellipse"; char* shapeAttr=(char*)forme.c_str(); agsafeset(agnod,shape,shapeAttr,""); tableNodes.insert(som, agnod); } }
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); }
static graph_t *create_test_graph(void) { #define NUMNODES 5 Agnode_t *node[NUMNODES]; Agedge_t *e; Agraph_t *g; Agraph_t *sg; int j, k; char name[10]; /* Create a new graph */ g = agopen("new_graph", Agdirected,NIL(Agdisc_t *)); /* Add nodes */ for (j = 0; j < NUMNODES; j++) { sprintf(name, "%d", j); node[j] = agnode(g, name, 1); agbindrec(node[j], "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data } /* Connect nodes */ for (j = 0; j < NUMNODES; j++) { for (k = j + 1; k < NUMNODES; k++) { e = agedge(g, node[j], node[k], NULL, 1); agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); //edge custom data } } sg = agsubg (g, "cluster1", 1); agsubnode (sg, node[0], 1); return g; }
static graph_t *create_test_graph(void) { #define NUMNODES 5 Agnode_t *node[NUMNODES]; Agraph_t *g; int j, k; char name[10]; /* Create a new graph */ g = agopen("new_graph", AGDIGRAPH); /* Add nodes */ for (j = 0; j < NUMNODES; j++) { sprintf(name, "%d", j); node[j] = agnode(g, name); } /* Connect nodes */ for (j = 0; j < NUMNODES; j++) { for (k = j + 1; k < NUMNODES; k++) { agedge(g, node[j], node[k]); } } return g; }
/** * Render a tree to tree graph image via graphviz (dot) */ int r3_tree_render_file(const node * tree, const char * format, char * filename) { Agraph_t *g; /* set up a graphviz context - but only once even for multiple graphs */ static GVC_t *gvc; if (!gvc) { gvc = gvContext(); } /* Create a simple digraph */ g = agopen("g", Agdirected, 0); // create self node Agnode_t *ag_root = agnode(g, "{root}", 1); r3_tree_build_ag_nodes(g, ag_root, tree, 0); gvLayout(gvc, g, "dot"); gvRenderFilename(gvc, g, format, filename); gvFreeLayout(gvc, g); agclose(g); return 0; }
/* mapN: * Convert cluster nodes back to ordinary nodes * If n is already ordinary, return it. * Otherwise, we know node's name is "__i:xxx" * where i is some number and xxx is the nodes's original name. * Create new node of name xxx if it doesn't exist and add n to clg * for later deletion. */ static node_t *mapN(node_t * n, graph_t * clg) { extern Agdict_t *agdictof(void *); node_t *nn; char *name; graph_t *g = n->graph; Agdict_t *d; Agsym_t **list; Agsym_t *sym; if (!(IS_CLUST_NODE(n))) return n; aginsert(clg, n); name = strchr(n->name, ':'); assert(name); name++; if ((nn = agfindnode(g, name))) return nn; nn = agnode(g, name); /* Set all attributes to default */ d = agdictof(n); list = d->list; while ((sym = *list++)) { /* Can use pointer comparison because of ref strings. */ if (agxget(nn, sym->index) != sym->value) agxset(nn, sym->index, sym->value); } return nn; }
/* clustNode: * Generate a special cluster node representing the end node * of an edge to the cluster cg. n is a node whose name is the same * as the cluster cg. clg is the subgraph of all of * the original nodes, which will be deleted later. */ static node_t *clustNode(node_t * n, graph_t * cg, agxbuf * xb, graph_t * clg) { node_t *cn; static int idx = 0; char num[100]; agxbput(xb, "__"); sprintf(num, "%d", idx++); agxbput(xb, num); agxbputc(xb, ':'); agxbput(xb, cg->name); cn = agnode(cg->root, agxbuse(xb)); SET_CLUST_NODE(cn); aginsert(cg, cn); aginsert(clg, n); /* set attributes */ N_label = setAttr(cn->graph, cn, "label", "", N_label); N_style = setAttr(cn->graph, cn, "style", "invis", N_style); N_shape = setAttr(cn->graph, cn, "shape", "box", N_shape); /* N_width = setAttr (cn->graph, cn, "width", "0.0001", N_width); */ return cn; }
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); }
static node_t *newNode(graph_t * g) { static int id = 0; char buf[100]; sprintf(buf, "n%d", id++); return agnode(g, buf); }
/* 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; }
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; }
/* mkDeriveNode: * Constructor for a node in a derived graph. * Allocates dndata. */ static node_t *mkDeriveNode(graph_t * dg, char *name) { node_t *dn; dn = agnode(dg, name,1); agbindrec(dn, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data ND_alg(dn) = (void *) NEW(dndata); /* free in freeDeriveNode */ ND_pos(dn) = N_GNEW(GD_ndim(dg), double); /* fprintf (stderr, "Creating %s\n", dn->name); */ return dn; }
/* 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; }
/* mkMCNode: returns a new node unless a name is provided, depending on the node type either a temporary node or a temp label node is returned otherwise a regular node is returned. it is caller's responsibility to set necessary edges */ Agnode_t *mkMCNode (Agraph_t * g, int type, char *name) { static int k = 0; Agnode_t *rv; char buf[512]; switch (type) { case INTNODE: sprintf(buf, "____tempN%d", k++); /*unique node name for internal nodes */ rv = agnode(g, buf, 1); break; case LBLNODE: sprintf(buf, "____lblN%d", k++); /*unique node name for labels */ rv = agnode(g, buf, 1); break; default: rv = agnode(g, name, 1); } agbindrec(rv, "mcnodeinfo_t", sizeof(mcnodeinfo_t), TRUE); MND_type(rv) = type; return rv; }
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; }
/* makeDerivedNode: * Make a node in the derived graph, with the given name. * orig points to what it represents, either a real node or * a cluster. Copy size info from original node; needed for * adjustNodes and packSubgraphs. */ static node_t *makeDerivedNode(graph_t * dg, char *name, int isNode, void *orig) { node_t *n = agnode(dg, name,1); agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data ND_alg(n) = (void *) NEW(cdata); if (isNode) { ND_pos(n) = N_NEW(Ndim, double); ND_lw(n) = ND_lw((node_t *) orig); ND_rw(n) = ND_rw((node_t *) orig); ND_ht(n) = ND_ht((node_t *) orig); ORIGN(n) = (node_t *) orig; } else
/* 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 *QGVScene::addNode(const QString &label) { Agnode_t *node = agnode(_graph->graph(), NULL, TRUE); if(node == NULL) { qWarning()<<"Invalid node :"<<label; return 0; } QGVNode *item = new QGVNode(new QGVNodePrivate(node), this); item->setLabel(label); addItem(item); _nodes.append(item); return item; }
int main(int argc, char **argv) { Agraph_t *g; Agnode_t *n, *m; Agedge_t *e; GVC_t *gvc; /* set up a graphviz context */ gvc = gvContext(); /* parse command line args - minimally argv[0] sets layout engine */ gvParseArgs(gvc, argc, argv); /* 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", ""); /* Compute a layout using layout engine from command line args */ gvLayoutJobs(gvc, g); /* Write the graph according to -T and -o options */ gvRenderJobs(gvc, g); /* Free layout data */ gvFreeLayout(gvc, g); /* Free graph structures */ agclose(g); /* close output file, free context, and return number of errors */ return (gvFreeContext(gvc)); }
/* bind/construct representative of an external endpoint to a model graph */ static rep_t model_extnode(Agraph_t *model, Agnode_t *orig) { Agnode_t *v; rep_t rep; rep = association(model,orig); if (rep.type) return rep; /* assume endpoint is represented by one node, even if orig is multi-rank */ rep.p = v = agnode(model,orig->name); rep.type = EXTNODE; ND_rank(v) = ND_rank(orig); /* should be ND_rank(orig)+ranksize(orig)? */ associate(model,orig,rep); return rep; }