Manually / adjusting order of edge and path - graphviz

In the diagram below, I'm looking to have the dashed path/edge going through the middle of the diagram (and therefore the A -> C -> D path will be at the bottom).
I've spent about 2 hours trying to figure this out, including drawing additional paths using "edge [style="invis"]," but to no avail.
Can someone please assist?
DiagrammeR::grViz("digraph {
graph [layout = dot, rankdir = LR]
node [shape = rectangle]
rec1 [label = 'A']
rec2 [label = 'B']
rec3 [label = 'C']
rec4 [label = 'D']
rec1 -> rec2
rec1 -> rec3
rec1 -> rec4 [style = dashed]
rec2 -> rec4
rec3 -> rec4
}"
)

changed rankdir
used rank= to create 3 ranks
used nodesep to spread A -> D
digraph {
// TB rankdir makes things easier
graph [layout = dot ]
graph [nodesep=.9] // spread nodes on same rank
node [shape = rectangle]
{rank=source
rec2 [label = "B"]
}
{rank=same
rec1 [label = "A"]
rec4 [label = "D"]
}
{ rank=sink
rec3 [label = "C"]
}
rec1 -> rec2
rec1 -> rec3
rec1 -> rec4 [style = dashed]
rec2 -> rec4
rec3 -> rec4
}
Giving:

Related

Centers node in a cluster

