top-down subgraphs, left-right inside subgraphs
Solution 1
Reproducing particular graph layouts usually can be achieved with:
- Invisible nodes and edges
- rank constraints
Here's how I reproduced your graph - or at least a part of it:
digraph g {
rankdir="LR";
node[shape = circle, fontsize=14];
fontsize=18;
labeljust="l";
edge[style=invis, fontsize=12];
{ rank=same;
0 [style = invis];
01 [style = invis];
02 [style=invis];
0 -> 01 -> 02;
}
subgraph clusterA {
"0A" -> "1A" -> "2A";
"2A" -> "0A" [label=".", constraint=false, style=solid];
label="A";
}
subgraph clusterB {
"0B" -> "1B" -> "2B";
"2B" -> "0B" [label=".", constraint=false, style=solid];
label="B";
}
subgraph clusterC {
"0C" -> "1C" -> "2C";
"2C" -> "0C" [label=".", constraint=false, style=solid];
label="C";
}
0 -> "0A"[style=solid];
01 -> "0B"[style=invis];
02 -> "0C"[style=invis];
// edges between clusters
edge[constraint=false, style=solid];
"0A" -> "1B" [label=a]
"1A" -> "2B" [label=a]
"0B" -> "1C" [label=b]
"1B" -> "2C" [label=b]
}
This solution is not very intuitive. A couple of points to achieve this:
- I chose
rankdir="LR"
which resulted in nicer edges thanTB
, though it does not really correspond with the direction of the graph - Invisible nodes and edges are use for the top rank nodes (0, 01, 02) in order to have the clusters align left.
- The (invisible) top nodes are forced to the same rank and are linked by invisible edges - this will ensure that the clusters linked to each node appear in the correct order.
The result is:
Solution 2
Using constraint=false should get the nodes in your subgraphs to turn out the way you want http://www.graphviz.org/doc/info/attrs.html#d:constraint
subgraph clusterB {
label=B
"0B"
"1B"
"2B" -> "0B" [constraint=false label=•]
}
After that you'll find that your subgraphs don't line up with each other the way you want. Something like this could resolve that.
"0A" -> "0B" -> "0C" -> "0D" -> "0E" [weight=999 style=invis];
Solution 3
It looks like rank=same might be a cleaner solution. Take a look at Placing clusters on the same rank in Graphviz.
Solution 4
rankdir doesn't work directly in the subgraph, but if you add another set of curly braces - whatever that's called - rankdir works. See below. Then, obviously you need more tricks to restore the alignment and ordering you're after.
digraph G {
node [shape = circle]
0 [style = invis]
0 -> "0A"
subgraph clusterA {
label=A
{
rank=same
"0A"
"1A"
"2A" -> "0A" [label=•]
}
}
subgraph clusterB {
label=B
{
rank=same
"0B"
"1B"
"2B" -> "0B" [label=•]
}
}
subgraph clusterC {
label=C
{
rank=same
"0C"
"1C"
"2C" -> "0C" [label=•]
}
}
subgraph clusterD {
label=D
{
rank=same
"0D"
"1D"
"2D" -> "0D" [label=•]
}
}
subgraph clusterE {
label=E
{
rank=same
"0E"
"1E"
"2E" -> "0E" [label=•]
}
}
subgraph clusterF {
label=F
{
rank=same
{node [shape = doublecircle] "0F" "1F"}
"2F" -> "0F" [label=•]
}
}
"0A" -> "1B" [label=a]
"1A" -> "2B" [label=a]
"0B" -> "1C" [label=b]
"1B" -> "2C" [label=b]
"0C" -> "1D" [label=c]
"1C" -> "2D" [label=c]
"0D" -> "1E" [label=d]
"1D" -> "2E" [label=d]
"0E" -> "1F" [label=e]
"1E" -> "2F" [label=e]
}
Solution 5
An update on @marapet's answer using group
digraph g {
rankdir="LR";
node[shape = circle, fontsize=14];
fontsize=18;
labeljust="l";
edge[style=invis, fontsize=12];
{ rank=same;
0 [group=a style = invis];
01 [style = invis];
02 [group=b style=invis];
0 -> 01 -> 02;
}
subgraph clusterA {
"0A" [group=a]
"0A" -> "1A" -> "2A";
"2A" -> "0A" [label=".", constraint=false, style=solid];
label="A";
}
subgraph clusterB {
"0B" -> "1B" -> "2B";
"2B" -> "0B" [label=".", constraint=false, style=solid];
label="B";
}
subgraph clusterC {
"0C" [group=b]
"1C" [group=b]
"0C" -> "1C" -> "2C";
"2C" -> "0C" [label=".", constraint=false, style=solid];
label="C";
}
0 -> "0A"[style=solid];
01 -> "0B"[style=invis];
02 -> "0C"[style=invis];
// edges between clusters
edge[constraint=false, style=solid];
"0A" -> "1B" [label=a]
"1A" -> "2B" [label=a]
"0B" -> "1C" [label=b]
"1B" -> "2C" [label=b]
}
Related videos on Youtube
Comments
-
Pitel almost 2 years
I'd like to have my graph looks like this:
But I can only get this:
The problem is,
rankdir
does not work insubgraph
. So, how to emulate it?The code:
digraph G { node [shape = circle] 0 [style = invis] 0 -> "0A" subgraph clusterA { label=A "0A" "1A" "2A" -> "0A" [label=•] } subgraph clusterB { label=B "0B" "1B" "2B" -> "0B" [label=•] } subgraph clusterC { label=C "0C" "1C" "2C" -> "0C" [label=•] } subgraph clusterD { label=D "0D" "1D" "2D" -> "0D" [label=•] } subgraph clusterE { label=E "0E" "1E" "2E" -> "0E" [label=•] } subgraph clusterF { label=F {node [shape = doublecircle] "0F" "1F"} "2F" -> "0F" [label=•] } "0A" -> "1B" [label=a] "1A" -> "2B" [label=a] "0B" -> "1C" [label=b] "1B" -> "2C" [label=b] "0C" -> "1D" [label=c] "1C" -> "2D" [label=c] "0D" -> "1E" [label=d] "1D" -> "2E" [label=d] "0E" -> "1F" [label=e] "1E" -> "2F" [label=e] }
-
morpheus over 4 years
-
-
Justin German over 8 years@jason-s Thanks for the bounty! Quite unexpected, years after submitting this answer!
-
nachocab over 5 yearsIt seems that the algorithm has changed. I get a weird 0C when I paste your solution in viz.js
-
nachocab over 5 yearsI was able to fix it using
group
. See my answer -
CodeMonkey almost 5 yearsThis worked very well, and much simpler to read than the other answers.
-
Clément over 3 yearsYou're not using rankdir, are you? It seems you're using
rank=same
instead, which breaks the graph: the order of the nodes in the clusters changes.