I have a PATRICA trie for which I'm generating a GraphViz file. The internal nodes are the skip values and the edges are dotted 0 and solid 1. It is preferred that 0 is to the left of 1, giving an alphabetical order of the leaves. I re-arranged the order I visit the graph so dot
gives this result. However, when I group them in trees in a forest using subgraphs, I can't seem to force dot
to reliably respect the order for inter-subgraph edges.
digraph {
rankdir=TB;
node [shape = box, style = filled, fillcolor = lightsteelblue];
// forest size 2.
subgraph cluster_tree0 {
style = filled; fillcolor = lightgray; label = "tree 0";
// branches
branch0_0 [label = "3", shape = none, fillcolor = none];
branch0_0 -> branch0_1;
branch0_1 [label = "0", shape = none, fillcolor = none];
branch0_1 -> branch0_2 [style = dashed];
branch0_2 [label = "1", shape = none, fillcolor = none];
branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
branch0_2 -> leaf0_2 [color = royalblue];
branch0_1 -> branch0_3;
branch0_3 [label = "2", shape = none, fillcolor = none];
branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
branch0_3 -> leaf0_4 [color = royalblue];
// leaves
leaf0_1 [label = "u"];
leaf0_2 [label = "v"];
leaf0_3 [label = "x"];
leaf0_4 [label = "y"];
}
branch0_0 -> branch1_0 [lhead = cluster_tree0, ltail = cluster_tree1, color = firebrick, style = dashed];
subgraph cluster_tree1 {
style = filled; fillcolor = lightgray; label = "tree 1";
// branches
branch1_0 [label = "0", shape = none, fillcolor = none];
branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
branch1_0 -> branch1_1;
branch1_1 [label = "1", shape = none, fillcolor = none];
branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
branch1_1 -> branch1_2;
branch1_2 [label = "0", shape = none, fillcolor = none];
branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
branch1_2 -> leaf1_3 [color = royalblue];
// leaves
leaf1_0 [label = "f"];
leaf1_1 [label = "m"];
leaf1_2 [label = "n"];
leaf1_3 [label = "o"];
}
}
On one graph it works fine, but it the subgraphs are reversed to the order I want them.
I reversed the order in the file and it still looks the same. I played around with it and I could get it turned around by rank=same
, ordering=out
, and invis
edges somehow, but I want it to be programmatic. Is there any easy way to draw the red dotted line, representing 0, to the left, instead of to the right, of the solid line, representing 1?
OK, a total kludge, but probably fully scriptable.
First, your input somewhat reworked:
digraph {
rankdir=TB;
newrank=true // helps
graph [splines=false]
node [shape = box, style = filled, fillcolor = lightsteelblue];
// forest size 2.
subgraph cluster_tree1 {
style = filled; fillcolor = lightgray; label = "tree 1";
// branches
branch1_0 [label = "0", shape = none, fillcolor = none];
branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
branch1_0 -> branch1_1;
branch1_1 [label = "1", shape = none, fillcolor = none];
branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
branch1_1 -> branch1_2;
branch1_2 [label = "0", shape = none, fillcolor = none];
branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
branch1_2 -> leaf1_3 [color = royalblue];
// leaves
leaf1_0 [label = "f"];
leaf1_1 [label = "m"];
leaf1_2 [label = "n"];
leaf1_3 [label = "o"];
}
subgraph cluster_tree0 {
style = filled; fillcolor = lightgray; label = "tree 0";
// branches
branch0_0 [label = "3", shape = none, fillcolor = none];
branch0_0 -> branch0_1;
branch0_1 [label = "0", shape = none, fillcolor = none];
branch0_1 -> branch0_2 [style = dashed];
branch0_2 [label = "1", shape = none, fillcolor = none];
branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
branch0_2 -> leaf0_2 [color = royalblue];
branch0_1 -> branch0_3;
branch0_3 [label = "2", shape = none, fillcolor = none];
branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
branch0_3 -> leaf0_4 [color = royalblue];
// leaves
leaf0_1 [label = "u"];
leaf0_2 [label = "v"];
leaf0_3 [label = "x"];
leaf0_4 [label = "y"];
}
// position the clusters (trees)
{rank=same branch1_0 -> branch0_1 [style=invis weight=0]}
// a kludge, we'll add this edge in later
graph [comment="branch0_0 -> branch1_0 [color = firebrick, style = dashed constraint=false weight=0 ];"]
}
The "problem" is the cluster-to-cluster branch, so we remove it (for the first dot pass). And we add the invisible edge to position the clusters where we want them.
Run this input into dot -Tdot >myfile.dot. This sets positions for all nodes & edges.
Run that thru gawk (any language) to un-comment the commented branch(s) and insert into the file.
Finally, neato -n2 -Tpng fixedfile >fixed.png
(yuck, but it works)
f=atrie4.gv;
T=png; F=`basename $f .gv`;dot -Tdot $f >$F.dot;
gawk '
$1~/comment/{
sub(/[\t ]*comment="/,"")
sub(/"[\],;]?[\t ]*$/,"")
add[++a]=$0
next
}
{oline[++o]=$0}
END{
for (i=1;i<o;i++)print oline[i]
for (i=1;i<=a;i++)print add[i]
print oline[o]
}' $F.dot|
neato -n2 -Tpng >$F.$T
firefox $F.$T