Graphviz: align nodes horizontally - graphviz

I thought the following would be simple, but for some reason, it really isn't...
Let's start with this:
digraph G {
rankdir=LR
A -> B -> C -> E -> F
}
This is the output:
Now, let's add a backwards relationship:
digraph G {
rankdir=LR
A -> B -> C -> E -> F
E -> A
}
I get this:
In the end, what I want is for the nodes to be aligned horizontally, and the backwards arrow to go around. I'm thinking, easy, with rank=same:
digraph G {
rankdir=LR
{rank=same;A -> B -> C -> E -> F}
E -> A
}
Oops:
Now, it's not even aligned horizontally or even sequentially (it's E, F, A, B, C). So how do I get a layout as in the very first output, with an arrow from E to A going around?

How about:
digraph G {
//rankdir=LR
{rank=same;A -> B -> C -> E -> F}
E -> A
}
the rank=same forces the LR

Related

Make a Graphviz plot more square

I am trying to make plot of several disconnected graphs.
digraph {
// rankdir=RL
subgraph template {
node [shape=square]
edge [color=black]
subgraph top {
node [group=1]
A
B
C
D
E
}
subgraph bottom {
node [group=2]
F
G
H
}
}
C -> c
F -> f
subgraph s1 {
edge [color=red]
A -> a
B -> b1
D -> d1
E -> e1
G -> g1
H -> h1
}
subgraph s2 {
edge [color=blue]
A -> b1
B -> a
D -> d2
E -> e2
G -> g2
H -> h2
}
subgraph s3 {
edge [color=green]
A -> a
B -> b1
D -> d2
E -> e3
G -> g3
H -> h1
}
subgraph s4 {
edge [color=purple]
A -> b1
B -> a
D -> e1
E -> e2
G -> g4
H -> h1
}
subgraph s5 {
edge [ color=orange]
A -> b1
B -> a
D -> d5
E -> e1
G -> g5
H -> h1
}
subgraph s6 {
edge [ color=brown]
A -> a
B -> b1
D -> d1
E -> e6
G -> g6
H -> h1
}
subgraph s6 {
edge [ color=tan]
A -> a
B -> b2
D -> d2
E -> e6
G -> g6
H -> h1
}
}
This creates a short, wide graph.
I would like to have a taller, narrower graph. For example, moving the F, G and H trees under the A-E nodes would be good.
I tried size, which just made the nodes bigger or smaller.
I tried ratio, which stretched the graph but did not move nodes around.
I tried using group and/or rankdir, but neither did what I wanted.
I have mostly tried using fdp, but also tried dot.
I am happy with a solution that either automatically moves the nodes around or requires me to manually move them.
Any suggestions on how to achieve this?
Here are two ways:
(easiest)
make each top-level cluster a stand-alone graph.
run each graph through dot -Tdot myfileX.gv >myfileX.dot
use gvpack (https://graphviz.org/pdf/gvpack.1.pdf) to combine the individual files into one combo graph
run the combo graph through neato -n2 -Tpng >mycombo.png (see https://www.graphviz.org/faq/#FaqDotWithCoords)
gvpack -array_ib1 myfiles*.dot |neato -Tpng -n2 >oooo.png
OR
use invisible edges to connect the nodes from one cluster to another a->C. Unfortunately, this quickly becomes tedious, trying to get all the nodes to line up as you want.

Graphviz nested subgraph orientation

I recently came across the image below. I know it was created with graphviz/dot, but the source code is not available (lost to time).
Desired Output:
I have been trying to find a way to reverse engineer the source code, but the horizontal ordering of the nested subgraphs has been giving me difficulty. A bare minimum mostly-working example looks like this in code
digraph G {
A
B
subgraph cluster_0 {
edge [style=invis]
subgraph cluster_0_0 {
D -> E -> F
}
C -> D -> E -> F -> G
}
A -> C
A -> B
A -> G
B -> { D E F }
}
However, that gives me this output:
Adding newrank=true to the outer subgraph gives me the horizontal orientation I'm looking for:
digraph G {
A
B
subgraph cluster_0 {
newrank=true
edge [style=invis]
subgraph cluster_0_0 {
D -> E -> F
}
C -> D -> E -> F -> G
}
A -> C
A -> B
A -> G
B -> { D E F }
}
But this sets the nodes in the wrong order:
I hope there is a better solution, but here is one (the rest of the node labels should be evident):
digraph G {
newrank=true
splines=false // A->C edge gets wacky without this
node [shape=Mrecord]
// Mrecords produce this Warning:
// flat edge between adjacent nodes one of which has a record shape - replace records with HTML-like labels
// but Mrecords still seem to work, so maybe ignore warning ??
// hoped that ordering or weight or group attributes would
// position C and G as desired, but nope
// instead, clusters and constraint attribute worked, why?
A [group=T label="{Measure|4/4}"]
B [group=T]
A -> B
{
rank=same C F E D G // declare right-to-left ??
}
subgraph clusterCDEFG {
graph [style=rounded]
// within a rank, layout tends to be right-to-left
// so, declare right-to-left ??
// why do these clusters help position C & G ???
subgraph clusterG { peripheries=0
G
}
subgraph clusterDEF {
// declare right-to-left
F
E [group=T]
D
edge [style=invis]
// D -> E -> F
}
// why do these clusters help position C & G ???
subgraph clusterC { peripheries=0
C
}
}
A -> C [constraint=false] // why does this impact position within rank ??
A -> G [constraint=false] // why does this impact position within rank ??
B -> { F E D } // declare right-to-left ??
edge [style=invis]
// C -> D // Mrecord shape has problems
// F -> G // Mrecord shape has problems
}
Giving:

In graphviz, can you bring two vertices closer together?

When describing a graph with graphviz, I sometimes find I want two vertices to appear closer together than the layout engine I chose places them. Is there a way to hint that I want them closer?
I'm mostly interested in the case of two connected vertices, so an answer specific to that case is fine.
Concrete example:
digraph G {
node [shape="circle"];
Start [shape="none" label=""];
C [shape="doublecircle"];
Start -> A;
A -> B [label="0,1"];
B -> C [label="0,1"];
C -> D [label="0,1"];
D -> D [label="0,1"];
}
I want the vertices Start and A to be closer.
You can't do that, but you can make nearly everything else twice as big, here is a start.
(But you can't increase the size of an edge to self)
digraph G {
rankdir=LR
edge[minlen=2 fontsize=28 arrowsize=2 penwidth=2]
node[fontsize=28 height=1 penwidth=2]
graph[fontsize=28 penwidth=2]
node [shape="circle"];
Start [shape="none" label=""];
C [shape="doublecircle"];
Start -> A[minlen=1]; // not twice the size to get the requested effect
A -> B [label="0,1"];
B -> C [label="0,1"];
C -> D [label="0,1"];
D -> D [label="0,1"];
}
[this answer applies specifically to dot]
there is no edge-level attribute that explicitly sets or changes edge length
the graph-level nodesep attribute sets minimum distance between two nodes of same rank
so:
digraph G {
nodesep=.17
{
rank=same
node [shape="circle"];
Start [shape="none" label=""];
C [shape="doublecircle"];
Start -> A;
A -> B [label="0,1"];
B -> C [label="0,1"];
C -> D [label="0,1"];
D -> D [label="0,1"];
}
}
produces:
To increase the distance between the other nodes, you can add spaces to the labels.
I'm not wild about it either, but this change:
B -> C [label=" 0,1 "]; // pad to make label (and edge) longer
produced this:

Graphviz: How to add label to arrows if nodes already have a label

I am making a graph using graphviz dot.
like this
digraph protocol {
label="Protocol workflow";
node[shape=box, style=rounded];
a[label="Byte received"];
b[label="Is start delimiter?", shape=diamond];
c[label="Recv length [n, 1B]"]; c1[label="Set count=n"];
d[label="Recv 1 payload byte and decrement count"];
e[label="count > 0", shape=diamond];
f[label="Recv CRC [2B]"];
g[label="Is CRC valid?", shape=diamond];
a -> b -> c -> c1 -> d -> e -> f -> g;
e -> d;
}
Problem is that to some arrows I need to add yes no labels but I don't know how I could do that.
You may add labels to edges like this:
e -> f [label="Yes"];

How can I create symmetric edges in Graphviz?

I would like the edges between two nodes to be symmetric about a horizontal line. For example, this code:
digraph G {
rankdir=LR
s [style=invisible]
A [peripheries=2]
D [peripheries=2]
B [peripheries=2]
s -> A
A -> C [label="1"]
C -> D [label="0"]
D -> C [label="1"]
A -> B [label="0"]
}
Produces this graph:
I would prefer the edges between C and D to look more like this:
Is there a way to get Graphviz to do this?
You can place a third edge and make the middle one invisible:
C -> D [label="0"];
D -> C [style=invis];
D -> C [label="1"];

Resources