Graphviz draw array data structure - graphviz

I can use "record" to draw one array like this one:
graph G{
node [shape = record];
node0 [fontsize=13, label ="A[0]|A[1]|A[2]"];
}
But how can I draw something like this one
Especially, how can I add the index number for each cell in the array, like 0,1,2,3,4,5.
Which node shape should I use?
Update at 2016/11/11
Ok, I got it based on the answer from https://stackoverflow.com/a/37986662/5374561
The code is here:
digraph so
{
rankdir=LR;
subgraph cluster0
{
rank = same{ Array notes }
color = white;
Array [ shape = record, label = "{ A | B | C | D }"] ;
notes [ shape = record, color = white, label = "{ 0 | 1 | 2 | 3 }" ];
Array -> notes[ style = invis ];
}
nodesep = .0;
}
But the result is not perfect. Is there any other ways?
Update at 2016/Aug/9
The solution from tequlia2pop (thank you) is close to the original pictures, but the line from "pointers" to "values" should be straight line.

digraph {
node [shape=plaintext, fontcolor=red, fontsize=18];
"Pointers:" -> "Values:" -> "Indices:" [color=white];
node [shape=record, fontcolor=black, fontsize=14, width=4.75, fixedsize=true];
pointers [label="<f0> A | <f1> A+1 | <f2> A+2 | <f3> A+3 | <f4> A+4 | <f5> A+5", color=white];
values [label="<f0> A[0] | <f1> A[1] | <f2> A[2] | <f3> A[3] | <f4> A[4] | <f5> A[5]", color=blue, fillcolor=lightblue, style=filled];
indices [label="0 | 1 | 2 | 3| 4 | 5", color=white];
{ rank=same; "Pointers:"; pointers }
{ rank=same; "Values:"; values }
{ rank=same; "Indices:"; indices }
edge [color=blue];
pointers:f0 -> values:f0;
pointers:f1 -> values:f1;
pointers:f2 -> values:f2;
pointers:f3 -> values:f3;
pointers:f4 -> values:f4;
pointers:f5 -> values:f5;
}
which yields

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

Line between connectors of the same node

How can I do the drawing of arrow
A1:Port1 -> A1:Port2 [dir=both]
nicer
So at least same connection point at the same point as the other connector. See picture.
Line between connectors of the same node
Round line between connecoors of the same node
digraph G {
graph [rankdir = LR];
node[shape=record];
A1[label="{A1|{<Port1>Port 1|<Port2>Port 2 }}"];
A2[label="{{<Port1>Port 1|<Port2>Port 2 }|A2}"];
A1:Port1 -> A1:Port2 [dir=both]
A1:Port1 -> A2:Port1 [dir=both]
}
I would introduce an intermediate node:
digraph G {
graph [rankdir = LR];
node[shape=record];
A1[label="{A1|{<Port1>Port 1|<Port2>Port 2 }}"];
A2[label="{{<Port1>Port 1|<Port2>Port 2 }|A2}"];
C[shape=point];
A1:Port1 -> C;
C -> A1:Port2;
C -> A2:Port1;
}
so you get:
Posting it as an answer, so that the resulting graph is clear:
digraph G
{
graph[ rankdir = LR, splines=line] ;
node[ shape=record ];
A1[ label= "{A1|{<Port1>Port 1|<Port2>Port 2 }}" ];
A2[ label= "{{<Port1>Port 1|<Port2>Port 2 }|A2}" ];
A1:Port1:e -> A1:Port2:e [ dir=both ]
A1:Port1 -> A2:Port1 [ dir=both, minlen = 2 ]
}
producing

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;
}
}

How can I direct dot to use a shorter edge path?

The diagram below is laid out almost perfectly, apart from the edge from the left "named pipe" node to "cat", which takes a long circuitous route, instead of the obvious short one I've marked with red on the diagram below. Is there a way to direct dot to use the short edge path? Note that the sequence diagram on the diagram's bottom, must be rendered as it currently appears, i.e. in the left to right order.
This is the code that draws the diagram.
digraph D {
fontname="Arial";
subgraph cluster_async {
label="Asynchronous processes";
style=filled;
color=lightgrey;
node [shape=box, style=solid, fillcolor=white, fontname="Arial"];
{
rank=same;
npi_0_0_0 [label="named\npipe"];
npi_0_3_0 [label="named\npipe"];
npi_0_2_0 [label="named\npipe"];
}
node [shape=box, style=bold];
tee [label="sgsh-tee"];
"ls -l" -> tee;
tee -> npi_0_0_0;
tee -> npi_0_3_0;
tee -> npi_0_2_0;
NBYTES [label="sgsh-writeval -s NBYTES"];
npi_0_3_0 -> "awk '{s += $5} END {print s}'" -> NBYTES;
NDIRS [label="sgsh-writeval -s NDIRS"];
npi_0_2_0 -> "grep -c '^d'" -> NDIRS;
// Put some order in the appearance
{
rank=same;
NDIRS;
NBYTES;
}
}
subgraph clustersync {
label="Synchronous sequence";
style=dashed;
start [shape=circle, style=filled, label="", fillcolor=black, width=.2];
node [shape=box, style=bold, fontname="Arial"];
npi_0_0_0:sw -> cat:nw [constraint=false];
"sgsh-readval -s NDIRS" -> echo;
"sgsh-readval -s NBYTES" -> echo;
NBYTES -> "sgsh-readval -s NBYTES";
NDIRS -> "sgsh-readval -s NDIRS";
end [shape=doublecircle, style=filled, label="", fillcolor=black, width=.2];
{
rank=same;
edge [arrowhead=open];
start -> cat -> echo -> end;
}
}
}
(In case you're interested, the diagram illustrates the setup of an example from sgsh.)
For this graph, setting splines=ortho will produce a desirable result.

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;
}

Resources