Exemple #1
0
static int dfs(Agraph_t * g, Agnode_t * t, int hasCycle)
{
    Agedge_t *e;
    Agedge_t *f;
    Agnode_t *h;

    ND_mark(t) = 1;
    ND_onstack(t) = 1;
    for (e = agfstout(g, t); e; e = f) {
	f = agnxtout(g, e);
	if (e->tail == e->head)
	    continue;
	h = e->head;
	if (ND_onstack(h)) {
	    if (AG_IS_STRICT(g)) {
		if (agfindedge(g, h, t) == 0)
		    addRevEdge(g, e);
	    } else
		addRevEdge(g, e);
	    agdelete(g, e);
	    hasCycle = 1;
	} else if (ND_mark(h) == 0)
	    hasCycle = dfs(g, h, hasCycle);
    }
    ND_onstack(t) = 0;
    return hasCycle;
}
Agedge_t *findedge(Agnode_t *t, Agnode_t *h)
{
    if (!t || !h)
        return NULL;
    if (AGTYPE(t) == AGRAPH || AGTYPE(h) == AGRAPH)
	return NULL;
    return agfindedge(agraphof(t), t, h);
}
Exemple #3
0
edge_t	* debug_getedge(graph_t *g, char *s0, char *s1)
{
	node_t	*n0,*n1;
	n0 = agfindnode(g,s0);
	n1 = agfindnode(g,s1);
	if (n0 && n1) return agfindedge(g,n0,n1);
	else return NULL;
}
Exemple #4
0
static void reverse_edge(graph_t *g, edge_t *e)
{
	edge_t	*rev;

	rev = agfindedge(g,e->head,e->tail);
	if (!rev) rev = agedge(g,e->head,e->tail);
	merge(rev,ED_minlen(e),ED_weight(e));
	agdelete(g,e);
}
Exemple #5
0
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 (ED_to_virt(e))
		continue;

	    /* skip edges that we want to ignore in this phase */
	    if (nonconstraint_edge(e))
		continue;

	    t = UF_find(agtail(e));
	    h = UF_find(aghead(e));

	    /* skip self, flat, and intra-cluster edges */
	    if (t == h)
		continue;


	    /* inter-cluster edges require special treatment */
	    if (ND_clust(t) || ND_clust(h)) {
		interclust1(g, agtail(e), aghead(e), e);
		continue;
	    }

	    if ((rep = find_fast_edge(t, h)))
		merge_oneway(e, rep);
	    else
		virtual_edge(t, h, e);

#ifdef NOTDEF
	    if ((t == agtail(e)) && (h == aghead(e))) {
		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 && (ED_to_virt(f) == 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
	}
    }
}
Exemple #6
0
/* a given edge can have several other edges (forward or backward)
   between the same endpoints.  here, we choose one of these to be
	 the canonical representative of those edges. */
