GraphViz - alignment of subgraph - graphviz

I'd like to draw a diagram like this.
But the only diagram I can draw is:
The code I used :
graph [rankdir = LR]
node [shape=box]
x1;x2;x3;y1;y2;y3;y4;y5;y6;y7;y8;
node [shape=oval]
ind60;dem60;dem65
{x1,x2,x3} -> ind60[arrowhead=none arrowtail=normal dir=both]
{y1,y2,y3,y4} -> dem60[arrowhead=none arrowtail=normal dir=both]
dem65 -> {y5,y6,y7,y8}
ind60->dem60 dem60->dem65 ind60->dem65
How can I draw the desired plot?

A first step in what you want to achieve, using rank=same, invisible edges, groups, and constraint=false:
digraph {
node [shape=box]
{
rank=same;
y1;y2;y3;y4;
}
dem60[shape=oval];
{y1;y2;y3;y4} -> dem60 [dir=back];
{
rank=same;
x2 [group=left];
ind60[shape=oval];
dem65[shape=oval];
y6 [group=right];
x2 -> ind60 [dir=back];
ind60 -> dem65
dem65 -> y6;
}
// Invisible edges to order vertically node groups
edge[style=invis];
x1[group=left];
x3[group=left];
x1 -> x2 -> x3;
node[group=right];
y5 -> y6 -> y7 -> y8;
node[group=""]
edge[style=solid]
ind60->dem60
dem60->dem65
edge[constraint=false];
ind60 -> x1;
ind60 -> x3;
dem65 -> y5;
dem65 -> y7;
dem65 -> y8;
}
group enforces vertical alignement of nodes (of the same group).
rank=same makes nodes stay on the same rank.
Invisible edges enforce rank order within a vertical group.
constraint=false removes constraint calculation for some edges.
dir=back reverses displayed edge direction.

Related

Controlling the ordering of nodes within a GraphViz subgraph cluster

I've got two cluster subgraphs in GraphViz, with edges between the nodes in each subgraph. I'd like to be able to influence the top-to-bottom ordering of the nodes within the second subgraph so as to achieve symmetry across the horizontal axis, and have the nodes in the second subgraph ordered top-to-bottom as a, b, c, d.
digraph {
rankdir=LR
subgraph cluster_1 {
bx -> cx
by -> cy
}
subgraph cluster_2 {
a; b; c; d
}
bx -> a
cx -> b
cy -> c
by -> d
}
Right now, I get this:
Changing the ordering of node appearance within the cluster_2 subgraph doesn't seem to matter, nor does changing the ordering of the cross-cluster edges at the bottom.
Is there any way to get GraphViz to produce what I want here?
You can add some scaffolding edges and/or nodes i.e. invisible edges/nodes but it can be a bit triggy especially when clusters are involved
e.g.:
digraph {
rankdir=LR
subgraph cluster_1 {
bx -> cx
by -> _d [dir=none]
by -> cy
_a[shape=point height=0]
_d[shape=point height=0]
bx -> _a [dir=none]
}
subgraph cluster_2 {
a; b; c; d
}
//bx -> a
cx -> b
cy -> c
//by -> d
_a->a
_d->d
}

How to set head and tail position in nodes graphviz

I can not control an edge's head and tail position between 2 nodes.
I'm setting up a node like a graph below
digraph G{
node [shape = "box"]
a -> b
b -> a
}
This first part is basically the same answer that #marapet has given already:
digraph G
{
node[ shape = "box" ];
a:w -> b:w;
a:e -> b:e[ dir = back ];
}
It produces a graph with round edges:
If that's OK, then marapet's answer should be accepted.
If you insist on the shape that you provided in your post, a bit more complicated procedure needs to be applied:
digraph G
{
// we create the two nodes to be displayed
node[ shape = "box" ];
a b;
//we also create four empty nodes for routing the edges
node[ shape = point, height = 0 ];
x1 x2 x3 x4;
// we make sure that the nodes are arranged on the right levels
{ rank = same; x1 a x2 }
{ rank = same; x3 b x4 }
// we draw the edges one by one as the heads are varying
x1 -> a[ dir = none ];
a -> x2[ dir = back ];
x1 -> x3[ dir = none ];
x2 -> x4[ dir = none ];
b -> x4[ dir = none ];
x3 -> b;
}
This gives you
The head and tail position of an edge can be defined by using compass points as specified in The dot language, or by using the headport or tailport attributes:
digraph G{
node [shape = "box"]
a:w -> b:w
b -> a [headport=e, tailport=e]
}

How to make an edge with both direction in GraphViz?

How to make an edge with both direction in GraphViz?
I am trying to make an curved edge with both direction.
But the only plot I can make is:
I want to make the edge between x1 and x2 curved with both direction.
The code I used:
digraph {
rankdir=LR
node [shape=box ]
x1;x2
node [shape=oval ]
y
x1->y[dir=back label=0.77]
x2->y[dir=back label=0.42]
x1:w -> x2:w[dir=both constraint=false]
}
I would appreciate any help.
I think there should be a better solution but the following did work for me:
digraph {
rankdir=LR
node [shape=box ]
x1;x2
node [shape=oval ]
y
x1->y[dir=back label=0.77]
x2->y[dir=back label=0.42]
x1:w -> x2:w[dir=both constraint=false]
x2:w -> x1:w[dir=both constraint=false]
}
based on the answer from Changing edge direction in dot:
digraph g {
rankdir=LR
node [shape=box ]
{rank=same x1;x2}
node [shape=oval ]
y
x1 -> y[dir=back label=0.77]
x2 -> y[dir=back label=0.42]
x1:w -> x2:w[dir=both label=0.34]
}

