Example #1
0
/* sets ports that represent connections to subclusters */
static void subclustports(Agraph_t *ug)
{
	Agraph_t	*model, *clustmodel;
	Agnode_t	*x;
	Agedge_t	*e;
	vpath_t		*p;
	Dict_t		*d;
	double		frac;

	/* walk all the paths */
	model = GD_model(ug);
	d = repdict(model);
	for (p = dtfirst(d); p; p = dtnext(d,p)) {
		if ((ND_type(p->v[p->low])) == NODETYPE_CNODE) {
			x = p->v[p->low];
			clustmodel = GD_model(ND_cluster(x));
			frac = (ND_order(x) + 1) / GD_rank(clustmodel)[ND_rank(x)].n;
			e = p->e[p->low];
			ED_tailport(e).p.x = 2 * PORTCLAMP * (frac - 0.5) + p->tailport;
		}
		if ((ND_type(p->v[p->high])) == NODETYPE_CNODE) {
			x = p->v[p->high];
			clustmodel = GD_model(ND_cluster(x));
			frac = (ND_order(x) + 1) / GD_rank(clustmodel)[ND_rank(x)].n;
			e = p->e[p->high-1];
			ED_headport(e).p.x = 2 * PORTCLAMP * (frac - 0.5) + p->headport;
		}
	}
}
Example #2
0
int transpose_onerank(Agraph_t* g, int r, boolean reverse)
{
	int     i,c0,c1,rv;
	node_t  *v,*w;

	rv = 0;
	GD_rank(g)[r].candidate = FALSE;
	for (i = leftmost(g,r); i < rightmost(g,r); i++) {
		v = GD_rank(g)[r].v[i];
		w = GD_rank(g)[r].v[i+1];
		assert (ND_order(v) < ND_order(w));
		if (left2right(g,v,w)) continue;
		c0 = c1 = 0;
		if (r > GD_minrank(g)) {
			c0 += in_cross(v,w);
			c1 += in_cross(w,v);
		}
		if (r < GD_maxrank(g)) {
			c0 += out_cross(v,w);
			c1 += out_cross(w,v);
		}
		if ((c1 < c0) || ((c0 > 0) && reverse && (c1 == c0))) {
			exchange(g,v,w);
			rv += (c0 - c1);
		}
	}
	return rv;
}
Example #3
0
static void infuse(graph_t * g, node_t * n)
{
    node_t *lead;

    lead = GD_rankleader(g)[ND_rank(n)];
    if ((lead == NULL) || (ND_order(lead) > ND_order(n)))
	GD_rankleader(g)[ND_rank(n)] = n;
}
Example #4
0
static void 
merge_ranks(graph_t * subg)
{
    int i, d, r, pos, ipos;
    node_t *v;
    graph_t *root;

    root = agroot(subg);
    if (GD_minrank(subg) > 0)
#ifndef WITH_CGRAPH
	ND_rank(root)[GD_minrank(subg) - 1].valid = FALSE;
#else /* WITH_CGRAPH */
	GD_rank(root)[GD_minrank(subg) - 1].valid = FALSE;
#endif /* WITH_CGRAPH */
    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
	d = GD_rank(subg)[r].n;
#ifndef WITH_CGRAPH
	ipos = pos = GD_rankleader(subg)[r]->u.order;
#else /* WITH_CGRAPH */
	ipos = pos = ND_order(GD_rankleader(subg)[r]);
#endif /* WITH_CGRAPH */
	make_slots(root, r, pos, d);
	for (i = 0; i < GD_rank(subg)[r].n; i++) {
#ifndef WITH_CGRAPH
	    v = ND_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i];
#else /* WITH_CGRAPH */
	    v = GD_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i];
#endif /* WITH_CGRAPH */
	    ND_order(v) = pos++;
#ifndef WITH_CGRAPH
	    v->graph = subg->root;
#else /* WITH_CGRAPH */
	/* real nodes automatically have v->root = root graph */
	    if (ND_node_type(v) == VIRTUAL)
		v->root = root;
