I'm struggling with directed graph hierarchy tree visualization (distributed network in this case). Using graphviz: dot I have this tree:
digraph G {
node[width=0.14, height=0.14];
edge[weight=3, color = "0.000 0.000 0.0"];
1 -> 2;
1 -> 3;
edge[weight=2, color = "0.000 0.000 0.175"];
2 -> 4;
2 -> 5;
3 -> 6;
3 -> 7;
edge[weight=1, color = "0.000 0.000 0.825"];
3 -> 4;
3 -> 5;
2 -> 6;
2 -> 7;
}
Resulting in:
You can see that the primary paths (edges with higher weights) are crossed. The goal is to have the preferred path nodes as close as possible. I can do it by changing the order of nodes randomly so the output looks like this:
However I don't want to think about the ordering algorithm as I want to automate this on hundreds of nodes.
From documentation:
The weight of an edge provides another way to keep edges straight. An edge’s weight suggests some measure of an edge’s importance; thus, the heavier the weight, the closer together its nodes should be. dot causes edges with heavier weights to be drawn shorter and straighter.
But this is not the case as the nodes are drawn in random order. What am I doing wrong?
Probably not the answer you were looking for, but since dot doesn't seem to work with edge weights in this case:
You may just use constraint=false for the lightgray edges.
Could you live with a solution like this, which places invisible ranks and invisible edges to enforce the left-to-right ordering of your nodes? While it adds some white space to the left of the diagram, at least it neatly solves the random-ordering issue within each rank, and lends itself to being automated.
digraph G {
node[width=0.14, height=0.14];
{
rankdir="TB";
edge [style=invis];
rank1 [style=invis];
rank2 [style=invis];
rank3 [style=invis];
rank1 -> rank2 -> rank3 [style=invis];
}
edge[weight=3, color = "0.000 0.000 0.0"];
1 -> 2;
1 -> 3;
edge[weight=2, color = "0.000 0.000 0.175"];
2 -> 4;
2 -> 5;
3 -> 6;
3 -> 7;
{
edge [style=invis];
rank=same;
rank2 -> 2 -> 3;
}
edge[weight=1, color = "0.000 0.000 0.825"];
3 -> 4;
3 -> 5;
2 -> 6;
2 -> 7;
{
rank=same;
edge [style=invis];
rank3 -> 4 -> 5 -> 6 -> 7 ;
}
}
Related
Consider the directed cyclic graph given below;
If a starting point (eg: vertex 0) and a maximum depth allowed is specified (eg: 5), what algorithm can be used to find all possible paths (note: a given vertex can be visited more than once)?
What is the most efficient algorithm to implement this graph problem?
Some of the possible paths for the above graph are given below in no particular order (starting with vertex 0 and maximum depth allowed is 5).
0 -> 1 -> 2 -> 4 -> 1 -> 3
0 -> 1 -> 2 -> 4 -> 5 -> 1
0 -> 1 -> 2 -> 4 -> 5 -> 6
0 -> 1 -> 3 -> 5 -> 1 -> 3
Pseudo algorithm for this will be an augmented BFS that keeps track of the path it has gone through. When it hits the required depth, it registers the path and then terminates.
Something like this (node.js style syntax):
const requiredDepth = X
const relevantPaths = {}
const runBFS = (curNode, curPath = []) => {
if (crPath.length === requiredDepth) {
relevantPaths.push(curPath)
return
}
for (let neighbor of curNode.neighbors) {
const newPath = [ ...curPath, getEdge(curNode, neighbor) ]
runBFS(neighbor, newPath)
}
}
runBFS(root)
Hope this helps
I'm trying to align this graph, whose purpose is to show the results of sorting.
I need a general solution.
The dot file is generated, so I can't use hand tweaking.
I've tried pos, pos with !, dot -n, dot -Kneato, dot -Kfdp, and other things.
Here is the source (laid out for human grokkability):
digraph x {
rankdir=LR
11 [pos="1,1"] 21 [pos="2,1"] 31 [pos="3,1"] 41 [pos="4,1"]
12 [pos="1,2"] 22 [pos="2,2"] 32 [pos="3,2"] 42 [pos="4,2"]
13 [pos="1,3"] 23 [pos="2,3"] 33 [pos="3,3"]
14 [pos="1,4"] 24 [pos="2,4"]
11:e -> 21:w 21:e -> 31:w 31:e -> 41:w
12:e -> 22:w 22:e -> 32:w 32:e -> 42:w
22:e -> 31:w
# 41:e -> 21:w
# 41:e -> 22:w
# 12:e -> 12:w
# 32:e -> 32:w
13:e -> 23:w 23:e -> 33:w
14:e -> 24:w
# 13:e -> 14:w
# 14:e -> 13:w
# 23:e -> 24:w
# 24:e -> 23:w
}
In the first rendering, you'll see essentially how it should look (except for the shuffled row order).
Later renderings, which will include cyclic edges, should retain this basic layout.
dot -Tpng -o test.png test.dot:
Now some renderings after uncommenting the cyclic edges.
dot -Tpng -o test.png test.dot:
dot -Kneato -Tpng -o test.png test.dot:
dot -Kfdp -Tpng -o test.png test.dot:
Not using pos as in my experience (confirmed by your attempts), it does not work well with the dot engine, and with neato and others I have never been able to produce something like a grid layout.
Three general steps to get closer with dot:
align the nodes vertically with rank = same
align the nodes horizontally using weight = 10 (or any other arbitrary number that works)
add invisible vertical struts as necessary (here 14 -> 12)
make sure that you point the edges following the established hierarchy, meaning explicitly using dir = back where appropriate
My shot at your situation:
digraph
{
rankdir = LR;
{rank = same; 14 -> 13 -> 12 -> 11[ style = invis ] }
{rank = same; 24 -> 23 -> 22 -> 21[ style = invis ] }
{rank = same; 33 -> 32 -> 31[ style = invis ] }
{rank = same; 42 -> 41[ style = invis ] }
14 -> 24[ weight = 10 ];
13 -> 23 -> 33[ weight = 10 ];
12 -> 22 -> 32 -> 42[ weight = 10 ];
11 -> 21 -> 31 -> 41[ weight = 10 ];
22:e -> 31:w;
12:e -> 12:w
32:e -> 32:w
21:se -> 41:sw[ dir = back ];
22:se -> 41:sw[ dir = back ];
14 -> 12 [ color = red ];
14:w -> 13:w
13:e -> 14:e[ dir = back ];
24:w -> 23:w
23:e -> 24:e[ dir = back ];
}
which yields
I'm using graphviz (dot) to generate time expanded graph to use in my master thesis. However, my drawing results the following graph:
As you can see, the third line is a little bit shifted to the right.I want all the lines in the same horizontal line. Also i want the x.th node in each line to stay at the same horizontal line of other x.th nodes of lines. Changing the edge weights would not helped me.
I could not find anything related to this problem so far.
What i want to achieve is something like this:
Here is my code:
digraph G {
1[label="1"]
2[label="1"]
3[label="1"]
4[label="1"]
5[label="1"]
6[label="1"]
7[label="2"]
8[label="2"]
9[label="2"]
10[label="2"]
11[label="2"]
12[label="2"]
13[label="3"]
14[label="3"]
15[label="3"]
16[label="3"]
17[label="3"]
18[label="3"]
19[label="4"]
20[label="4"]
21[label="4"]
22[label="4"]
23[label="4"]
24[label="4"]
rankdir="LR";
node[width=0.15, height=0.15, shape=point];
edge[weight=500, label="1"];
1 -> 2 -> 3 -> 4 -> 5 -> 6 ;
7 -> 8 -> 9 -> 10 -> 11 -> 12 ;
13 -> 14 -> 15 -> 16 -> 17 -> 18 ;
19 -> 20 -> 21 -> 22 -> 23 -> 24 ;
edge[weight=3];
1 -> 9;
2 -> 9;
3 -> 11;
13 -> 22;
14 -> 22;
15 -> 24;
edge[weight=1];
1 -> 14;
2 -> 15;
3 -> 17;
7 -> 21;
8 -> 23;
9 -> 22;
}
Any help would be appreciated.
Instead of using weight try using the attribute constraint=false for all edges which go from one "line" to another.
Setting constraint to false makes graphviz to not consider those edges when laying out the nodes of the graph.
See also this very similar question & answer
As far as I know, the only way is to specify an explicit position for each individual node.
See: How to force node position (x and y) in graphviz
I have the following dot:
digraph G
{
rank="same";
subgraph sys
{
1 [shape=record, label="| | Système"];
}
subgraph obj
{
2 [shape=box, label="Sites"];
3 [shape=box, label="Sociétés de\nmaintenance"];
1 -> 2 [arrowhead=none] [label="a"];
1 -> 3 [arrowhead=none] [label="b"];
}
subgraph constraints
{
4 [style=dotted, label="Surveiller"];
5 [style=dotted, label="Effectuer des\ninterventions"];
4 -> 2 [style=dotted];
4 -> 3 [style=dotted];
5 -> 2 [style=dotted];
5 -> 3 [style=dotted];
}
}
Which gives me this image:
But I want to have a subgraph by column (1 on the first column, 2-3 on the second and 4-5 on the last).
Is there a way to do that?
For your help,
Thanks by advance.
digraph G
{
rank=same
rankdir=LR
subgraph sys
{
1 [shape=record, label="| | Système"]
}
subgraph obj
{
node [shape=box]
2 [label="Sites"]
3 [label="Sociétés de\nmaintenance"]
}
subgraph constraints
{
node [style=dotted]
4 [label="Surveiller"]
5 [label="Effectuer des\ninterventions"]
}
edge [style=invis, weight=2]
2->4
3->5
edge [style=dotted]
4 -> 2
4 -> 3
5 -> 2
5 -> 3
edge [style="" arrowhead=none]
1 -> 2 [label="a"]
1 -> 3 [label="b"]
}
This solution is the same as suggested by #alexandr_anturis (+1), but I have removed some irrelevant 'syntax noise', because I feel that such a complex and powerful specification as dot language benefits of any simplification available.
Use rankdir and hidden edges with appropriate weight.
Picture of the result:
digraph G
{
rank="same";
layout="dot";
rankdir=LR;
subgraph sys
{
style=filled;
1 [rank=1, shape=record, label="| | Système"];
}
subgraph obj
{
2 [rank=2,shape=box, label="Sites"];
3 [rank=3,shape=box, label="Sociétés de\nmaintenance"];
}
subgraph constraints
{
4 [rank=4,style=dotted, label="Surveiller"];
5 [rank=5,style=dotted, label="Effectuer des\ninterventions"];
}
2->3->4->5 [color=white, weight=100];
rankdir=LR;
4 ->2 [style=dotted, w=0];
4 -> 3 [style=dotted, w=0];
5 -> 2 [style=dotted, w=0];
5 -> 3 [style=dotted, w=0];
1 -> 2 [arrowhead=none] [label="a"];
1 -> 3 [arrowhead=none] [label="b"];
}
You can use something like this. The way to make what you want is to use rankdir and add invisible edges for correct ranking.
I'm generating diagram with graphviz and I have a problem - there are several nodes that are very large - and large number of small nodes. I tried generating png with neato and fdp but both generate very large graphics, which are mostly blank (nodes are very far apart). Is there a way to set a larger spring 'strength' for these tools to force nodes closer together?
When using neato, you may fiddle with the overlap and with the sep attribute.
overlap can be set to false, compress, scalexy, and more.
sep may either designate an additive margin when used with a preceding plus sign, otherwise the margin is defined by scaling the node's size with 1 + the value of sep. It seems that the default
Don't hesitate to post a sample graph. Not knowing your particular graph, I made an example containing some big and some small nodes:
layout=neato;
overlap=scalexy; //false, compress, ...
sep="+1"; // 0.1, +1
node[label="Large node", width=2, height=2];
l1; l2; l3;
node[label="\N", width=0.5, height=0.3];
1 -> l1;
2 -> l1;
3 -> l1;
4 -> l1;
5 -> l1;
5 -> l2;
6 -> l2;
7 -> l2;
8 -> l2;
8 -> l3;
9 -> l3;
10 -> l3;