Graphviz: Flat horizontal graph with arching edges? - graphviz

I have this code
graph G {
node [shape=circle]
rankdir=LR;
1 -- 10;
2 -- 9;
3 -- 8;
4 -- 7;
5 -- 6;
}
but I want to have the vertices 1 ... 10 in a flat, horizontal row, then with the connecting edges as arcs (alternating above, below) connecting 1 to 10, 2 to 9, etc. My code only produces a stack of vertices and their edges.

You need to tell graphviz first that you want to have the nodes in a row. Only then you can introduce a second set of edges the way you like. There is very limited control as to how graphviz places the edges; Trial and error brought me to the solution below which is the best I could find.
See comments in the code:
graph so
{
node [shape=circle]
rankdir=LR;
// We put all nodes in one row
// We need the weight to keep them straight
// Edge style is invisible, so that they are not in the way of your edges
1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -- 8 -- 9 -- 10[ weight = 10, style = invis ];
1:ne -- 10:nw; // added ports to force node above
2 -- 9; // the rest is graphviz' decision
3 -- 8;
4 -- 7;
5 -- 6;
}
gives you

Try this. Invisible edges are to enforce order within rank. Double 5 -- 6 edge is to enforce arc, otherwise the edge would be straight. I tried it on viz-js.com. The alternation of above and below arcs heavily depends on order of edges. Since it's very sensitive, undocumented and probably prone to minor version change, I don't recommend it as production solution, the DOT engine is IMHO not suitable for such tasks. For one-shot documentation purposes it's sufficient and fulfills your specification.
graph G {
splines=splines;
node [shape=circle];
edge [constraint=false];
rankdir=LR;
1 -- 10;
3 -- 8;
2 -- 9;
1 -- 2 [style=invis, constraint=true];
2 -- 3 [style=invis, constraint=true];
3 -- 4 [style=invis, constraint=true];
4 -- 5 [style=invis, constraint=true];
5 -- 6 [style=invis];
4 -- 7;
5 -- 6 [constraint=true];
6 -- 7 [style=invis, constraint=true];
7 -- 8 [style=invis, constraint=true];
8 -- 9 [style=invis, constraint=true];
9 -- 10 [style=invis, constraint=true];
}

Related

Random position of nodes in hierarchical tree with alternate paths

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

Generate a Random Flow Network

