How to make this graph in graphviz? - graphviz

My graph:
I could do this by setting the coordinates of each vertex. But I do not know how to set the pixel coordinates.
My attempt to do so:
digraph {
node [shape=circle]
edge [arrowhead=none]
rankdir = BT;
0 -> {1; 2;}
1 -> {3; 4;}
2 -> {4; 8;}
3 -> {9; 5;}
4 -> {5; 10;}
5 -> 11
6 -> {7; 12; 8;}
7 -> {9; 10}
8 -> {10; 14}
9 -> {15; 11}
10 -> {11; 16}
11 -> 17
12 -> {13; 14}
13 -> {15; 16}
14 -> 16
15 -> 17
16 -> 17
0 [pos = "5,0!"]
1 [pos = "4,1!"]
2 [pos = "6,1!"]
3 [pos = "3,2!"]
4 [pos = "5,2!"]
5 [pos = "4,3!"]
6 [pos = "6,3!"]
7 [pos = "4,4!"]
8 [pos = "6,4!"]
9 [pos = "3,5!"]
10 [pos = "5,5!"]
11 [pos = "4,6!"]
12 [pos = "6,6!"]
13 [pos = "4,7!"]
14 [pos = "6,7!"]
15 [pos = "3,8!"]
16 [pos = "5,8!"]
17 [pos = "4,9!"]
}
I renamed the nodes with the letters on the number.
Result:

ex2.dot file:
digraph {
node [ shape=circle, fixedsize=true, width=0.3 ]
edge [ arrowhead=none ]
0 -> {1; 3; 6;}
1 -> {2; 4; 7;}
2 -> {5; 8;}
3 -> {4; 9;}
4 -> {5; 10;}
5 -> 11
6 -> {7; 9; 12;}
7 -> {8; 10; 13;}
8 -> {14; 11;}
9 -> {10; 15;}
10 -> {11; 16;}
11 -> 17
12 -> {13; 15}
13 -> {14; 16}
14 -> 17
15 -> 16
16 -> 17
0 [ pos = "6.00,0.00!" ]
1 [ pos = "5.10,0.30!" ]
2 [ pos = "4.20,0.60!" ]
3 [ pos = "6.60,0.60!" ]
4 [ pos = "5.70,0.90!" ]
5 [ pos = "4.80,1.20!" ]
6 [ pos = "6.30,1.53!" ]
7 [ pos = "5.40,1.83!" ]
8 [ pos = "4.50,2.13!" ]
9 [ pos = "6.90,2.13!" ]
10 [ pos = "6.00,2.43!" ]
11 [ pos = "5.10,2.73!" ]
12 [ pos = "6.60,3.06!" ]
13 [ pos = "5.70,3.36!" ]
14 [ pos = "4.80,3.66!" ]
15 [ pos = "7.20,3.66!" ]
16 [ pos = "6.30,3.96!" ]
17 [ pos = "5.40,4.26!" ]
}
Command:
dot -Kfdp -n -Tpng -o ex2.dot.png ex2.dot
Result:

Related

How to prevent the subgraph cluster alignment order from being reversed?

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

Determine if the resulting value of a function is odd or even

I am solving a hailstone problem, but with a twist, you are given the length, find the value of x if the hailstone starts with 1
I thought it could be determined, if I alternatively change odd and even, and reverse the equation like so:
function r(len, prev, isEven) {
if(len < 1) return prev;
if(isEven) {
return r(len - 1, prev * 2, !isEven);
} else {
return r(len - 1, (prev - 1) * 3, !isEven);
}
}
Now I realized it wasn't just alternate seq., what mathematical concept should I apply in this problem.
Example:
if Len = 8, answer is 6
since:
6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
Just output 2^len :)
Imagine, for len = 8, 6 is a valid answer, because 6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
again, 2^len = 2^8 = 256 is also valid, because 256 -> 128 -> 64 -> 32 -> 16 -> 8 -> 4 -> 2 -> 1
function r(len , pre){
if (len <1) return prev
if ((pre-1)/3 == 1 && (pre-1)%3== 0) || ((pre-1)/3 > 1 && (pre-1)%3 != 0) || (pre<=3 && pre>=1) {
return r(len-1 , 2*pre)
}
elsif((pre-1)/3 > 1 && (pre-1)%3 == 0){
return r(len-1 , (pre-1)/3)
}
}