#endif /* WITH_CGRAPH */
	    delete_fast_node(subg, v);
	    fast_node(agroot(subg), v);
	    GD_n_nodes(agroot(subg))++;
	}
#ifndef WITH_CGRAPH
	GD_rank(subg)[r].v = ND_rank(root)[r].v + ipos;
	ND_rank(root)[r].valid = FALSE;
#else /* WITH_CGRAPH */
	GD_rank(subg)[r].v = GD_rank(root)[r].v + ipos;
	GD_rank(root)[r].valid = FALSE;
#endif /* WITH_CGRAPH */
    }
    if (r < GD_maxrank(root))
	GD_rank(root)[r].valid = FALSE;
    GD_expanded(subg) = TRUE;
}
Example #5
0
static int presort_cmpf(const void *arg0, const void *arg1)
{
	Agnode_t	*n0, *n1;
	Agraph_t	*c0, *c1;

	n0 = *(Agnode_t**)arg0;
	n1 = *(Agnode_t**)arg1;
	c0 = ND_cluster(n0);
	c1 = ND_cluster(n1);
	if (c0 == c1) return 0;
	assert(ND_rank(n0) == ND_rank(n1));
	n0 = GD_skel(c0)->v[ND_rank(n0)];
	n1 = GD_skel(c1)->v[ND_rank(n1)];
	return ND_order(n0) - ND_order(n1);
}
Example #6
0
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;
}
Example #7
0
/* Execute union commands for "same rank" subgraphs and clusters. */
static void 
collapse_sets(graph_t *rg, graph_t *g)
{
    int c;
    graph_t  *subg;
#ifdef OBSOLETE
    node_t *n;
#endif

    for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
	c = rank_set_class(subg);
	if (c) {
	    if ((c == CLUSTER) && CL_type == LOCAL)
		collapse_cluster(rg, subg);
	    else
		collapse_rankset(rg, subg, c);
	}
	else collapse_sets(rg, subg);

#ifdef OBSOLETE
 Collapsing leaves is currently obsolete

	/* mark nodes with ordered edges so their leaves are not collapsed */
	if (agget(subg, "ordering"))
	    for (n = agfstnode(subg); n; n = agnxtnode(subg, n))
		ND_order(n) = 1;
#endif
    }
}
Example #8
0
static void restorebest(graph_t *g)
{
	Agnode_t	*n;
	int			i;

	for (i = GD_minrank(g); i <= GD_maxrank(g); i++) 
		GD_rank(g)[i].changed = FALSE;
	for (n = agfstnode(g); n; n = agnxtnode(g,n))  {
		if (ND_order(n) != ND_saveorder(n)) {
			invalidate(g,ND_rank(n));
			GD_rank(g)[i].changed = TRUE;
			ND_order(n) = ND_saveorder(n);
		}
	}
	for (i = GD_minrank(g); i <= GD_maxrank(g); i++)  {
		if (GD_rank(g)[i].changed)
			qsort(GD_rank(g)[i].v,GD_rank(g)[i].n,sizeof(Agnode_t*),ND_order_cmpf);
	}
}
Example #9
0
static void install(Agraph_t *g, Agnode_t *n)
{
	int				rank;
	rank_t		*r;

	rank = ND_rank(n);
	r = &GD_rank(g)[rank];
	r->v[r->n] = n;
	ND_order(n) = r->n++;
}
Example #10
0
static void rebuild_vlists(graph_t * g)
{
    int c, i, r, maxi;
    node_t *n, *lead;
    edge_t *e, *rep;

    for (r = GD_minrank(g); r <= GD_maxrank(g); r++)
	GD_rankleader(g)[r] = NULL;

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	infuse(g, n);
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    for (rep = e; ED_to_virt(rep); rep = ED_to_virt(rep));
	    while (ND_rank(rep->head) < ND_rank(e->head)) {
		infuse(g, rep->head);
		rep = ND_out(rep->head).list[0];
	    }
	}
    }

    for (r = GD_minrank(g); r <= GD_maxrank(g); r++) {
	lead = GD_rankleader(g)[r];
	if (ND_rank(g->root)[r].v[ND_order(lead)] != lead)
	    abort();
	GD_rank(g)[r].v =
	    ND_rank(g->root)[r].v + GD_rankleader(g)[r]->u.order;
	maxi = -1;
	for (i = 0; i < GD_rank(g)[r].n; i++) {
	    if ((n = GD_rank(g)[r].v[i]) == NULL)
		break;
	    if (ND_node_type(n) == NORMAL) {
		if (agcontains(g, n))
		    maxi = i;
		else
		    break;
	    } else {
		edge_t *e;
		for (e = ND_in(n).list[0]; e && ED_to_orig(e);
		     e = ED_to_orig(e));
		if (e && (agcontains(g, e->tail))
		    && agcontains(g, e->head))
		    maxi = i;
	    }
	}
	if (maxi == -1)
	    agerr(AGWARN, "degenerate concentrated rank %s,%d\n", g->name,
		  r);
	GD_rank(g)[r].n = maxi + 1;
    }

    for (c = 1; c <= GD_n_cluster(g); c++)
	rebuild_vlists(GD_clust(g)[c]);
}
Example #11
0
static void mergevirtual(graph_t * g, int r, int lpos, int rpos, int dir)
{
    int i, k;
    node_t *left, *right;
    edge_t *e, *f, *e0;

    left = GD_rank(g)[r].v[lpos];
    /* merge all right nodes into the leftmost one */
    for (i = lpos + 1; i <= rpos; i++) {
	right = GD_rank(g)[r].v[i];
	if (dir == DOWN) {
	    while ((e = ND_out(right).list[0])) {
		for (k = 0; (f = ND_out(left).list[k]); k++)
		    if (f->head == e->head)
			break;
		if (f == NULL)
		    f = virtual_edge(left, e->head, e);
		while ((e0 = ND_in(right).list[0])) {
		    merge_oneway(e0, f);
		    /*ED_weight(f) += ED_weight(e0); */
		    delete_fast_edge(e0);
		}
		delete_fast_edge(e);
	    }
	} else {
	    while ((e = ND_in(right).list[0])) {
		for (k = 0; (f = ND_in(left).list[k]); k++)
		    if (f->tail == e->tail)
			break;
		if (f == NULL)
		    f = virtual_edge(e->tail, left, e);
		while ((e0 = ND_out(right).list[0])) {
		    merge_oneway(e0, f);
		    delete_fast_edge(e0);
		}
		delete_fast_edge(e);
	    }
	}
	assert(ND_in(right).size + ND_out(right).size == 0);
	delete_fast_node(g, right);
    }
    k = lpos + 1;
    i = rpos + 1;
    while (i < GD_rank(g)[r].n) {
	node_t *n;
	n = GD_rank(g)[r].v[k] = GD_rank(g)[r].v[i];
	ND_order(n) = k;
	k++;
	i++;
    }
    GD_rank(g)[r].n = k;
    GD_rank(g)[r].v[k] = NULL;
}
Example #12
0
static void savebest(graph_t *g)
{
	int		nc;
	Agnode_t	*n;

	nc = crossings(g);
	if (nc < GD_bestcrossings(g)) {
		for (n = agfstnode(g); n; n = agnxtnode(g,n))
			ND_saveorder(n) = ND_order(n);
		GD_bestcrossings(g) = nc;
		GD_lastwin(g) = GD_pass(g);
	}
}
Example #13
0
static void presort(Agraph_t *ug)
{
	int		r;
	int		i;
	Agraph_t	*mg;

	if (ug == ug->root) return;
	mg = GD_model(ug);
	for (r = GD_minrank(mg); r <= GD_maxrank(mg); r++) {
		qsort(GD_rank(mg)[r].v,GD_rank(mg)[r].n,sizeof(Agnode_t*),presort_cmpf);
		for (i = leftmost(mg,r); i < rightmost(mg,r); i++)
			ND_order(GD_rank(mg)[r].v[i]) = i;
	}
}
Example #14
0
static void
attach_phase_attrs (Agraph_t * g, int maxphase)
{
    Agsym_t* rk = agnodeattr(g,"rank","");
    Agsym_t* order = agnodeattr(g,"order","");
    Agnode_t* n;
    char buf[BUFSIZ];

    for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
	if (maxphase >= 1) {
	    sprintf(buf, "%d", ND_rank(n));
	    ag_xset(n,rk,buf);
	}
	if (maxphase >= 2) {
	    sprintf(buf, "%d", ND_order(n));
	    ag_xset(n,order,buf);
	}
    }
}
Example #15
0
File: rank.c Project: aosm/graphviz
int rank_set_class(graph_t* g)
{
	static char	*name[] = {"same","min","source","max","sink",NULL};
	static int	class[] = {SAMERANK,MINRANK,SOURCERANK,MAXRANK,SINKRANK,0};
	int		val;

	if (is_cluster(g)) return CLUSTER;
	val = maptoken(agget(g,"rank"),name,class);
	GD_set_type(g) = val;
	return val;
}