static Agedge_t* canonical_edge(Agedge_t* e)
{
	Agraph_t	*g;
	Agedge_t	*canon;

	g = e->tail->graph;
	if (ND_rank(e->head) > ND_rank(e->tail))
		canon = agfindedge(g,e->tail,e->head);
	else {
		if 
	}
}
Exemple #7
0
static void
validate(graph_t * g)
{
    node_t *n;
    edge_t *e;
    int    i, cnt;
  
    cnt = 0;
    for (n = GD_nlist(g);n; n = ND_next(n)) {
      assert(outdegree(g,n) == ND_out(n).size);
      for (i = 0; (e = ND_out(n).list[i]); i++) {
        assert(agtail(e) == n);
        assert( e == agfindedge(g, n, aghead(e))); 
      }
      assert(indegree(g,n) == ND_in(n).size);
      for (i = 0; (e = ND_in(n).list[i]); i++) {
        assert(aghead(e) == n);
        assert( e == agfindedge(g, agtail(e), n)); 
      }
      cnt++;
    }

    assert (agnnodes(g) == cnt); 
}
Exemple #8
0
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;
}
Exemple #9
0
Agnode_t *nexttail(Agnode_t *n, Agnode_t *t)
{
    Agedge_t *e;

    if (!n || !t)
	return NULL;
    e = agfindedge(n->graph, t, n);
    if (!e)
	return NULL;
    do {
	e = agnxtout(n->graph, e);
	if (!e)
	    return NULL;
    } while (e->tail == t);
    return e->tail;
}
Exemple #10
0
static void checkChain(graph_t * g)
{
    node_t *t;
    node_t *h;
    edge_t *e;
    t = GD_nlist(g);
    for (h = ND_next(t); h; h = ND_next(h)) {
	if (!agfindedge(g, t, h)) {
	    e = agedge(g, t, h);
	    ED_minlen(e) = 0;
	    elist_append(e, ND_out(t));
	    elist_append(e, ND_in(h));
	}
	t = h;
    }
}
Agnode_t *nexttail(Agnode_t *n, Agnode_t *t)
{
    Agedge_t *e;
    Agraph_t *g;

    if (!n || !t)
        return NULL;
    g = agraphof(n);
    e = agfindedge(g, t, n);
    if (!e)
        return NULL;
    do {
        e = agnxtin(g, e);
        if (!e)
            return NULL;
    } while (agtail(e) == t);
    return agtail(e);
}
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);
}
Exemple #13
0
static void checkChain(graph_t * g)
{
    node_t *t;
    node_t *h;
    edge_t *e;
    t = GD_nlist(g);
    for (h = ND_next(t); h; h = ND_next(h)) {
	if (!agfindedge(g, t, h)) {
#ifdef WITH_CGRAPH
            e = agedge(g, t, h, NULL, 1);
	    agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE);
#else
	    e = agedge(g, t, h);
#endif
	    ED_minlen(e) = 0;
	    elist_append(e, ND_out(t));
	    elist_append(e, ND_in(h));
	}
	t = h;
    }
}
Exemple #14
0
Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg)
{
    Agraph_t *mg;
    Agnode_t *ng, *nsg;
    Agedge_t *e;

    if (!g || !sg)
	return NULL;
    ng = g->meta_node;
    nsg = sg->meta_node;
    if (!ng || !nsg) 
	return NULL;
    mg = ng->graph;
    if (!mg) 
	return NULL;
    e = agfindedge(mg, nsg, ng);
    if (!e) 
	return NULL;
    e = agnxtin(mg, e);
    if (!e) 
	return NULL;
    return agusergraph(e->tail);
}
Exemple #15
0
/*-------------------------------------------------------------------------*\
 * 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;
  }
}
Exemple #16
0
Agedge_t *findedge(Agnode_t *t, Agnode_t *h)
{
    if (!t || !h)
	return NULL;
    return agfindedge(t->graph, t, h);
}
Exemple #17
0
/* mkNConstraintG:
 * Similar to mkConstraintG, except it doesn't enforce orthogonal
 * ordering. If there is overlap, as defined by intersect, the
 * nodes will kept/pushed apart in the current order. If not, no
 * constraint is enforced. If a constraint edge is added, and it
 * corresponds to a real edge, we increase the weight in an attempt
 * to keep the resulting shift short. 
 */
static graph_t *mkNConstraintG(graph_t * g, Dt_t * list,
			      intersectfn intersect, distfn dist)
{
    nitem *p;
    nitem *nxp;
    node_t *n;
    edge_t *e;
    node_t *lastn = NULL;
#ifndef WITH_CGRAPH
    graph_t *cg = agopen("cg", AGDIGRAPHSTRICT);
#else
    graph_t *cg = agopen("cg", Agstrictdirected, NIL(Agdisc_t *));
    agbindrec(cg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE);  // graph custom data
#endif

    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
#ifndef WITH_CGRAPH
	n = agnode(cg, agnameof(p->np));	/* FIX */
#else
	n = agnode(cg, agnameof(p->np), 1);      /* FIX */
	agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data
#endif
	ND_alg(n) = p;
	p->cnode = n;
	alloc_elist(0, ND_in(n));
	alloc_elist(0, ND_out(n));
	if (lastn) {
	    ND_next(lastn) = n;
	    lastn = n;
	} else {
	    lastn = GD_nlist(cg) = n;
	}
    }
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	for (nxp = (nitem *) dtlink(link, (Dtlink_t *) p); nxp;
	     nxp = (nitem *) dtlink(list, (Dtlink_t *) nxp)) {
	    e = NULL;
	    if (intersect(p, nxp)) {
	        double delta = dist(&p->bb, &nxp->bb);
#ifndef WITH_CGRAPH
	        e = agedge(cg, p->cnode, nxp->cnode);
#else
	        e = agedge(cg, p->cnode, nxp->cnode, NULL, 1);
		agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE);   // edge custom data
#endif
		assert (delta <= 0xFFFF);
		ED_minlen(e) = delta;
		ED_weight(e) = 1;
	    }
	    if (e && agfindedge(g,p->np, nxp->np)) {
		ED_weight(e) = 100;
            }