Nesting nodes in GraphViz

I'm trying to draw bigraphs in GraphViz (something like this)
Is it possible to nest nodes directly in GraphViz?
If not is it possible to change the shape of a subgraph/cluster?
I have found a post about how to import images of graphs into nodes but that seems like more effort than drawing them in powerpoint.
I can also make clusters visible, but they will include nodes from outside the cluster and as far as I can tell have a fixed shape.
Thanks for your help.
Nest nodes is impossible, but nest clusters is possible.
Subgraph/cluster has some predefined styles. Also nodes has predefines shapes. I don't know about manual editing path of border shapes for nodes in graphviz in different layouts (or alternatives like representing the border as a chain of nodes), maybe someone else can tell us.
You can get nested nodes in neato layout engine, but in fact they will be nested only visually, because you just set their coordinates with pos attribute, which means they overlap each other.
Example image:
and script:
graph {
layout=neato
node [shape=circle pin=true ]
foo [height=0.6 pos="0.7,1.5" ]
bar [height=2 pos="1,2" ]
baz [height=1 pos="2,2" ]
}
You can import images as backgrounds into nodes as described in this answer. For example for Windows you can use this official archive, it comes with a cairo.dll, which will avoid errors like Warning: No loadimage plugin for "jpeg:cairo" when you run the command $ dot -Tpng input.dot -o output.png.
The image from your question can be drawn like this:
Script:
digraph {
graph [
layout=dot,
ranksep=1,
overlap=false,
compound=true, // to enable `lhead`, `ltail` features
newrank=true, // to enable ranking between nodes in clusters
splines=true,
splines=curved]
edge[color=lime arrowhead=none]
node[shape=plaintext]
y0 [label=<<FONT><I>y</I><SUB>0</SUB></FONT>>]
y1 [label=<<FONT><I>y</I><SUB>1</SUB></FONT>>]
y2 [label=<<FONT><I>y</I><SUB>2</SUB></FONT>>]
x0 [label=<<FONT><I>x</I><SUB>0</SUB></FONT>>]
x1 [label=<<FONT><I>x</I><SUB>1</SUB></FONT>>]
subgraph cluster_r0{
style="rounded, dashed"
margin=20
label=<<FONT><I>r</I><SUB>0</SUB></FONT>>
v2 [shape=circle]
noname_dot[shape=point height=0]
subgraph cluster_v0{
style="rounded"
label=<<FONT><I>v</I><SUB>0</SUB></FONT>>
invis_dot_1 [style=invis shape=point]
subgraph cluster_v1{
style="rounded";
label=<<FONT><I>v</I><SUB>1</SUB></FONT>>
subgraph cluster_s0{
label=<<FONT><I>s</I><SUB>0</SUB></FONT>>
fillcolor=lightgrey
style="filled, rounded"
invis_dot_2 [style=invis shape=point]
}
}
}
}
y0 -> noname_dot
noname_dot -> invis_dot_2 [lhead="cluster_v1"]
noname_dot -> invis_dot_1 [lhead="cluster_v0"]
noname_dot -> v2 [constraint=false]
y1 -> v2
subgraph cluster_r1{
style="rounded, dashed"
margin=20
label=<<FONT><I>r</I><SUB>1</SUB></FONT>>
noname_dot_2 [shape=point height=0]
subgraph cluster_s3{
label=<<FONT><I>s</I><SUB>3</SUB></FONT>>
fillcolor=lightgrey
style="filled, rounded"
invis_dot_s3 [style=invis shape=point]
}
subgraph cluster_v3{
style="rounded"
label=<<FONT><I>v</I><SUB>3</SUB></FONT>>
subgraph cluster_s2{
label=<<FONT><I>s</I><SUB>2</SUB></FONT>>
fillcolor=lightgrey
style="filled, rounded"
invis_dot_s2 [style=invis shape=point]
}
}
}
y2 -> noname_dot_2
noname_dot_2 -> x0
v2 -> noname_dot_2 [weight=0]
noname_dot_2 -> invis_dot_s2 [lhead="cluster_v3"]
invis_dot_s2 -> x1 [ltail="cluster_v3"]
// Vertical alignment (`rank`) of the desired nodes:
{rank=same; noname_dot; noname_dot_2; v2 }
{rank=same; invis_dot_s3; invis_dot_s2 }
{rank=same; x0; x1;}
{rank=same; y0; y1; y2;}
}

Draw two subgraph without connection, one under the other, in DOT?

For example:
digraph G {
rankdir = TB;
subgraph A {
a -> {a0, a1};
};
subgraph B {
b -> {b0, b1, b2};
};
};
I want to put B at the bottom of A, how to do it?
You'll have to tell graphviz that the subgraphs are not equal. One way to do it is simply to add invisible edges between the graphs:
digraph G {
rankdir = TB;
subgraph A {
a -> {a0, a1};
};
subgraph B {
b -> {b0, b1, b2};
};
a0 -> b [style=invis];
a1 -> b [style=invis];
};
By adding two invisible edges the subgraphs are neatly aligned.

Resources