/* Execute union commands for "same rank" subgraphs and clusters. */
void collapse_sets(graph_t* g)
{
	int			c;
	graph_t		*mg,*subg;
	node_t		*mn,*n;
	edge_t		*me;

	mg = g->meta_node->graph;
	for (me = agfstout(mg,g->meta_node); me; me = agnxtout(mg,me)) {
		mn = me->head;
		subg = agusergraph(mn);

		c = rank_set_class(subg);
		if (c) {
			if ((c == CLUSTER) && CL_type == LOCAL) collapse_cluster(g,subg);
			else collapse_rankset(g,subg,c);
		}

		/* mark nodes with ordered edges so their leaves are not collapsed */
		if (agget(subg,"ordering"))
			for (n = agfstnode(subg); n; n = agnxtnode(subg,n)) ND_order(n) = 1;
	}
}
Example #16
0
/* swaps two nodes in the same level */
static void exchange(Agraph_t *g, Agnode_t *u, Agnode_t *v)
{
	rank_t	*r;
	int			ui,vi,rank;

	assert(ND_rank(u) == ND_rank(v));
	rank = ND_rank(u);
	r = &GD_rank(g)[rank];
	ui = ND_order(u);
	vi = ND_order(v);
	ND_order(v) = ui;
	ND_order(u) = vi;
	r->v[ND_order(u)] = u;
	r->v[ND_order(v)] = v;
	r->crossing_cache.valid = FALSE;
	r->changed = TRUE;
	r->candidate = TRUE;	/* old dot had this.  i have qualms. sn */
	invalidate(g,rank);
}
Example #17
0
/* make d slots starting at position pos (where 1 already exists) */
static void 
make_slots(graph_t * root, int r, int pos, int d)
{
    int i;
    node_t *v, **vlist;
#ifndef WITH_CGRAPH
    vlist = ND_rank(root)[r].v;
#else /* WITH_CGRAPH */
    vlist = GD_rank(root)[r].v;
#endif /* WITH_CGRAPH */
    if (d <= 0) {
#ifndef WITH_CGRAPH
	for (i = pos - d + 1; i < ND_rank(root)[r].n; i++) {
#else /* WITH_CGRAPH */
	for (i = pos - d + 1; i < GD_rank(root)[r].n; i++) {
#endif /* WITH_CGRAPH */
	    v = vlist[i];
	    ND_order(v) = i + d - 1;
	    vlist[ND_order(v)] = v;
	}
#ifndef WITH_CGRAPH
	for (i = ND_rank(root)[r].n + d - 1; i < ND_rank(root)[r].n; i++)
#else /* WITH_CGRAPH */
	for (i = GD_rank(root)[r].n + d - 1; i < GD_rank(root)[r].n; i++)
#endif /* WITH_CGRAPH */
	    vlist[i] = NULL;
    } else {
/*assert(ND_rank(root)[r].n + d - 1 <= ND_rank(root)[r].an);*/
#ifndef WITH_CGRAPH
	for (i = ND_rank(root)[r].n - 1; i > pos; i--) {
#else /* WITH_CGRAPH */
	for (i = GD_rank(root)[r].n - 1; i > pos; i--) {
#endif /* WITH_CGRAPH */
	    v = vlist[i];
	    ND_order(v) = i + d - 1;
	    vlist[ND_order(v)] = v;
	}
	for (i = pos + 1; i < pos + d; i++)
	    vlist[i] = NULL;
    }
#ifndef WITH_CGRAPH
    ND_rank(root)[r].n += d - 1;
#else /* WITH_CGRAPH */
    GD_rank(root)[r].n += d - 1;
#endif /* WITH_CGRAPH */
}

static node_t* 
clone_vn(graph_t * g, node_t * vn)
{
    node_t *rv;
    int r;

    r = ND_rank(vn);
    make_slots(g, r, ND_order(vn), 2);
    rv = virtual_node(g);
    ND_lw(rv) = ND_lw(vn);
    ND_rw(rv) = ND_rw(vn);
    ND_rank(rv) = ND_rank(vn);
    ND_order(rv) = ND_order(vn) + 1;
    GD_rank(g)[r].v[ND_order(rv)] = rv;
    return rv;
}
Example #18
0
/* this assumes one level per node - no mega-nodes */
static void apply_model(Agraph_t *ug)
{
	Agnode_t *un;
	for (un = agfstnode(ug); un; un = agnxtnode(ug,un)) 
			ND_order(un) = ND_order(ND_rep(un));
}
Example #19
0
/* Execute union commands for "same rank" subgraphs and clusters. */
static void 
collapse_sets(graph_t *rg, graph_t *g)
{
    int c;
    graph_t  *subg;
#ifdef OBSOLETE
    node_t *n;
#endif

#ifndef WITH_CGRAPH
    graph_t *mg;
    node_t *mn;
    edge_t *me;
    mg = g->meta_node->graph;
    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
	mn = aghead(me);
	subg = agusergraph(mn);
#else /* WITH_CGRAPH */
    for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
#endif /* WITH_CGRAPH */
	c = rank_set_class(subg);
	if (c) {
	    if ((c == CLUSTER) && CL_type == LOCAL)
		collapse_cluster(rg, subg);
	    else
		collapse_rankset(rg, subg, c);
	}
	else collapse_sets(rg, subg);

#ifdef OBSOLETE
 Collapsing leaves is currently obsolete

	/* mark nodes with ordered edges so their leaves are not collapsed */
	if (agget(subg, "ordering"))
	    for (n = agfstnode(subg); n; n = agnxtnode(subg, n))
		ND_order(n) = 1;
#endif
    }
}

static void 
find_clusters(graph_t * g)
{
    graph_t *subg;
#ifndef WITH_CGRAPH
    graph_t *mg;
    node_t *mn;
    edge_t *me;

    mg = g->meta_node->graph;
    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
	mn = me->head;
	subg = agusergraph(mn);
#else /* WITH_CGRAPH */
    for (subg = agfstsubg(agroot(g)); subg; subg = agnxtsubg(subg)) {
#endif /* WITH_CGRAPH */
	if (GD_set_type(subg) == CLUSTER)
	    collapse_cluster(g, subg);
    }
}

static void 
set_minmax(graph_t * g)
{
    int c;

    GD_minrank(g) += ND_rank(GD_leader(g));
    GD_maxrank(g) += ND_rank(GD_leader(g));
    for (c = 1; c <= GD_n_cluster(g); c++)
	set_minmax(GD_clust(g)[c]);
}
Example #20
0
static int ND_order_cmpf(const void *arg0, const void *arg1)
{
	return ND_order(*(Agnode_t**)arg0) - ND_order(*(Agnode_t**)arg1);
}