#if 0
	    if (agfindedge(g,p->np, nxp->np)) {
		if (e == NULL)
	            e = agedge(cg, p->cnode, nxp->cnode);
		ED_weight(e) = 100;
                /* If minlen < SCALE, the nodes can't conflict or there's
                 * an overlap but it will be removed in the orthogonal pass.
                 * So we just keep the node's basically where they are.
                 */
		if (SCALE > ED_minlen(e))
		    ED_minlen(e) = SCALE;
	    }
#endif
	}
    }
   
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	n = p->cnode;
	for (e = agfstout(cg,n); e; e = agnxtout(cg,e)) {
	    elist_append(e, ND_out(n));
	    elist_append(e, ND_in(aghead(e)));
	}
    }

    /* We could remove redundant constraints here. However, the cost of doing 
     * this may be a good deal more than the time saved in network simplex. 
     * Also, if the graph is changed, the ND_in and ND_out data has to be 
     * updated.
     */
    return cg;
}
Exemple #18
0
void class2(graph_t* g)
{
	int		c;
	node_t	*n,*t,*h;
	edge_t	*e,*prev,*opp;

	g->u.nlist = NULL;

	g->u.n_nodes = 0;	/* new */

	mark_clusters(g);
	for (c = 1; c <= g->u.n_cluster; c++)
		build_skeleton(g,g->u.clust[c]);
	for (n = agfstnode(g); n; n = agnxtnode(g,n))
		for (e = agfstout(g,n); e; e = agnxtout(g,e)) {
			if (e->head->u.weight_class <= 2) e->head->u.weight_class++;
			if (e->tail->u.weight_class <= 2) e->tail->u.weight_class++;
	}

	for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
		if ((n->u.clust == NULL) && (n == UF_find(n))) {fast_node(g,n); g->u.n_nodes++;}
		prev = NULL;
		for (e = agfstout(g,n); e; e = agnxtout(g,e)) {

				/* already processed */
			if (e->u.to_virt) continue;

				/* edges involving sub-clusters of g */
			if (is_cluster_edge(e)) {
				/* following is new cluster multi-edge code */
				if (mergeable(prev,e)) {
					if (prev->u.to_virt) { 
						merge_chain(g,e,prev->u.to_virt,FALSE);
						other_edge(e);
					}
					else if (e->tail->u.rank == e->head->u.rank) {
						merge_oneway(e,prev);
						other_edge(e);
					}
					/* else is an intra-cluster edge */
					continue;
				}
				interclrep(g,e);
				prev = e;
				continue;
			}
				/* merge multi-edges */
			if (prev && (e->tail == prev->tail) && (e->head == prev->head)) {
				if (e->tail->u.rank == e->head->u.rank) {
					merge_oneway(e,prev);
					other_edge(e);
					continue;
				}
				if ((e->u.label == NULL) && (prev->u.label == NULL) && ports_eq(e,prev)) {
					if (Concentrate) 
						e->u.edge_type = IGNORED;
					else{
					merge_chain(g,e,prev->u.to_virt,TRUE);
					other_edge(e);
					}
					continue;
				}
				/* parallel edges with different labels fall through here */
			}

				/* self edges */
			if (e->tail == e->head) {
				other_edge(e);
				prev = e;
				continue;
			}

			t = UF_find(e->tail);
			h = UF_find(e->head);

				/* non-leader leaf nodes */
			if ((e->tail != t) || (e->head != h)) {
					/* ### need to merge stuff */
				continue;	
			}


				/* flat edges */
			if (e->tail->u.rank == e->head->u.rank) {
				flat_edge(g,e);
				prev = e;
				continue;
			}

				/* forward edges */
			if (e->head->u.rank > e->tail->u.rank) {
				make_chain(g,e->tail,e->head,e);
				prev = e;
				continue;
			}

				/* backward edges */
			else {
				/*other_edge(e);*/
				if ((opp = agfindedge(g,e->head,e->tail))) {
					/* shadows a forward edge */
					if (opp->u.to_virt == NULL)
						make_chain(g,opp->tail,opp->head,opp);
					if ((e->u.label == NULL) && (opp->u.label == NULL) && ports_eq(e,opp)) {
						if (Concentrate) {
							e->u.edge_type = IGNORED;
							opp->u.conc_opp_flag = TRUE;
						}
						else{	/* see above.  this is getting out of hand */
						other_edge(e);
						merge_chain(g,e,opp->u.to_virt,TRUE);
						}
						continue;
					}
				}
				make_chain(g,e->head,e->tail,e);
				prev = e;
			}
		}
	}
	/* since decompose() is not called on subgraphs */
	if (g != g->root) {
		g->u.comp.list = ALLOC(1,g->u.comp.list,node_t*);
		g->u.comp.list[0] = g->u.nlist;
	}
