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:
Related
I am trying to create a plot of a binary, coloring and marking different nodes in different colors.
To get the borders around the subtrees I use subgraphs which works almost perfectly fine:
graph G
{
graph [ranksep="0.25", nodesep="0.25"]
rankdir = TB;
node [shape=ellipse, style=filled, fillcolor="#0068B4", color=white, fontcolor=white, penwidth=10]
edge [arrowtail="none"]
subgraph cluster_0 {
node [fillcolor="#99CC00"]
color="#99CC00"
style=filled
fillcolor=white
fontcolor="#99CC00"
label="12 is the root of\n26's left child\r"
18;
subgraph cluster_01 {
node [fillcolor="#00B0F0"]
color="#00B0F0"
fontcolor="#00B0F0"
style=filled
fillcolor=white
label="4 is the root of \n12's left child \r"
7 [fillcolor=white]
4 -- 13
4 -- 7 [style=invisible]
7 -- 13 [style=invisible]
{ rank=same; 7, 13 }
{ rank=same; 4, 18 }
}
12 -- {4,18}
{ rank=same; 12 }
}
subgraph cluster_1 {
node [fillcolor="#C00000"]
color="#C00000"
style=filled
fillcolor=white
fontcolor="#C00000"
label="32 is the root of\n26's right child\r"
35 [fillcolor=white]
32 -- 38
32 -- 35 [style=invisible]
35 -- 38 [style=invisible]
{ rank=same; 32 }
{ rank=same; 35, 38 }
}
26 -- {12, 32}
{ rank=same; 26 }
}
which leads to this output:
As you can see, the node 18 is placed inside the blue subcluster. Is there an easy way to move that node "out of the box" other than placing a blank dummy node (like the invisible nodes 7 and 35) between 4 and 18?
But, adding graph [newrank=true] and rearranging a few lines makes things better:
graph G
{
graph [ranksep="0.25", nodesep="0.25" newrank=true]
rankdir = TB;
node [shape=ellipse, style=filled, fillcolor="#0068B4", color=white, fontcolor=white, penwidth=10]
edge [arrowtail="none"]
subgraph cluster_0 {
node [fillcolor="#99CC00"]
color="#99CC00"
style=filled
fillcolor=white
fontcolor="#99CC00"
label="12 is the root of\n26's left child\r"
subgraph cluster_01 {
node [fillcolor="#00B0F0"]
color="#00B0F0"
fontcolor="#00B0F0"
style=filled
fillcolor=white
label="4 is the root of \n12's left child \r"
7 [fillcolor=white]
4 -- 13
4 -- 7 [style=invisible]
7 -- 13 [style=invisible]
{ rank=same; 7, 13 }
}
{ rank=same; 4, 18 }
12 -- {4,18}
{ rank=same; 12 }
}
subgraph cluster_1 {
node [fillcolor="#C00000"]
color="#C00000"
style=filled
fillcolor=white
fontcolor="#C00000"
label="32 is the root of\n26's right child\r"
35 [fillcolor=white]
32 -- 38
32 -- 35 [style=invisible]
35 -- 38 [style=invisible]
{ rank=same; 32 }
{ rank=same; 35, 38 }
}
26 -- {12, 32}
{ rank=same; 26 }
}
Gives:
In the following example, the nodes in the subgraphs are ordered from the bottom to the top instead of from top to bottom. How can that be reversed, so that the start is top-left and the nodes in the subgraphs are ordered from top to bottom (A1-A4 and B1-B4)?
digraph ab
{
rankdir=LR
splines=ortho
ranksep=1
node[shape = record]
subgraph cluster_0
{
label="A"
{
rank = "same"
state0_anchor [label="", style=invis, width=0]
state0_step0 [label="A1"]
state0_step1 [label="A2"]
state0_step2 [label="A3"]
state0_step3 [label="A4"]
}
state0_anchor->state0_step0[style = invis]
state0_step0 -> state0_step1 -> state0_step2 -> state0_step3
}
state0_step3 -> state0_step0 [constraint=false]
state0_step3 -> state1_step0 [constraint=false]
subgraph cluster_state1
{
label="B"
{
rank = "same"
state1_anchor [label="", style=invis, width=0, height=0]
state1_step0 [label="B1"]
state1_step1 [label="B2"]
state1_step2 [label="B3"]
state1_step3 [label="B4"]
}
state1_anchor->state1_step0[style = invis]
state1_step0 -> state1_step1 -> state1_step2 -> state1_step3
}
state1_step3 -> state0_step0 [constraint=false]
state0_anchor -> state1_anchor[style = invis]
start -> state0_step0
}
In your example, when direction of the edges within the subgraphs are reversed, the nodes will be ordered the way you'd like. Something like this:
state0_step3 -> state0_step2 [dir=rev]
state0_step2 -> state0_step1 [dir=rev]
state0_step1 -> state0_step0 [dir=rev]
state0_step0 -> state0_anchor [style = invis]
The same for state1-nodes.
Details about transformations when going LR can be found in https://stackoverflow.com/a/9592856/63733
If I have a graphviz dot script like this:
digraph g {
node [style=rounded, shape=box]
subgraph cluster1 {
style="invis"
1 -> 2 -> 3 -> 4 -> 5
}
subgraph cluster2 {
style="invis"
6 -> 7
7 -> 8 -> 11
7 -> 9 -> 11
7 -> 10 -> 11
}
edge[constraint=false];
splines="ortho"
5 -> 6 [weight=0]
}
I get an output that looks like this (what I want):
However, if the labels in some of the nodes at the end become too long, the arrangement gets reversed like this:
digraph g {
node [style=rounded, shape=box]
8 [label="very long label"]
9 [label="very long label"]
10 [label="very long label"]
subgraph cluster1 {
style="invis"
1 -> 2 -> 3 -> 4 -> 5
}
subgraph cluster2 {
style="invis"
6 -> 7
7 -> 8 -> 11
7 -> 9 -> 11
7 -> 10 -> 11
}
edge[constraint=false];
splines="ortho"
5 -> 6 [weight=0]
}
How can I prevent this and force the original ordering method to occur?
You will have to define your long labels after having defined the other; graphviz draws the nodes in the order the are defined.
digraph g {
node [style=rounded, shape=box]
subgraph cluster1 {
style="invis"
1 -> 2 -> 3 -> 4 -> 5
}
subgraph cluster2 {
style="invis"
6 -> 7
7 -> 8 -> 11
7 -> 9 -> 11
7 -> 10 -> 11
}
8 [label="very long label"]
9 [label="very long label"]
10 [label="very long label"]
edge[constraint=false];
splines="ortho"
5 -> 6 [weight=0]
}
yields
I have read this link --> Forcing "main line" nodes into a straight line in Graphviz (or alternatives)
Despite using this - I can not get this right. What do I do wrong?
Why is not the node number 3 at the same level=height when I have put the weight at the same as no 2? Why is node 5 not at the same level=height as no 4 dispite using the same weight?
Is there any why to have the same left margin with the boxes 1 and 4
Thanks!
F
<graphviz>
digraph MMM8
{
rankdir=LR
node [shape=box, width="0.8", height="0.5", fontsize="10"];
edge [weight=2]
1, 2, 3, 6, 7;
edge [weight=1]
4, 5, Nod1, 8;
node [shape = box];
1 [label = "111111111111"];
2 [label = "2"];
3 [label = "3"];
4 [label = "4"];
5 [label = "5"];
6 [label = "6"];
7 [label = "7"];
8 [label = "7"];
9 [label = "9"];
Nod1 [label="N1", shape=diamond,style=filled,label="",height=.1,width=.1] ;
{
1-> 2[label="C1"]
2-> 3
3 -> Nod1
4->Nod1
Nod1->5
5->6
6-> 7
5->8
8-> 9
9-> 7
{
rank = same;
1, 4
}
{
rank = same;
6,8
}
}
</graphviz>
You've got to create a subgroup with rank=same and include each node you want inline in the subgroup.
digraph MMM8
{
rankdir=LR
node [shape=box, width="0.8", height="0.5", fontsize="10"];
node [shape = box];
{
rank=same;
1 [label = "111111111111"];
2 [label = "2"];
3 [label = "3"];
6 [label = "6"];
7 [label = "7"];
}
{
rank=same;
4 [label = "4"];
5 [label = "5"];
8 [label = "8"];
Nod1 [label="N1", shape=diamond,style=filled,label="",height=.1,width=.1] ;
}
9 [label = "9"];
1-> 2[label="C1"];
2-> 3;
3 -> Nod1;
4->Nod1;
Nod1->5;
5->6 ;
6-> 7;
5->8;
8-> 9;
9-> 7;
}
If you want to get all those nodes in line, then you'll have to combine the two subgroups into one and move node 9 into it.
I want to draw two parallel horizontal lines at the top. How to do it?
My code is here. The output lines are of the same height, so it does not work.
digraph G {
graph [center, rankdir=TB, bgcolor=black];
edge [arrowsize=1, color=red, dir=none];
node [penwidth=1, color=white, fontcolor=white, labelloc=b];
BB1P1[shape=point, color=red, width=0.01];
BB1P[shape=point, color=white, width=0.1];
BB1PV[shape=point, color=red, width=0.01];
BB1P2[shape=point, color=red, width=0.01];
BB1P1 -> BB1P -> BB1PV -> BB1P2;
BB2P1[shape=point, color=red, width=0.01];
BB2PV[shape=point, color=red, width=0.01];
BB2P[shape=point, color=white, width=0.1];
BB2P2[shape=point, color=red, width=0.01];
BB2P1 -> BB2PV -> BB2P -> BB2P2;
{ rank=same; BB1P1; BB1P; BB1PV; BB1P2 };
{ rank=same; BB2P1; BB2PV; BB2P; BB2P2 };
}
Actually one invisible node is sufficient:
digraph G {
graph [center, rankdir=TB, bgcolor=black];
edge [arrowsize=1, color=red, dir=none];
node [penwidth=1, color=red, fontcolor=white, labelloc=b, shape=point, width=0.01];
{
rank=same;
BB1P1;
BB1P[color=white, width=0.1];
BB1PV;
BB1P2;
}
{
rank=same;
BB2P1;
BB2PV;
BB2P[color=white, width=0.1];
BB2P2;
}
BB1P1 -> BB1P -> BB1PV -> BB1P2;
BB2P1 -> BB2PV -> BB2P -> BB2P2;
BB1P1 -> BB2P1[style=invis];
}
Or, even simpler, just change rankdir to LR:
digraph G {
graph [center, rankdir=LR, bgcolor=black];
edge [arrowsize=1, color=red, dir=none];
node [penwidth=1, color=red, fontcolor=white, labelloc=b, shape=point, width=0.01];
BB1P[color=white, width=0.1];
BB2P[color=white, width=0.1];
BB1P1 -> BB1P -> BB1PV -> BB1P2;
BB2P1 -> BB2PV -> BB2P -> BB2P2;
}