I try to draw multiple finite state diagram in graphviz in only one diagram
For now i have this :
digraph D {
rankdir = LR;
node [shape = circle]
subgraph automaton_1 {
invis [shape = point style = invis]
0 [label =<S<SUB>0</SUB>>]
1 [label =<S<SUB>1</SUB>>]
2 [label =<S<SUB>2</SUB>>]
3 [label =<S<SUB>3</SUB>>]
4 [label =<S<SUB>4</SUB>>]
5 [label =<S<SUB>5</SUB>> peripheries = 2]
}
invis -> 0
0 -> 1[label = "a"]
1 -> 2[label = "b"]
0 -> 3[label = "b"]
3 -> 4[label = "c"]
2 -> 5[label = "d"]
4 -> 5[label = "d"]
subgraph automaton_2 {
b_invis [shape = point style = invis]
b_0 [label =<S<SUB>0</SUB>'>]
b_1 [label =<S<SUB>1</SUB>'>]
b_2 [label =<S<SUB>2</SUB>'>]
b_3 [label =<S<SUB>3</SUB>'>]
b_4 [label =<S<SUB>4</SUB>'>]
b_5 [label =<S<SUB>5</SUB>'> peripheries = 2]
}
b_invis -> b_0
b_0 -> b_1[label = "a"]
b_1 -> b_2[label = "b"]
b_0 -> b_3[label = "b"]
b_3 -> b_4[label = "c"]
b_2 -> b_5[label = "d"]
b_4 -> b_5[label = "d"]
invis -> b_invis[constraint=false, style=invis]
}
which give this result : image 1
But i want to have two independently aligned diagram, aligned like this : image 2
You can turn your subgraphs into actual clusters by adding cluster_ to their names. Inside clusters nodes from each of the subgraphs won't be affected by each other.
Here's the corrected code and the result (note that I've also added peripheries=0 for each cluster to remove borders:
digraph D {
rankdir = LR;
node [shape = circle]
subgraph cluster_automaton_1 {
peripheries=0
invis [shape = point style = invis]
0 [label =<S<SUB>0</SUB>>]
1 [label =<S<SUB>1</SUB>>]
2 [label =<S<SUB>2</SUB>>]
3 [label =<S<SUB>3</SUB>>]
4 [label =<S<SUB>4</SUB>>]
5 [label =<S<SUB>5</SUB>> peripheries = 2]
}
invis -> 0
0 -> 1[label = "a"]
1 -> 2[label = "b"]
0 -> 3[label = "b"]
3 -> 4[label = "c"]
2 -> 5[label = "d"]
4 -> 5[label = "d"]
subgraph cluster_automaton_2 {
peripheries=0
b_invis [shape = point style = invis]
b_0 [label =<S<SUB>0</SUB>'>]
b_1 [label =<S<SUB>1</SUB>'>]
b_2 [label =<S<SUB>2</SUB>'>]
b_3 [label =<S<SUB>3</SUB>'>]
b_4 [label =<S<SUB>4</SUB>'>]
b_5 [label =<S<SUB>5</SUB>'> peripheries = 2]
}
b_invis -> b_0
b_0 -> b_1[label = "a"]
b_1 -> b_2[label = "b"]
b_0 -> b_3[label = "b"]
b_3 -> b_4[label = "c"]
b_2 -> b_5[label = "d"]
b_4 -> b_5[label = "d"]
invis -> b_invis[constraint=false, style=invis]
}

Subgraphs horizontal and its nodes vertical aligned

I have problems to organize my subgraphs horizontal and the nodes inside the subgraphs vertical. All of them (subgraphs and nodes) are just on one line (horizontal or vertical).
digraph G {
rankdir = LR;
subgraph cluster_0 {
rankdir = TB;
node [style=filled];
label = "Title 1";
color=black
N1 -> N2;
}
subgraph cluster_1 {
rankdir = TB;
node [style=filled];
label = "Title 2";
color=black
N3 -> N4 -> N5;
}
subgraph cluster_2 {
rankdir = TB;
node [style=filled];
...
}
...
N2 -> N3;
...
N1 [label = "BA_A", fillcolor="green", shape="Msquare"]
N2 [label = "W2", fillcolor="green", shape="octagon"]
N3 [label = "BA_A", fillcolor="green", shape="Msquare"]
N4 [label = "W2", fillcolor="green", shape="octagon"]
N5 [label = "W2_ERROR", fillcolor="red", shape="octagon"]
N6 [label = "W3", fillcolor="green", shape="invtriangle"]
...
}
I also tried with {rank=same; N1; N3; ...;}. This take the nodes out of the subgraphs.
You can use something like that:
digraph G {
rankdir = LR;
subgraph cluster_0 {
{rank=same N1 N2}
label = "Title 1";
N1 -> N2;
}
subgraph cluster_1 {
{rank=same N3 N4 N5}
label = "Title 2";
N3 -> N4 -> N5;
}
subgraph cluster_2 {
node [style=filled];
label = "Title 3";
N6;
}
N2 -> N3;
N5 -> N6;
N1 [label = "BA_A", fillcolor="green", shape="Msquare"]
N2 [label = "W2", fillcolor="green", shape="octagon"]
N3 [label = "BA_A", fillcolor="green", shape="Msquare"]
N4 [label = "W2", fillcolor="green", shape="octagon"]
N5 [label = "W2_ERROR", fillcolor="red", shape="octagon"]
N6 [label = "W3", fillcolor="green", shape="invtriangle"]
}
In your case I'd prefer top-to-bottom layout
digraph G {
rankdir = TB;
node [style=filled];
subgraph cluster_0 {
N1 N2
label = "Title 1";
edge [dir = back]
N2 -> N1;
}
subgraph cluster_1 {
N3 N4 N5
label = "Title 2";
edge [dir = back]
N5 -> N4 -> N3;
}
subgraph cluster_2 {
label = "Title 3";
N6
}
N2 -> N3 [constraint=none];
N5 -> N6 [constraint=none];
N1 [label = "BA_A", fillcolor="green", shape="Msquare"]
N2 [label = "W2", fillcolor="green", shape="octagon"]
N3 [label = "BA_A", fillcolor="green", shape="Msquare"]
N4 [label = "W2", fillcolor="green", shape="octagon"]
N5 [label = "W2_ERROR", fillcolor="red", shape="octagon"]
N6 [label = "W3", fillcolor="green", shape="invtriangle"]
}

Adding labels under subgraphs in Graphviz

I use the following code to produce a graph using dot in Graphviz. I have manually included the coordinates of nodes, as I require four disjoint subgraphs placed adjacent to one another, as in the picture.
I would love to add labels under each of the subgraphs: $G_0$, $G_1$, etc. Adding label under subgraph creates a box and ignores my coordinates alignment. Is there any other way, like placing arbitrary text at specified coordinates? I use "dot -Teps -Kfdp -n trees -o t.eps" for compilation.
digraph Trees {
node [shape=circle, style="filled", fixedsize=true,width=0.6]; 0; 1;2; 3;4; 5;6; 7; 8;9;10;11;12;13;14;15;
0[pos = "0,1!"]
1[fillcolor=red, pos = "-1,2!"]
2[pos = "1,2!"]
3 [pos = "0,-0.5!"]
5[label=1, fillcolor=red, pos = "2,2!"]
4[label=0, fillcolor=red, pos = "3,1!"]
6[label=2, pos = "4,2!"]
7[label=3, pos = "3, -0.5!"]
9[label=1, fillcolor=red, pos = "5,2!"]
8[label=0, fillcolor=red, pos = "6,1!"]
10[label=2, pos = "7,2!"]
11[label=3, fillcolor=red, pos = "6, -0.5!"]
12[label=1, fillcolor=red, pos = "8,2!"]
13[label=0, fillcolor=green, pos = "9,1!"]
14[label=2, pos = "10, 2!"]
15[label=3, fillcolor=green, pos = "9, -0.5!"]
overlap=false;
fontsize=10;
subgraph 1{
edge [dir=none] 1->0 2->0 3->0;
}
subgraph 2{
edge [color=red] 5->4;
edge[color=black, dir=none] 6->4 7->4;
}
subgraph 3{
edge [color=red] 9->8 8->11;
edge [color=black, dir=none] 8->10;
}
subgraph 4{
edge [color=green] 12->13; 13->15;
edge [color=black, dir=none] 13->14;
}
}
The sub-graphs can be made disjoint using clusters and the dot layout engine. The same approach will also permit the introduction of cluster labels. They can be placed at the bottom of the cluster as required without creating dummy nodes.
This way, no absolute positions are required, and, the layout is automatically generated even if other nodes are added. The exact position of the nodes change, but the graphs remain topologically unchanged.
digraph Trees { node [shape = circle, style = "filled", fixedsize = true, width=0.4];
edge [dir = none];
layout = dot; overlap = false; fontsize = 10;
graph [labelloc = "b", penwidth = 0];
{ node [fillcolor = "red"];
1; 5 [label = 1]; 4 [label = 0]; 9 [label = 1];
8 [label = 0]; 11 [label = 3]; 12 [label = 1];
}
2; 0; 3; 6 [label = 2]; 7 [label = 3];
10 [label = 2]; 14 [label = 2];
{ node [fillcolor = "green"];
13 [label = 0]; 15 [label = 3];
}
subgraph cluster1{
label = "Subgraph 1";
{ 1; 2; } -> 0 -> 3;
}
subgraph cluster2{
label = "Subgraph 2";
5 -> 4 [color = red, dir = fwd];
6 -> 4 -> 7;
}
subgraph cluster3{
label = "Subgraph 3";
9 -> 8-> 11 [color=red, dir = fwd];
10 -> 8 [color=black];
}
subgraph cluster4{
label = "Subgraph 4";
12 -> 13 -> 15 [color=green, dir = fwd];
14-> 13;
}
}
Instead of using explicit node positions, you may use a simple directed graph combined with some rank constraints, invisible edges and text nodes instead of subgraph labels:
digraph Trees {
fontsize=10;
node [shape=circle, style="filled", fixedsize=true,width=0.6];
{rank=same;
a1[label=1, fillcolor=red];
a2[label=2];
a3[label=1, fillcolor=red];
a4[label=2];
a5[label=1, fillcolor=red];
a6[label=2];
a7[label=1, fillcolor=red];
a8[label=2];
}
node[label=0];
b1;
b2[fillcolor=red];
b3[fillcolor=red];
b4[fillcolor=green];
node[label=3];
c1;
c2;
c3[fillcolor=red];
c4[fillcolor=green];
node[shape=none, fillcolor=transparent];
d1[label="Label 1"];
d2[label="Label 2"];
d3[label="Label 3"];
d4[label="Label 4"];
edge[dir=none];
a1->b1;
a2->b1;
b1->c1;
c1->d1[style=invis];
a3->b2[dir=forward, fillcolor=red, color=red];
a4->b2;
b2->c2;
c2->d2[style=invis];
a5->b3[dir=forward, fillcolor=red, color=red];
a6->b3[dir=forward, fillcolor=red, color=red];
b3->c3;
c3->d3[style=invis];
a7->b4[dir=forward, fillcolor=green, color=green];
a8->b4[dir=forward, fillcolor=green, color=green];
b4->c4;
c4->d4[style=invis];
edge[style=invis];
a2 -> a3;
a4 -> a5;
a6 -> a7;
}

How can I get the boxes in the same line?

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.

Graphviz .dot node ordering

I'm building a epsilon NFA to recognize a regular expression using the canonical construction. I'm using subgraphs to group various parts of the regular expression. The * operator is giving me particular trouble since dot has decided to move the order of the nodes around. I've tried adding edge weights to force particular edges to be short to keep the order of the edges in line but that does not seem to be working.
What I would like to do is force the nodes in a subgraph in to be placed in a particular order so that the output graph is recognizable as a particular type of (well known) construction. In the example below I would like edges 3, 4, 5 and 6 placed in that order, however the dot places them in the order 6, 3, 4, 5. Any pointers appreciated.
Note that the current weight parameter produces no difference than no weight parameter at all.
I have the following
digraph G {
rankdir = LR;
node [shape = none];
0 [label = "start"];
node [shape = circle];
1 [label = "q1"];
2 [label = "q2"];
3 [label = "q3"];
4 [label = "q4"];
5 [label = "q5"];
node [shape = doublecircle];
6 [label = "q6"];
subgraph re1 {
rank = same;
edge[label = "0"];
1 -> 2;
};
subgraph re2 {
rank = same;
edge[label = "ε"];
3 -> 4 [weight = 10];
edge[label = "1"];
4 -> 5 [weight = 10];
edge[label = "ε"];
5 -> 6 [weight = 10];
5 -> 4 [weight = 1];
6 -> 3 [weight = 1];
};
edge[color=black];
0 -> 1
edge[label = "ε"];
2 -> 3;
}
Here's how I'd write that graph:
First of all, to me this is a graph which goes from top to bottom, not left to right, therefore I removed the rankdir=LR and added rank=same only for nodes 0/1 and nodes 2/3.
I removed all the weights
Most importantly, I added constraint=false to the edges going against the direction of the graph - the one going from node 4 to node 5, and the one from node 6 to node 3.
Here the source:
digraph G {
0 [label = "start", shape = none];
node [shape = circle];
1 [label = "q1"];
2 [label = "q2"];
3 [label = "q3"];
4 [label = "q4"];
5 [label = "q5"];
6 [label = "q6", shape = doublecircle];
{rank = same; 0 -> 1; }
1 -> 2 [label = "0"];
{rank = same; 2 -> 3 [label = "ε"]; }
4 -> 5 [label = "1"];
edge [label = "ε"];
3 -> 4;
5 -> 6;
5 -> 4 [constraint = false];
6 -> 3 [constraint = false];
}
And here's the result:
Now if you want to, you could keep rankdir=LR, just take the markup you posted, remove the weights and add constraint=false to the same edges as I did, it works, too.

Resources