Exemple #19
0
/* find_pair_edges:
 */
static void find_pair_edges(Agraph_t * g, Agnode_t * n, Agraph_t * outg)
{
    Agnode_t **neighbors_with;
    Agnode_t **neighbors_without;

    Agedge_t *e;
    Agedge_t *ep;
    Agedge_t *ex;
    Agnode_t *n1;
    Agnode_t *n2;
    int has_pair_edge;
    int diff;
    int has_pair_count = 0;
    int no_pair_count = 0;
    int node_degree;
    int edge_cnt = 0;

    node_degree = DEGREE(n);
    neighbors_with = N_GNEW(node_degree, Agnode_t *);
    neighbors_without = N_GNEW(node_degree, Agnode_t *);

    for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
	n1 = e->head;
	if (n1 == n)
	    n1 = e->tail;
	has_pair_edge = 0;
	for (ep = agfstedge(g, n); ep; ep = agnxtedge(g, ep, n)) {
	    if (ep == e)
		continue;
	    n2 = ep->head;
	    if (n2 == n)
		n2 = ep->tail;
	    ex = agfindedge(g, n1, n2);
	    if (ex) {
		has_pair_edge = 1;
		if (n1 < n2) {	/* count edge only once */
		    edge_cnt++;
		    if (ORIGE(ex)) {
			agdelete(outg, ORIGE(ex));
			ORIGE(ex) = 0;	/* delete only once */
		    }
		}
	    }
	}
	if (has_pair_edge) {
	    neighbors_with[has_pair_count] = n1;
	    has_pair_count++;
	} else {
	    neighbors_without[no_pair_count] = n1;
	    no_pair_count++;
	}
    }

    diff = node_degree - 1 - edge_cnt;
    if (diff > 0) {
	int mark;
	Agnode_t *hp;
	Agnode_t *tp;

	if (diff < no_pair_count) {
	    for (mark = 0; mark < no_pair_count; mark += 2) {
		if ((mark + 1) >= no_pair_count)
		    break;
		tp = neighbors_without[mark];
		hp = neighbors_without[mark + 1];
		agedge(g, tp, hp);
		DEGREE(tp)++;
		DEGREE(hp)++;
		diff--;
	    }

	    mark = 2;
	    while (diff > 0) {
		tp = neighbors_without[0];
		hp = neighbors_without[mark];
		agedge(g, tp, hp);
		DEGREE(tp)++;
		DEGREE(hp)++;
		mark++;
		diff--;
	    }
	}

	else if (diff == no_pair_count) {
	    tp = neighbors_with[0];
	    for (mark = 0; mark < no_pair_count; mark++) {
		hp = neighbors_without[mark];
		agedge(g, tp, hp);
		DEGREE(tp)++;
		DEGREE(hp)++;
	    }
	}
    }

    free(neighbors_without);
    free(neighbors_with);
}