I have several related sub-graphs that I want to draw together in GraphViz. When I draw simple nodes it looks quite pretty:
Source:
digraph {
rankdir=LR;
A1 -> A21;
A1 -> A22;
A1 -> A23;
A1 -> A24;
B1 -> B21;
B1 -> B22;
B1 -> B23;
B1 -> B24;
A21 -> A31;
A22 -> A31;
A23 -> A31;
A23 -> A32;
B21 -> B31;
B21 -> B32;
B22 -> B32;
B21 -> B33;
B23 -> B33;
}
As the nodes in the same level across the several sub-graphs are related, I want to group them and give it a label.
I tried to do it using clusters, but it "squeezes" the nodes:
Source:
digraph {
rankdir=LR;
subgraph cluster_level1 {
label = "Level 1";
style=filled;
color=lightgrey;
A1;
B1;
}
subgraph cluster_level2 {
label = "Level 2";
style=filled;
color=lightgrey;
A21;
A22;
A23;
A24;
B21;
B22;
B23;
B24;
}
subgraph cluster_level3 {
label = "Level 3";
style=filled;
color=lightgrey;
A31;
A32;
B31;
B32;
B33;
}
A1 -> A21;
A1 -> A22;
A1 -> A23;
A1 -> A24;
B1 -> B21;
B1 -> B22;
B1 -> B23;
B1 -> B24;
A21 -> A31;
A22 -> A31;
A23 -> A31;
A23 -> A32;
B21 -> B31;
B21 -> B32;
B22 -> B32;
B21 -> B33;
B23 -> B33;
}
With just two sub-graphs, it's bad, but still not horrible. However, if I add more sub-graphs, it becomes uglier and uglier.
Is there a way to group nodes with some shadowing and labels, while keeping the original nodes layout using GraphViz?
This is probably not a good answer since it implies a lot of trial and error but at least you get what you want (I guess) with invisible nodes:
digraph {
rankdir=LR;
subgraph cluster_level1 {
label = "Level 1";
style=filled;
color=lightgrey;
A01[ style = invis ];
A1;
A02[ style = invis ];
A03[ style = invis ];
A06[ style = invis ];
A05[ style = invis ];
B1;
A04[ style = invis ];
}
subgraph cluster_level2 {
label = "Level 2";
style=filled;
color=lightgrey;
A21;
A22;
A23;
A24;
B21;
B22;
B23;
B24;
}
subgraph cluster_level3 {
label = "Level 3";
style=filled;
color=lightgrey;
A07[ style = invis ];
A31;
A32;
A08[ style = invis ];
B31;
B32;
B33;
A01[ style = invis ];
A09[ style = invis ];
}
A1 -> A21;
A1 -> A22;
A1 -> A23;
A1 -> A24;
B1 -> B21;
B1 -> B22;
B1 -> B23;
B1 -> B24;
A21 -> A31;
A22 -> A31;
A23 -> A31;
A23 -> A32;
B21 -> B31;
B21 -> B32;
B22 -> B32;
B21 -> B33;
B23 -> B33;
}
yields
Related
How do I align nodes with each other between subgraphs?
In the example, I would like all the 0 nodes aligned vertically as well as the 1, 2, 3 and 4 nodes. It would be good if all the right edges of subgraphs were extended as necessary to align too.
digraph AlignWhenMissing {
rankdir=LR;
node [shape=box]
subgraph clusterA {label = "A Shift a4 along (no a3)";
a0 -> a1;
a1 -> a2;
a2 -> a4;
}
subgraph clusterB {label = "B Shift b2 above a2";
b0 -> b2;
b2 -> b3;
}
subgraph clusterC {label = "C Shift c3 above b3";
c0 -> c3;
}
A -> a0[lhead=clusterA];
B -> b0[lhead=clusterB];
C -> c0[lhead=clusterC];
a0 -> b0[constraint=false];
b3 -> c3[constraint=false];
a2 -> b2[constraint=false];
}
The minlen attribute (https://graphviz.org/docs/attrs/minlen/) applies to edges to lengthen them (i.e. to push them "out" by N ranks).
Then added invisible nodes and edges to increase cluster dimension.
digraph AlignWhenMissing {
rankdir=LR;
node [shape=box]
subgraph clusterA {label = "A Shift a4 along (no a3)";
a0 -> a1;
a1 -> a2;
a2 -> a4 [minlen=2];
}
subgraph clusterB {label = "B Shift b2 above a2";
b0 -> b2 [minlen=2]
b2 -> b3;
b4 [style=invis]
b3 -> b4 [style=invis]
}
subgraph clusterC {label = "C Shift c3 above b3";
c0 -> c3 [minlen=3];
c4 [style=invis]
c3 -> c4 [style=invis]
}
A -> a0[lhead=clusterA];
B -> b0[lhead=clusterB];
C -> c0[lhead=clusterC];
a0 -> b0[constraint=false];
b3 -> c3[constraint=false];
a2 -> b2[constraint=false];
}
Giving:
I have Graphviz as below:
digraph G {
node [fontname = "font-awesome"]; edge [dir=none];
A [label="A"];
B [label="B"];
c_A_B [shape=diamond];
{rank=same; A -> c_A_B -> B};
C [label="C"];
L1_0 [shape=circle,label="",height=0.01,width=0.01];
L1_0->C;
D [label="D"];
L1_1 [shape=circle,label="",height=0.01,width=0.01];
L1_1->D;
E [label="E"];
L1_2 [shape=circle,label="",height=0.01,width=0.01];
L1_2->E;
{rank=same; L1_0->L1_1->L1_2};
{rank=same; C; D; E;};
c_A_B->L1_1;
F [label="F"];
c_E_F [shape=diamond];
{rank=same; E->c_E_F->F};
L2_0 [shape=circle,label="",height=0.01,width=0.01];
c_E_F->L2_0;
}
which shows the graph as below, can anyone be kind to help me how to avoid the edge overlapping?
I this case in this case a solution for you can be an invisible edge in the form of:
C -> D [style=invis];
so your example would look like:
digraph G {
node [fontname = "font-awesome"]; edge [dir=none];
A [label="A"];
B [label="B"];
c_A_B [shape=diamond];
{rank=same; A -> c_A_B -> B};
C [label="C"];
L1_0 [shape=circle,label="",height=0.01,width=0.01];
L1_0->C;
D [label="D"];
L1_1 [shape=circle,label="",height=0.01,width=0.01];
L1_1->D;
C -> D [style=invis];
E [label="E"];
L1_2 [shape=circle,label="",height=0.01,width=0.01];
L1_2->E;
{rank=same; L1_0->L1_1->L1_2};
{rank=same; C; D; E;};
c_A_B->L1_1;
F [label="F"];
c_E_F [shape=diamond];
{rank=same; E->c_E_F->F};
L2_0 [shape=circle,label="",height=0.01,width=0.01];
c_E_F->L2_0;
}
And the resulting image is:
I am trying to create a neural network diagram using Graphviz. So basically I want to leave more space between Dropout 1 and LSTM 4 and add on top of the arrow 3 bullet points to indicate that there are more layers repeating. Also since I have in total 50 nodes I would like to leave space between the first two red nodes and the third one and adding bullet points there as well. Hope I am making myself clear.
Diagram I am trying to create I used paint to draw the spacing and the bullets
digraph G {
rankdir=LR
splines=line
node [fixedsize=false, label=""];
subgraph cluster_0 {
color=white;
node [style=solid,color=red2, shape=circle];
x1 x2 x3;
label = "Input layer (60,1)";
}
subgraph cluster_1 {
color=white;
node [style=solid,color=blue4, shape=circle];
a12 a22 a32;
label = "LSTM 1 (60,1)";
}
subgraph cluster_2 {
color=white;
node [style=solid,color=blue4, shape=circle];
b12 b22 b32;
label="Dropout 1(0.2 probability)";
}
subgraph cluster_7 {
color=white;
node [style=solid,color=blue4, shape=circle];
c12 c22 c32;
label="LSTM 4(60,50)";
}
subgraph cluster_8 {
color=white;
node [style=solid,color=blue4, shape=circle];
d12 d22 d32;
label="Dropout 4(0.2 probability)";
}
subgraph cluster_9 {
color=white;
node [style=solid,color=red2, shape=circle];
O;
label="Dense(1)";
}
x1 -> a12;
x1 -> a22;
x1 -> a32;
x2 -> a12;
x2 -> a22;
x2 -> a32;
x3 -> a12;
x3 -> a22;
x3 -> a32;
a12 -> b12;
a12 -> b22;
a12 -> b32;
a22 -> b12;
a22 -> b22;
a22 -> b32;
a32 -> b12;
a32 -> b22;
a32 -> b32;
b12 -> c12;
b12 -> c22;
b12 -> c32;
b22 -> c12;
b22 -> c22;
b22 -> c32;
b32 -> c12;
b32 -> c22;
b32 -> c32;
c12 -> d12;
c12 -> d22;
c12 -> d32;
c22 -> d12;
c22 -> d22;
c22 -> d32;
c32 -> d12;
c32 -> d22;
c32 -> d32;
d12 -> O
d22 -> O
d32 -> O
}
Add some scafolding (invis nodes and edges)
also needed an xlabel not to bend one of the edges
and constraint on some edges to make drawing straight
e.g.:
digraph G {
rankdir=LR
splines=line
node [fixedsize=false, label=""];
{node[shape=point color=invis] x0 a02 b02 c02 d02}
subgraph cluster_0 {
color=white;
node [style=solid,color=red2, shape=circle];
x0
x1 x2 x3;
label = "Input layer (60,1)";
}
subgraph cluster_1 {
color=white;
node [style=solid,color=blue4, shape=circle];
a02
a12 a22 a32;
label = "LSTM 1 (60,1)";
}
subgraph cluster_2 {
color=white;
node [style=solid,color=blue4, shape=circle];
b02
b12 b22 b32;
label="Dropout 1(0.2 probability)";
}
subgraph cluster_7 {
color=white;
node [style=solid,color=blue4, shape=circle];
c02
c12 c22 c32;
label="LSTM 4(60,50)";
}
subgraph cluster_8 {
color=white;
node [style=solid,color=blue4, shape=circle];
d02
d12 d22 d32;
label="Dropout 4(0.2 probability)";
}
subgraph cluster_9 {
color=white;
node [style=solid,color=red2, shape=circle];
O;
label="Dense(1)";
}
edge[minlen=2]
{node[shape=point color=invis]
edge[dir=both arrowhead=tee arrowtail=tee]
rank=same x03->x02[label=<⋮>] // is utf8 vertical ellipsis
}
{edge[style=invis minlen=1]
x003[shape=none]
x003->x03->x1
x02->x2
}
{
edge[dir=both arrowhead=tee arrowtail=tee]
b02 -> c02[xlabel="..."]
}
//{rank=same b32 b02}
x1 -> a12;
x1 -> a22[constraint=0];
x1 -> a32[constraint=0];
x2 -> a12[constraint=0];
x2 -> a22;
x2 -> a32[constraint=0];
x3 -> a12[constraint=0];
x3 -> a22[constraint=0];
x3 -> a32;
a12 -> b12;
a12 -> b22[constraint=0];
a12 -> b32[constraint=0];
a22 -> b12[constraint=0];
a22 -> b22;
a22 -> b32[constraint=0];
a32 -> b12[constraint=0];
a32 -> b22[constraint=0];
a32 -> b32;
b12 -> c12;
b12 -> c22[constraint=0];
b12 -> c32[constraint=0];
b22 -> c12[constraint=0];
b22 -> c22;
b22 -> c32[constraint=0];
b32 -> c12[constraint=0];
b32 -> c22[constraint=0];
b32 -> c32;
c12 -> d12;
c12 -> d22[constraint=0];
c12 -> d32[constraint=0];
c22 -> d12[constraint=0];
c22 -> d22;
c22 -> d32[constraint=0];
c32 -> d12[constraint=0];
c32 -> d22[constraint=0];
c32 -> d32;
d12 -> O
d22 -> O
d32 -> O
}
rendered on viz-js.com
I'd like the column a ... i to be the first column from the left and a1 ... f1 the first column from the right. I tried to setup same rank, different weights, but with no luck. How can I control the order of columns?
digraph G {
newrank = true;
node [shape=record, style="rounded,filled", color="#5F6368", fillcolor="#F7F7F7", fontname="Arial", fontsize=10];
graph [fontname = "Arial"]; edge [fontname = "Arial"];
style = "dashed";
subgraph cluster0 {
color="#34A853";
a; a1; b; b1; c; c1; d; d1;
}
subgraph cluster1 {
color="#EA4335";
e1; f1;
subgraph cluster2 {
color="#FBBC05";
e; f; g; h; i;
}
}
a -> b -> c -> d [color="#34A853"];
a1 -> b1 -> c1 -> d1 [color="#4285F4"];
edge[style=invis];
{rank="same"; a -> a1 [constraint=false]}
{rank="same"; b -> b1 [constraint=false]}
{rank="same"; c -> c1 [constraint=false]}
{rank="same"; d -> d1 [constraint=false]}
{rank="same"; e -> e1 [constraint=false]}
{rank="same"; f -> f1 [constraint=false]}
d -> e -> f -> g -> h -> i;
d1 -> e1 -> f1;
}
If I run graphviz on this digraph:
digraph G {
subgraph cluster_0 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
a0; a1; a2; a3;
label = "sources";
}
subgraph cluster_1 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
b0; b1; b2; b3;
label = "intermediaries";
}
a0 -> b0; a1 -> b0;
a0 -> b1; a1 -> b1;
a2 -> b2; b0 -> b2;
b1 -> b2; a3 -> b3;
b0 -> b3; b1 -> b3;
}
I get
with many edges intersecting the "intermediaries" label. How do I get graphviz to make edges avoid labels?
As a workaround:
digraph G {
subgraph cluster_0 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
a0; a1; a2; a3;
label = "sources";
}
subgraph cluster_1 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
nodelabel [label="intermediaries"; style=filled; color=lightgrey]
nodelabel -> b1 [style=invis];
nodelabel -> b0 [style=invis];
b0; b1; b2; b3;
}
a0 -> b0; a1 -> b0;
a0 -> b1; a1 -> b1;
a2 -> b2; b0 -> b2;
b1 -> b2; a3 -> b3;
b0 -> b3; b1 -> b3;
}
produce: