How to layout boolean combinatorics system with dot - graphviz

I have a problem with layout in Graphviz. I looking for a somewhat general way to have the inbound edges to enter a node evenly spread out on the left side and exit from the middle of the right side.
In short I want to make something like this,
But instead my markup generates this
from this code
graph g {
splines=ortho;
nodesep=0.005
rankdir="LR";
node [shape=box width=.5];
x [shape=none];
y1 [label="y" shape=none];
y2 [label="y" shape=none];
z [shape=none];
f [label="f(x,y,z)" shape=none];
A [label="&"];
B [label="1" ];
C [label="&" ];
D [label="≥1"];
x -- A;
y1 -- A;
A -- D;
y2 -- B;
B -- C [arrowtail="odot"];
z -- C;
C -- D;
D -- f;
{ rank=same; x y1 y2 z }
{ rank=same; A B }
{ rank=same; C }
{ rank=same; D }
{ rank=same; f }
}
I've experimented with the splines, nodsep and pos attributes neither made an acceptable result.

HTML-like labels would be the solution. Unfortunately ports do not work with splines=ortho (issue) and splines do not look great on logic charts. This port/ortho bug also applies to record shape nodes. So basically you are lost.
digraph logic { rankdir=LR
node [shape=plaintext]
nand [label=<
<TABLE CELLBORDER="0" CELLSPACING="0">
<TR>
<TD><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0">
<TR><TD BORDER="0" PORT="1">1</TD></TR>
<TR><TD BORDER="0" PORT="2">2</TD></TR>
</TABLE></TD>
<TD BORDER="0" PORT="out">&</TD>
</TR>
</TABLE>>];
1 -> nand:1:w [dir=none]
2 -> nand:2:w [dir=none]
nand:out:e -> out [dir=back arrowtail=odot]
}

Related

Is it possible to generate a small GraphViz chart?

I need to generate a small graphviz graph that represents a "price map" of the main graphviz. The main graph is:
digraph g {
graph [rankdir = "LR"];
a [label = "<f0>a | <f1> $139 | <f2> Chair | Brown" shape = "record"];
b [label = "<f0>b | <f1> $280 | <f2> Speakers | Grey" shape = "record"];
c [label = "<f0>c | <f1> $89 | <f2> Jacket | Beige" shape = "record"];
d [label = "<f0>d | <f1> $19 | <f2> Mug | Green" shape = "record"];
e [label = "<f0>e | <f1> $180 | <f2> Printer | Grey" shape = "record"];
a -> b; a -> c; c -> d; c -> e;
}
and it generates:
When I try to generate a "small" price map like:
digraph g {
graph [rankdir = "LR"];
node [shape=box];
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
I get:
But I wanted a really small price map, like:
Is this possible?
You should really read the dot guide which is a pretty impressive view across using dot (although HTMl nodes don't feature so much): http://graphviz.org/pdf/dotguide.pdf
Try changing the shape to plain:
node [shape=plain];
Result:
Another possibility is to use HTML nodes - my answer in this example shows compact nodes https://stackoverflow.com/a/68320427/2318649
Another way to control spacing is useing nodesep and ranksep on the graph, for example:
digraph g {
graph [rankdir="LR" nodesep=0.1 ranksep=0.2];
node [shape=plain];
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
Result:
Another way to minimize the space inside a box node is setting margin, width and height all to 0:
digraph g {
graph [rankdir="LR" nodesep=0.1 ranksep=0.2];
node [shape=box margin=0 width=0 height=0];
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
Result:
You can control the arrow size on each edge, e.g.:
a -> b [arrowsize=0.5]; a -> c [arrowsize=0.5]; c -> d [arrowsize=0.5]; c -> e;
result:
Or you can control arrowsize across all edges:
digraph g {
graph [rankdir="LR" nodesep=0.1 ranksep=0.2];
node [shape=box margin=0 width=0 height=0];
edge [arrowsize=0.5]
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
Result:
Read about attributes: http://graphviz.org/doc/info/attrs.html
Read about nodes: http://graphviz.org/doc/info/shapes.html
Read about using dot: http://graphviz.org/pdf/dotguide.pdf

Using Graphviz / yed to produce a timeline + graph

I had an idea of representing something like a family tree where nodes are connected by directed graphs but to add an additional dimension of time on the y-axis. So imagine the top of the page representing 1900 and all the way down to the bottom being 2020.
Is there a way to do something like this in Graphviz or yed? Basically auto layout a specified digraph but the position of nodes on the y axis is linked to time?
Here is shells.gv - part of the source:
digraph shells {
size="7,8";
node [fontsize=24, shape = plaintext];
1972 -> 1976;
1976 -> 1978;
1978 -> 1980;
1980 -> 1982;
1982 -> 1984;
1984 -> 1986;
1986 -> 1988;
1988 -> 1990;
1990 -> future;
node [fontsize=20, shape = box];
{ rank=same; 1976 Mashey Bourne; }
{ rank=same; 1978 Formshell csh; }
{ rank=same; 1980 esh vsh; }
{ rank=same; 1982 ksh "System-V"; }
{ rank=same; 1984 v9sh tcsh; }
{ rank=same; 1986 "ksh-i"; }
{ rank=same; 1988 KornShell Perl rc; }
{ rank=same; 1990 tcl Bash; }
{ rank=same; "future" POSIX "ksh-POSIX"; }
Thompson -> Mashey;
Thompson -> Bourne;
Thompson -> csh;
csh -> tcsh;
Bourne -> ksh;
Bourne -> esh;
Bourne -> vsh;
Bourne -> "System-V";
Bourne -> v9sh;
v9sh -> rc;
Bourne -> Bash;
"ksh-i" -> Bash;
KornShell -> Bash;
esh -> ksh;
vsh -> ksh;
Formshell -> ksh;
csh -> ksh;
KornShell -> POSIX;
"System-V" -> POSIX;
ksh -> "ksh-i";
"ksh-i" -> KornShell;
KornShell -> "ksh-POSIX";
Bourne -> Formshell;
edge [style=invis];
1984 -> v9sh -> tcsh ;
1988 -> rc -> KornShell;
Formshell -> csh;
KornShell -> Perl;
}
Producing this:
The graph you want in Graphviz is pretty straightforward, you just switch on the dir=TD, separate your nodes into subgraphs and use rank=same inside them to force them be on the same level.
The tricky part may be with achieving the Z node on your example. You can do it using HTML-like tables in the label. Full graphviz interpretation of your example picture will look like this:
digraph {
node [shape=rect style=filled fillcolor="#d2deee" fontname="Arial"]
edge [color="#658bb2"]
dir = TD
1900 -> 1950 -> 2020 [style=invis]
subgraph 1900 {
rank=same
1900 [
fillcolor="#efefef"
fontcolor="#182697"
fontname="Arial bold"
]
A
}
subgraph 1950 {
rank=same
1950 [
fillcolor="#efefef"
fontcolor="#182697"
fontname="Arial bold"
]
B
}
subgraph 2020 {
rank=same
2020 [
fillcolor="#efefef"
fontcolor="#182697"
fontname="Arial bold"
]
C
}
Z [
shape=plain
label=<
<table cellspacing="0">
<tr>
<td cellpadding="15" border="0" width="70" port="p1"></td>
<td border="0">Z</td>
<td cellpadding="15" border="0" width="70" port="p2"></td>
</tr>
</table>
>
]
A -> Z:p1
B -> Z:p2
Z -> C
C
}
which will render you:

trying to create ranked subgraphs in graphviz

I've tried to make something like this using Graphviz:
x y z
| | |
# | |
a#__\| |
# /#b |
# #__\|
# # /#c
# d#/__#
# #\ x
# # |
e#/__# |
#\ # |
But ranking doesn't seem to be working as I expect. I want e to be below all of the other nodes.
digraph x
{
rankdir = tb;
size = "7.5, 7.5";
rank = source;
a -> b -> c -> d -> e;
subgraph "cluster x"
{
style=filled;
color=lightgrey;
label="x";
a -> e [style=invis];
}
subgraph "cluster y"
{
label="y";
b -> d [style=invis];
}
subgraph "cluster z"
{
label="z";
c;
}
}
I've tried to use clusterrank = global which sort of works, but then the subgraphs are not separated into a more obvious column and there's overlap over the columns. It also is not going to the right like I want. The following image highlights one of the overlaps in red, but as you can see there are 4.
digraph x
{
rankdir = tb;
rankstep=equally;
clusterrank = global;
size = "7.5, 7.5";
a -> b -> c -> d -> e;
subgraph "cluster x"
{
style=filled;
color=lightgrey;
label="x";
a -> e [style=invis];
}
subgraph "cluster y"
{
label="y";
b -> d [style=invis];
}
subgraph "cluster z"
{
label="z";
c;
}
}
I've tried to make a separate cluster that is going to have a guaranteed top to bottom ranking and then rank the appropriate clusters together, but it does the same as the previous attempt, removing the boxes seen the the first attempt and causing unwanted overlapping.
digraph x
{
rankdir = tb;
1 -> 2 -> 3 -> 4 -> 5;
a -> b -> c -> d -> e;
{ rank=same; 1; a; }
{ rank=same; 2; b; }
{ rank=same; 3; c; }
{ rank=same; 4; d; }
{ rank=same; 5; e; }
subgraph "cluster x"
{
style=filled;
color=lightgrey;
label="x";
a -> e [style=invis];
}
subgraph "cluster y"
{
label="y";
b -> d [style=invis];
}
subgraph "cluster z"
{
label="z";
c;
}
}
Anyone have any ideas as to try and get the layout I want?
As a side note, I tried to login to the Graphviz forum regarding this matter, but found that logging in from this page doesn't seem to work. I keep getting a long timeout problem. I check my email account and nothing is there. I try creating a new account with the same email and it says that the account is already in use. I then try and get them to reset my password and I get another timeout problem.
Does anyone know who I can contact to try and fix that annoying login problem? Maybe someone who is already logged in can post that for me?
Run dot with -Gnewrank. That will get you what you want based on your sketch. If more tweaks are needed, please specify what you are after.
Your last solution will work as soon as you do a minor tuning
Use newrank=true to avoid of "unboxing" clusters
Play with splines=... to adjust arrows
Define label as separate nodes.
digraph x
{
rankdir = tb;
newrank=true;
splines=ortho;
0 -> 1 -> 2 -> 3 -> 4 -> 5;
X; Y; Z;
a -> b -> c -> d -> e;
{ rank=same; 0 X Y Z}
{ rank=same; 1; a; }
{ rank=same; 2; b; }
{ rank=same; 3; c; }
{ rank=same; 4; d; }
{ rank=same; 5; e; }
subgraph "cluster x"
{
style=filled;
color=lightgrey;
a -> e [style=invis];
}
subgraph "cluster y"
{
b -> d [style=invis];
}
subgraph "cluster z"
{
c;
}
}

Straight edge between clusters in Graphviz

I'm trying to have an edge between clusters in Graphviz where the edge does not affect the ranking.
This looks fine:
digraph {
subgraph clusterX {
A
B
}
subgraph clusterY {
C
D
}
A -> B
B -> C [constraint=false]
C -> D
}
However when I add a label to the C -> D edge the B -> C edge tries to circumvent said label (which looks ugly).
digraph {
subgraph clusterX {
A
B
}
subgraph clusterY {
C
D
}
A -> B
B -> C [constraint=false]
C -> D [label=yadda]
}
Any idea how I can keep the edge from B to C straight?
The easiest way to achieve this is to add splines=false to the dot file - this forces the rendering of the edges to be straight lines:
digraph {
splines=false;
subgraph clusterX {
A;
B;
}
subgraph clusterY {
C;
D;
}
A -> B;
B -> C [constraint=false];
C -> D [label=yadda];
}
Output:
You can use this version :
digraph G {
subgraph cluster_X {
A [ pos = "0,1!" ];
B [ pos = "0,0!" ];
}
subgraph cluster_Y {
C [ pos = "1,1!" ];
D [ pos = "1,0!" ];
}
A -> B
B -> C[label="yadda"]
C -> D;
}
Then you use neato (not dot)
neato -Tpng -oyadda.png yadda.dot
And the result is :
Instead of the label attribute, you can use the attributes xlabel or headlbel or taillabel.
Result with xlabel:
Script:
digraph {
subgraph clusterX { A B }
subgraph clusterY { C D }
A -> B
B -> C [constraint=false]
C -> D [xlabel=yadda]
}
Result with headlabel:
Script:
digraph {
subgraph clusterX { A B }
subgraph clusterY { C D }
A -> B
B -> C [constraint=false]
C -> D [headlabel=yadda]
}
Result with taillabel:
Script:
digraph {
subgraph clusterX { A B }
subgraph clusterY { C D }
A -> B
B -> C [constraint=false]
C -> D [taillabel=yadda]
}

subgraph cluster ranking in dot

I'm trying to use graphviz on media wiki as a documentation tool for software.
First, I documented some class relationships which worked well. Everything was ranked vertically as expected.
But, then, some of our modules are dlls, which I wanted to seperate into a box. When I added the nodes to a cluster, they got edged, but clusters seem to have a LR ranking rule. Or being added to a cluster broke the TB ranking of the nodes as the cluster now appears on the side of the graph.
This graph represents what I am trying to do: at the moment, cluster1 and cluster2 appear to the right of cluster0.
I want/need them to appear below.
<graphviz>
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
</graphviz>
The layout is an attempt by Dot to minimise the overall height.
One reason for the more compact than required layout is the use of the edge that goes in the reverse direction from dll1_a to B1. It tries to pull the cluster as close back to the destination node as possible. To avoid this edge affecting the graph, either relax the constraint on the upwards edges as shown, or draw the edge in the forward direction and use the dir attribute to reverse the arrow.
This will help with many layouts but it alone is not sufficient to fix the example given. To prevent Dot from maintaining the compact layout it prefers you can add a minlen attribute to edges that should remain (near) vertical. This may be difficult to calculate in general but is practical for manually tuned layouts.
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [constraint = false];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
My experience shows that constraint=false commonly gives unnecessarily convoluted edges. It seems that weight=0 gives better results:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [weight = 0];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
This will produce the graph you are looking for:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph {
rankdir="TB"
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
}
dll1_A -> dll2_A;
}
What this does is creat a subgraph that is used only for layout purposes to provide the top to bottom ordering that you desire.

Resources