GraphViz ignores my node positions

I can't get GraphViz to respect some node positions, even though they have pos attributes with !. E.g.:
digraph Versions {
ranksep=0.05;
node [style=filled, shape=point, fillcolor=black, fixedsize=true, width=0.3, height=0.1, fontname="Helvetica", fontsize=8, fontcolor=white];
edge [arrowhead=none, len=0.1];
2 [pos="0,0!", fillcolor=red];
3 [pos="20,0!", fillcolor=red];
4 [pos="40,0!", fillcolor=red];
5 [pos="60,0!", fillcolor=red];
6 [pos="80,0!", fillcolor=red];
7 [pos="100,0!", fillcolor=red];
8 [pos="120,0!", fillcolor=red];
9 [pos="140,0!", fillcolor=red];
10 [pos="160,0!", fillcolor=red];
11 [pos="180,0!", fillcolor=red];
12 [pos="200,0!", fillcolor=red];
13 [pos="220,0!", fillcolor=red];
2 -> 14;
14 -> 15;
3 -> 16;
16 -> 17;
11 -> 18;
18 -> 19;
6 -> 20;
20 -> 21;
10 -> 22;
22 -> 23;
13 -> 24;
24 -> 25;
9 -> 26;
26 -> 27;
4 -> 28;
28 -> 29;
7 -> 30;
30 -> 31;
5 -> 32;
32 -> 33;
8 -> 34;
34 -> 35;
12 -> 36;
36 -> 37;
15 -> 38;
38 -> 39;
17 -> 40;
40 -> 41;
19 -> 42;
42 -> 43;
// etc.
}
The top most rank should be evenly distributed, but is not. The horizontal spacing between the top most nodes is not the same:
From the documentation of the pos attribute:
In neato and fdp, pos can be used to set the initial position of a node.
Are you using neato or fdp? Because dot does not respect this attribute.
Assuming you're using neato, here's an excerpt from the manual:
-n[1|2] (no-op) If set, neato assumes nodes have already been positioned and all nodes have a pos attribute giving the positions
This means you can render a graph with
neato -n2 -Tpng mygraph.gv -o mygraph.png
and have neato respect the pos attributes (in points) of the nodes.
This also states that all nodes must have a pos attribute.
Since some nodes of your graph do not have a pos attribute, this will lead to an error.

How to add "irrelevant" edges

I have this graph:
digraph G {
1 [label="car"];
2 [label="x"];
3 [label="car"];
4 [label="y"];
5 [label="cdr"];
6 [label="cdr"];
7 [label="cons"];
8 [label="x1"];
9 [label="x2"];
10 [label="cons"];
11 [label="y1"];
12 [label="y2"];
13 [label="f"];
14 [label="f"];
15 [label="car"];
16 [label="cdr"];
17 [label="car"];
18 [label="cdr"];
1 -> 2;
3 -> 4;
5 -> 2;
6 -> 4;
7 -> 8;
7 -> 9;
10 -> 11;
10 -> 12;
13 -> 2;
14 -> 4;
15 -> 7;
16 -> 7;
17 -> 10;
18 -> 10;
}
and I want to add these other edges:
1 -> 3 [style="dashed"];
2 -> 7 [style="dashed"];
3 -> 8 [style="dashed"];
4 -> 10 [style="dashed"];
5 -> 6 [style="dashed"];
6 -> 9 [style="dashed"];
7 -> 10 [style="dashed"];
8 -> 11 [style="dashed"];
9 -> 12 [style="dashed"];
13 -> 14 [style="dashed"];
15 -> 8 [style="dashed"];
16 -> 9 [style="dashed"];
17 -> 11 [style="dashed"];
18 -> 12 [style="dashed"];
but without altering the layout.
I tried setting the edge weight to 0, but it doesn't work.
Thanks
You can simply add
edge[constraint=false];
before adding the irrelevant edges.
Without:
With the edges:
(There still seem to be some small changes)

