GraphViz ignores my node positions - graphviz

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.

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

How do i get all answers that lead to a specific output

So i am starting with Prolog and had an example task, where i have some points that form a maze and i want to know all the nodes that can lead to node 1.
connected(1,2).
connected(3,4).
connected(5,6).
connected(7,8).
connected(9,10).
connected(12,13).
connected(13,14).
connected(15,16).
connected(17,18).
connected(19,20).
connected(4,1).
connected(6,3).
connected(4,7).
connected(6,11).
connected(14,9).
connected(11,15).
connected(16,12).
connected(14,17).
connected(16,19).
reachable(X,Z) :- connected(X,Z).
reachable(X,Z) :- connected(X,Y),reachable(Y,Z).
I used the following query:
reachable(X,1).
which resulted in a simple false and not all nodes that lead to 1.
I on the other hand expected something like this:
x = 4;
It should be noted that this is a directed Graph.
If I execute the query reachable(X,1)., I get the expected result:
?- reachable(N,1).
N = 4 ;
N = 3 ;
N = 5 ;
N = 6 ;
false.
Which is what one expects based on the following graph:
generated with: dot -Tpng < conn.dot > conn.png and conn.dot:
digraph G {
1 -> 2;
3 -> 4;
5 -> 6;
7 -> 8;
9 -> 10;
12 -> 13;
13 -> 14;
15 -> 16;
17 -> 18;
19 -> 20;
4 -> 1;
6 -> 3;
4 -> 7;
6 -> 11;
14 -> 9;
11 -> 15;
16 -> 12;
14 -> 17;
16 -> 19;
}
Please check whether you have made a small typo or space error in your Prolog file.

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.

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