I am trying to use Graphviz to produce a tree such as the following:
I have it almost working, as shown below:
My problems are the following:
Subtrees should never overlap, but the PP tree and the (.) tree overlap.
Subtrees should always be fairly regular, so that if there are multiple children, the edges should go to the left and right of the parent. Again, this does not work properly for the PP tree.
I have fixed (1) by using subgraph clusters, however, this introduces a few new issues. Namely, the edges are not straight, and I can't figure out how to hide the borders without leaving tons of empty space.
Is there a better way to force the tree formatting? It feels like it shouldn't be too unusual.
My code is below (generated by Python, sorry for unhelpful names):
graph {
subgraph 0 {
subgraph 1 {
0 [label=ROOT group=0 shape=plain]
subgraph 8 {
1 [label=S group=1 shape=plain]
subgraph 11 {
2 [label=NP group=2 shape=plain]
subgraph 15 {
3 [label=PRP group=3 shape=plain]
4 [label=I shape=plain]
3 -- 4
4 [label=I group=3]
}
2 -- 3
3 [label=PRP group=2]
}
subgraph 24 {
5 [label=VP group=5 shape=plain]
subgraph 28 {
6 [label=VBD group=6 shape=plain]
7 [label=solved shape=plain]
6 -- 7
7 [label=solved group=6]
}
subgraph 41 {
8 [label=NP group=8 shape=plain]
subgraph 45 {
9 [label=DT group=9 shape=plain]
10 [label=the shape=plain]
9 -- 10
10 [label=the group=9]
}
subgraph 63 {
11 [label=NN group=11 shape=plain]
12 [label=problem shape=plain]
11 -- 12
12 [label=problem group=11]
}
8 -- 9
8 -- 11
}
subgraph 77 {
13 [label=PP group=13 shape=plain]
subgraph 81 {
14 [label=IN group=14 shape=plain]
15 [label=on shape=plain]
14 -- 15
15 [label=on group=14]
}
subgraph 89 {
16 [label=NP group=16 shape=plain]
subgraph 93 {
17 [label=DT group=17 shape=plain]
18 [label=the shape=plain]
17 -- 18
18 [label=the group=17]
}
subgraph 102 {
19 [label=NN group=19 shape=plain]
20 [label=bus shape=plain]
19 -- 20
20 [label=bus group=19]
}
16 -- 17
16 -- 19
}
13 -- 14
13 -- 16
}
5 -- 6
5 -- 8
5 -- 13
}
subgraph 114 {
21 [label="." group=21 shape=plain]
22 [label="." shape=plain]
21 -- 22
22 [label="." group=21]
}
1 -- 2
1 -- 5
1 -- 21
}
0 -- 1
1 [label=S group=0]
}
}
ranksep=0.2
}
You are correct, Graphviz has "problems" with trees. That said, here is your graph, with clusters (peripheries=0), splines=false, and margin=2:
graph {
graph [splines=false]
subgraph cluster_0 {
peripheries=0
margin=2
subgraph cluster_1 {
0 [label=ROOT group=0 shape=plain]
subgraph cluster_8 {
1 [label=S group=1 shape=plain]
subgraph cluster_11 {
2 [label=NP group=2 shape=plain]
subgraph cluster_15 {
3 [label=PRP group=3 shape=plain]
4 [label=I shape=plain]
3 -- 4
4 [label=I group=3]
}
2 -- 3
3 [label=PRP group=2]
}
subgraph cluster_24 {
5 [label=VP group=5 shape=plain]
subgraph cluster_28 {
6 [label=VBD group=6 shape=plain]
7 [label=solved shape=plain]
6 -- 7
7 [label=solved group=6]
}
subgraph cluster_41 {
8 [label=NP group=8 shape=plain]
subgraph cluster_45 {
9 [label=DT group=9 shape=plain]
10 [label=the shape=plain]
9 -- 10
10 [label=the group=9]
}
subgraph cluster_63 {
11 [label=NN group=11 shape=plain]
12 [label=problem shape=plain]
11 -- 12
12 [label=problem group=11]
}
8 -- 9
8 -- 11
}
subgraph cluster_77 {
13 [label=PP group=13 shape=plain]
subgraph cluster_81 {
14 [label=IN group=14 shape=plain]
15 [label=on shape=plain]
14 -- 15
15 [label=on group=14]
}
subgraph cluster_89 {
16 [label=NP group=16 shape=plain]
subgraph cluster_93 {
17 [label=DT group=17 shape=plain]
18 [label=the shape=plain]
17 -- 18
18 [label=the group=17]
}
subgraph cluster_102 {
19 [label=NN group=19 shape=plain]
20 [label=bus shape=plain]
19 -- 20
20 [label=bus group=19]
}
16 -- 17
16 -- 19
}
13 -- 14
13 -- 16
}
5 -- 6
5 -- 8
5 -- 13
}
subgraph cluster_114 {
21 [label="." group=21 shape=plain]
22 [label="." shape=plain]
21 -- 22
22 [label="." group=21]
}
1 -- 2
1 -- 5
1 -- 21
}
0 -- 1
1 [label=S group=0]
}
}
ranksep=0.2
}
Giving:
I'm new to graphviz and have generated a graph that contains temporal constraints. That is, the order of nodes from left to right matters, but only locally. Here's the ruleset I'm trying to enforce:
1) Only and all 'box'-shaped nodes should be at the bottom of the graph. These represent terminal nodes.
2) Any rule at a 'doublecircle'-shaped node has temporal constraints (i.e. ordering matters).
Here's an attempt of enforcing these rules:
digraph G {
0 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
1 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
2 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
3 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
4 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
5 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
6 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
7 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
8 [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
9 [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
9 -> 0 [penwidth=3, weight=3]
9 -> 2 [penwidth=3, weight=3]
{
rank=same;
0->2[color=white]
rankdir=LR;
}
10 [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
10 -> 9 [penwidth=3, weight=3]
10 -> 5 [penwidth=3, weight=3]
{
rank=same;
9->5[color=white]
rankdir=LR;
}
11 [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
11 -> 4 [penwidth=3, weight=3]
11 -> 10 [penwidth=3, weight=3]
{
rank=same;
4->10[color=white]
rankdir=LR;
}
12 [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
12 -> 10 [penwidth=3, weight=3]
12 -> 11 [penwidth=3, weight=3]
{
rank=same;
10->11[color=white]
rankdir=LR;
}
13 [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
13 -> 4 [penwidth=3, weight=3]
13 -> 9 [penwidth=3, weight=3]
{
rank=same;
4->9[color=white]
rankdir=LR;
}
14 [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
14 -> 26 [penwidth=3, weight=3]
14 -> 8 [penwidth=3, weight=3]
{
rank=same;
26->8[color=white]
rankdir=LR;
}
15 [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
15 -> 12 [penwidth=3, weight=3]
15 -> 13 [penwidth=3, weight=3]
{
rank=same;
12->13[color=white]
rankdir=LR;
}
26 [shape=circle, fillcolor=palegreen1, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
26 -> 12[label = "0.50", penwidth=2.0, weight=3 ]
26 -> 15[label = "0.50", penwidth=2.0, weight=3 ]
}
From the ruleset, node 9 should have 0 as the left child and 2 as the right child, and so forth. This graph also does not enforce that all 'box;-shaped nodes should be at the bottom of the graph. Is it possible to build such a graph with GraphViz?
Thanks!
I'm not entirely sure how you would like this graph to look, but I have made an attempt. All boxes are at the bottom, this is done using a cluster subgraph (you can change the styling if you do not like the box). To prevent the edges from "special" edges (white in your code, red in mine because the background is also white) from interfering with the ordering, I specified a constraint = false on those edges. Let me know if this helps.
The code:
digraph G {
subgraph clusterSquares {
rank = same
node [shape=box, fillcolor=lightgrey, style=filled, ranksep=0.5, nodesep=0.5]
0; 1; 2; 3; 4; 5; 6; 7; 8;
}
{
node [shape=doublecircle, fillcolor=palegreen3, style=filled, color=blue, ranksep=0.5, nodesep=0.5]
edge [penwidth=3, weight=3]
9 -> { 0; 2; }
10 -> { 5; 9; }
11 -> { 4; 10 }
12 -> { 10; 11; }
13 -> { 4; 9; }
14 -> { 26; 8; }
15 -> { 12; 13; }
26 -> { 12; 15; }
}
{
edge [color = red, constraint = false]
0 -> 2
9 -> 5
4 -> 10
10 -> 11
4 -> 9
26 -> 8
13 -> 13
}
}
The resulting image:
I'm using splines=ortho and I was hoping for the edges to collapse together. To illustrate, I want to accomplish this:
I tried this:
digraph G {
splines=ortho;
edge [dir=none];
node [shape=diamond, label="", height=0.1, width=0.1];
start -> a [weight=10];
start -> b;
start -> c;
start -> d;
start -> e;
}
But it ends up looking like this:
Any clue on how I can make the edges overlap each other?
You need to create empty nodes on the same level as start and connect to them first, then draw the rest of your graph:
digraph G
{
node[ shape = point, label="", height=0, width=0 ] 01 02 03 04;
node[ shape=diamond, label="", height=0.1, width=0.1 ];
{ rank = same; start 01 02 03 04; }
edge [dir=none];
start -> 01 -> 02 -> 03 -> 04[ minlen = 2 ];
start -> a [weight=2];
01 -> b;
02 -> c;
03 -> d;
04 -> e;
}
yields
I'm trying to get the following dot file to output two subgraphs. I want the bLoop node in cluster0 to align with the ISR struct in cluster 2. I'm using an invisible node to do this now, but with the unintended consequence of lot of gray space left in cluster0.
Is there a way to do what I want without the invisible node?
I can't post images yet, so here's the link.
digraph G {
ranksep=.75;
nodesep = 1.5;
node [shape = none]
node[fontsize=16,fixedsize=false,width=0.7,shape=rectangle];
edge[fontsize=16];
ratio=fill;
splines=false;
compound=true;
subgraph cluster0 {
node [style=filled];
style=filled;
color=lightgrey;
label = "Setup and Background Loop";
a0[label = "Peripheral Configs"];
a1[label = "Solar Library Block Configs"];
a2[label = "Enable Interrupts"];
bgLoop[label = "Start Background Loop"];
e0[shape=rectangle, style=invis, fixedsize=true, width=.01];
a0 -> a1 -> a2 -> bgLoop;
bgLoop ->e0[style=invis]
}
subgraph cluster1 {
node [style=filled, shape = "doublecircle"];
start
style="invis"
}
subgraph cluster2 {
node [shape=record,color=white];
style=filled;
color=lightgrey;
label = "ISRs";
struct1 [shape = record, color=white, label="{<f1> Slow ISR | <f2> Fast ISR }"];
}
concentrate = true;
struct1 -> bgLoop[lhead=cluster0, ltail=cluster4, constraint=true];
bgLoop -> struct1[lhead=cluster4, ltail=cluster0, constraint=true];
struct1 -> e0[style=invis, constraint=true];
start -> a0[lhead=cluster0];
}
you need helper nodes to get the correct rank for struct1.
digraph G {
ranksep=.75;
nodesep = 1.5;
node[fontsize=16,fixedsize=false,width=0.7,shape=rectangle];
edge[fontsize=16];
compound=true
subgraph cluster2 { rank="max"
node [shape=record,color=white];
style=filled;
color=lightgrey;
label = "ISRs";
struct1 [shape = record, color=white, label="{<f1> Slow ISR | <f2> Fast ISR }"];
}
subgraph cluster0 {
node [style=filled];
style=filled;
color=lightgrey;
label = "Setup and Background Loop";
a0[label = "Peripheral Configs"];
a1[label = "Solar Library Block Configs"];
a2[label = "Enable Interrupts"];
bgLoop[label = "Start Background Loop"];
a0 -> a1 -> a2 -> bgLoop;
}
subgraph cluster1 {
node [style=filled, shape = "doublecircle"];
start
style="invis"
}
{node [style=invis]; 0; 1; 2; 3; }
{edge [style=invis]; 0->1->2->3->struct1; }
struct1 -> bgLoop[lhead=cluster0, ltail=cluster2, constraint=false];
bgLoop -> struct1[lhead=cluster2, ltail=cluster0, constraint=false];
start -> a0[lhead=cluster0];
}