top-down subgraphs, left-right inside subgraphs
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:
It looks like rank=same might be a cleaner solution. Take a look at Placing clusters on the same rank in Graphviz.
You can also use 'constraint=false' and invisible edges to carefully control node rank. This is basically the same answer as the above.
digraph G {
newrank=true; // rank without respect to cluster
rankdir="LR";
node [shape = circle]
subgraph clusterA {
a0 -> a1 -> a2 [style = invis] // set node order in cluster
a2 -> a0 [constraint=false] //don't use this edge for ranking
}
subgraph clusterB {
b0 -> b1 -> b2 [style = invis]
b2 -> b0 [constraint=false]
}
a0 -> b1 [constraint=false]
a1 -> b2 [constraint=false]
}