graphviz: minor tweaks to make the graph look nicer

I have a test graph here that I would like to tweak to make it look nicer.
Here is the graphviz (dot) source, test6.dot:
digraph G {
ranksep=0.3; size="6.0,6.0";
node [fontsize=11];
subgraph clusterA {
X2 [shape=box];
node [style=filled];
1 -> 2 -> 3 -> X2 -> 5;
6;
7;
label = "A";
color=blue
}
X1 [shape=box];
subgraph clusterB {
node [style=filled];
8;
9;
10 -> 11 -> 12;
12 -> 9;
12 -> 8 -> 13;
13 -> 14;
label = "B";
color=blue
}
subgraph clusterC {
label = "C";
{
node [style="invis"];
gap;
}
node [shape=box];
edge [style="invis"];
X3 -> gap -> X4;
}
14 -> X4 -> 3;
6 -> X1 -> 10;
{ edge [dir="both"];
8 -> X3 -> 7;
}
9 -> X3
}
Questions / changes I would like to make:
I want the flow of nodes 10 -> 11 -> 12 -> 8 -> 13 -> 14 to be in a vertical line (swap 8 and 9 horizontally). How can I do this? (same with 1 -> 2 -> 3 -> X2 -> 5; swap 6 and 1)
I want X1 to be at the same vertical position as 10, and the same horizontal position as 6. How can I do this?
I want 8 and X3 and 7 to be at the same vertical position, also with 14 and X4 and 3. How can I do this?
The ranksep=0.3; statement works great except note that 8 -> 13 -> 14 has a larger gap, as does X3 -> gap -> X4. Why doesn't it obey the ranksep=0.3 rule, and how do I fix this?
Below is the best I can do: phantom nodes and edges help. But I can't seem to encourage a particular ordering in the transverse direction (the other direction from rankdir).
digraph G {
ranksep=0.3; size="6.0,6.0";
rankdir=TB;
node [fontsize=11];
subgraph clusterA {
X2 [shape=box];
label = "A";
color=blue;
node [style=filled];
/* force 1, 6, and 7 to be at the top together,
add enough phantoms to keep things in nice columns */
{
node [style="invis", label=""];
phantom3;
phantom4;
phantom5;
phantom6;
}
rank = same;
1 -> 2 -> 3 -> X2 -> 5;
edge [style="invis"];
6 -> phantom3 -> phantom5;
7 -> phantom4 -> phantom6;
}
subgraph clusterB {
node [style=filled];
label = "B";
color=blue;
/* create an invisible phantom node
to take up space */
{
node [style="invis",label=""];
phantom1;
phantom1b;
}
{ rank=same; 11;
phantom1;
}
10 -> 11 -> 12 -> 8 -> 13 -> 14;
12 -> 9;
phantom1 -> 9 -> phantom1b [style="invis"];
}
/* force X1 to be at the same vertical pos as 10
(this yields a warning though) */
{ rank = same;
X1 [shape=box];
10;
}
6 -> X1;
X1 -> 10 [weight=0.5];
subgraph clusterC {
label = "C";
phantom2 [style="invis", label=""];
node [shape=box];
edge [style="invis"];
X3 -> phantom2 -> X4;
}
9 -> X3 [weight=0.5];
{
edge [weight=20];
14 -> X4 -> 3;
3 -> X4 -> 14 [style="invis"];
/* add a reverse path so graphviz doesn't force 14 above X4 above 3 */
}
{
edge [dir="both", weight=20];
8 -> X3 -> 7;
7 -> X3 -> 8 [style="invis"];
edge [style="invis"];
X4 -> phantom6;
1 -> phantom2;
8 -> phantom2;
}
}

Resources