I am trying to create a flow network for a given graph so that it can be used to test an algorithm. To provide clarity, I want the flow into each vertex to equal the flow out. All flow comes from the source and goes to the sink. Each edge has a maximum capacity and a direction. I would like to generate a flow through this network that equals the maximum flow (found by the min cut) that never exceeds the capacity for each edge.
Below is a graphical example of what I am given and what I am trying to obtain. Of course the "Desired Flow Graph" is not a unique example. I want this generated randomly.
Given Weighted Graph
Desired Flow Graph
I have this graph represented in MatLab with three arrays. The first array s gives the "from" vertex, the second array t gives the "to" vertex, and the third array w1 gives the maximum capacity from s to t. I would like to generate a random array such as w2 that represents the flow. (Note the letters in the pictures are equivalent to their corresponding numbers in the code where "A" = 1.
s = [1 1 1 2 3 3 4 6 5 6];
t = [2 3 4 5 5 6 6 5 7 7];
w1 = [10 15 10 8 5 7 6 5 18 15];
w2 = [8 12 6 8 5 7 6 0 13 13];
Any help with some sort of algorithm that can perform this task would be greatly appreciated. I would love a link to an algorithm, pseudocode, direct code, or even just a description of how such an algorithm may be implemented. Thanks in advance for the help.
Check out the maxflow function in MATLAB:
http://www.mathworks.com/help/matlab/ref/graph.maxflow.html
For the graph you posted, you can construct a directed graph with these commands:
s = [1 1 1 2 3 3 4 6 5 6];
t = [2 3 4 5 5 6 6 5 7 7];
w1 = [10 15 10 8 5 7 6 5 18 15];
g = digraph(s,t,w1);
Then you can use maxflow to calculate the flow values between node 1 and node 7 and return them in a new directed graph gf:
[mf,gf] = maxflow(g,1,7);
The w2 vector you refer to now just includes the edge weights of the gf graph, so you can extract it like this:
w2 = gf.Edges.Weight

Does 8 puzzle solvability rules work for any goal state?

Ive learned that the solvability of a 8 puzzle can be checked via following certain rules.
https://www.cs.bham.ac.uk/~mdr/teaching/modules04/java2/TilesSolvability.html
http://ldc.usb.ve/~gpalma/ci2693sd08/puzzleFactible.txt.
My question is whether this solvability check applies only when the goal state (solution) is in correct ascending order?
Example:
Start state
3 1 5
6 0 4
2 7 8
Goal state1 Goal State2
3 1 5 1 2 3
6 4 8 4 5 6
2 0 7 7 8 0
Now my obeservation is that, the solvability check would work if the goal state is Goal State2 in the example. But it would not work if the goal state is Goal state1.
The inversion count can be odd or even, and in short we can call a state even or odd. This is called a state's parity. If the start state is even, then it is solvable. In the referenced articles this does indeed mean that the target must be the one with the incremental order.
But since there are in fact two classes of states (based on parity) and you can only stay within one of those two classes by making legal moves -- i.e. the parity is invariable when you make legal moves -- this principle can be extended to any target state:
If the parity of the starting state is the same as the parity of the target state, then it is reachable (solvable).
In the example states you give, the starting state is odd, and also the first target state is odd. So they belong to the same class, and the one can be reached from the other.
Here is a simple implementation of the parity check in JavaScript. It works for even sized grids as well:
function parity(grid) {
var inversions = 0;
// take copy and remove blank (0) from it.
var arr = grid.slice(0);
arr.splice(arr.indexOf(0), 1);
// perform sort and count swaps
for (var i = 1; i < arr.length; i++) {
for (var j = i - 1; j >= 0; j--) {
if (arr[j] <= arr[j+1]) break;
[arr[j+1], arr[j]] = [arr[j], arr[j+1]];
inversions++;
};
}
if (grid.length % 2 == 0) { // even grid width
var size = Math.round(Math.sqrt(grid.length));
var blankRow = Math.floor((grid.length - 1 - grid.indexOf(0)) / size);
inversions += blankRow;
}
return inversions & 1; // only odd/even is needed as info
}
document.querySelector('button').onclick = function() {
var res = '';
var txt = document.querySelector('textarea');
var grid = txt.value.trim().split(/[,\s]+/g).map(Number);
var size = Math.round(Math.sqrt(grid.length));
var res = size*size !== grid.length
? 'input is not a complete square matrix of data'
: 'parity = ' + parity(grid);
document.querySelector('pre').textContent = res;
}
Enter grid. 0 represents empty slot.<br>
<textarea rows=4>3 1 5
6 0 4
2 7 8
</textarea><button>Verify</button><br>
<pre></pre>
Yes, it does work. There's a pretty trivial way of showing this. Just map the values in the solution to the values of let's say your GoalState2, for which the check works:
state we want to reach Goal State2
3 1 5 1 2 3
6 4 8 4 5 6
2 0 7 7 8 0
map:
3 -> 1
1 -> 2
3 -> 5
...
Now apply this table to your start-state, by replacing each value with the one it's mapped to, solve the entire problem in the way you used to for GoalState2, and reverse the mapping for the final-state. And there you are with your desired result, if it exists. And the solvability-rule can be reused without changing a bit of it, just by using that simple remapping.
An illustration of how this works:
state we want to reach Goal State2
3 1 5 1 2 3
6 4 8 4 5 6
2 0 7 7 8 0
build map
map:
3 -> 1
1 -> 2
3 -> 5
...
Start state
3 1 5 apply map 1 2 3 solve for 1 2 3 apply 3 1 5
6 0 4 --------> 4 8 5 --------> 4 5 6 ---------> 6 4 8
2 7 8 7 0 6 GoalS2 7 8 0 reverse map 2 0 7
That's the most trivial way of solving it. Just consider the numbers as labels without any meaning and you're already halve way done.
For a more complex answer that gives you a better understanding of the rule itself, take a look at #trincots answer.

How to enforce sub graphs to be on the same horizontal line in Graphviz

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

How to set the 'spring' force with graphviz for compact graph layouts

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;

Resources