Using GraphViz to Diagram an Extensive-Form Game - graphviz

I'm attempting to diagram an extensive form game in GraphViz. Compiling the code results in a graph that is correct in all ways except one. I want the "War" label to be placed to the left of the edge it labels, such that the edge is closest to "r" and not "W".
This is my "game" or graph so far:
digraph hierarchy_of_D {
graph [rankdir ="UD"]
node [color=black,shape=circle]
//splines="polyline"
I [label="R"]
subgraph infoset1
{
label="whatever"
rank="same"
1 [label="C"]
2 [label="C"]
}
I -> 1 [label="War"] //fix how this floats right of the line
I -> 2 [label="Peace"]
1 -> 2 [style=dashed, dir=none]
subgraph info21
{
rank="same"
3 [label="(2,2)", rank=sink, shape="plaintext"]
4 [label="(5,1)", rank=sink, shape="plaintext"]
5 [label="(1,5)", rank=sink, shape="plaintext"]
6 [label="(4,4)", rank=sink, shape="plaintext"]
}
1 -> 3 [label="War"]
1 -> 4 [label="Peace"]
2 -> 5 [label="War"]
2 -> 6 [label="Peace"]
}
Any ideas? I've already tried the following, which does not do what I want:
1 -> 3 [label="War/l"]
See also this question and that question, neither of which have an answer. C'mon now, this is worth triple points!

Triple points? Well then, the correct answer is that you cannot choose the placement of edge labels.
However, you may play with headlabel, labeldirection and labelangle:
digraph hierarchy_of_D {
node [color=black,shape=circle]
I [label="R"]
subgraph infoset1
{
label="whatever"
rank="same"
1 [label="C"]
2 [label="C"]
}
I -> 1 [headlabel="War", labeldistance=3, labelangle=40]
I -> 2 [headlabel="Peace", labeldistance=3, labelangle=-40]
1 -> 2 [style=dashed, dir=none]
subgraph info21
{
rank="same"
3 [label="(2,2)", rank=sink, shape="plaintext"]
4 [label="(5,1)", rank=sink, shape="plaintext"]
5 [label="(1,5)", rank=sink, shape="plaintext"]
6 [label="(4,4)", rank=sink, shape="plaintext"]
}
1 -> 3 [headlabel="War", labeldistance=3, labelangle=40]
1 -> 4 [headlabel="Peace", labeldistance=3, labelangle=-40]
2 -> 5 [headlabel="War", labeldistance=3, labelangle=40]
2 -> 6 [headlabel="Peace", labeldistance=3, labelangle=-40]
}
Output:

Just for fun, an other workaround I just found:
By forcing straight edges between nodes using splines=false and defining edges twice, the edges are drawn as if they were one single edge, but the labels of each edge get to are drawn (most of the time) on different sides of the edge.
Therefore by having one edge without a label, and the other one with a label, it is possible to influence the placement of the edge(s) label(s).
Your example:
digraph hierarchy_of_D {
splines=false;
node [color=black,shape=circle]
I [label="R"]
subgraph infoset1
{
rank="same"
1 [label="C"]
2 [label="C"]
}
I -> 1 [label="War "]
I -> 1 [label=" "]
I -> 2 [label=""]
I -> 2 [label="Peace"]
1 -> 2 [style=dashed, dir=none]
subgraph info21
{
rank="same"
3 [label="(2,2)", rank=sink, shape="plaintext"]
4 [label="(5,1)", rank=sink, shape="plaintext"]
5 [label="(1,5)", rank=sink, shape="plaintext"]
6 [label="(4,4)", rank=sink, shape="plaintext"]
}
1 -> 3 [label="War"]
1 -> 3 [label=""]
1 -> 4 [label=""]
1 -> 4 [label="Peace"]
2 -> 5 [label=""]
2 -> 5 [label="War "]
2 -> 6 [label=""]
2 -> 6 [label="Peace"]}
And the output:
It's not perfect, and your mileage may vary depending on the graph, but I thought it was worth mentioning it.

Related

graphviz basic ruler: number positioning

I just want to create a basic ruler with numbers next to the dashes
Am I using dot wrong or what is the matter?
What would be a better approach?
rendered
digraph timeline {
node [fixedsize=true height=.01 label="" shape=box width=.1 xlp="100,0"]
edge [arrowhead=none arrowtail=none]
1 -> 2 [xlabel=1]
2 -> 3 [xlabel=2]
3 -> 4 [xlabel=3]
4 -> 5 [xlabel=4]
5 -> 6 [xlabel=5]
6 -> 7 [xlabel=6]
7 -> 8 [xlabel=7]
8 -> 9 [xlabel=8]
9 -> 10 [xlabel=9]
}
dot is not well suited for this - I'd try gpic. But is this close enough?
digraph timeline {
size="2,12!"
ratio=fill
node [fixedsize=true height=.01 label="" shape=box width=.1 xlp="100,0"]
edge [arrowhead=none arrowtail=none]
0 [label=""]
1 [label="1"]
2 [label="2 "]
3 [label="3 "]
4 [label="4 "]
5 [label="5 "]
6 [label="6 "]
7 [label="7 "]
8 [label="8 "]
9 [label="9 "]
0->1->2->3->4->5->6->7->8->9
}

Edge direction in digraph depends on presence of label? Likely a bug?

I noticed something very strange with a small graph. It only seems to exist in one certain configuration (that I can find) of said graph. Namely: the direction of one of the edges flips depending on the presence of a label. If the label is present, the edge goes the wrong way, if it is absent, the edge points the right way.
Here are the two versions of the graph:
As you can see, the arrowhead on the edge titled foobar reverses direction as soon as the label is present. The definition says 4 -> 3, so, as I understand it, the head should be at 3, the tail originating from 4. But the opposite is the case as soon as I add a label. Nothing but the label=foobar attribute was changed in the code.
I must apologize for the size of the graph. I would normally try to find a minimal example, but in this case, changing even the slightest thing about the layout of the nodes changes the outcome, and the edge is displayed correctly regardless of the presence of a label.
The code is here:
digraph G {
2;
3;
6;
red;
11;
4;
8;
brown;
1;
ne2;
12;
two;
one;
yellow;
e2;
10;
5;
green;
four;
three;
7;
9;
1 -> 2 [style=bold];
1 -> 4 [style=bold];
1 -> 5 [style=bold];
1 -> 3 [style=bold];
2 -> ne2 [style=bold];
2 -> e2 [style=bold];
4 -> 6 [style=bold];
4 -> 7 [style=bold];
6 -> 10 [style=bold];
6 -> 9 [style=bold];
6 -> 8 [style=bold];
7 -> 11 [style=bold];
7 -> 12 [style=bold];
5 -> one [style=bold];
5 -> two [style=bold];
5 -> three [style=bold];
5 -> four [style=bold];
3 -> green [style=bold];
3 -> red [style=bold];
3 -> yellow [style=bold];
3 -> brown [style=bold];
4 -> 3 [constraint=false
,style=dotted
,label=foobar
,arrowhead=odot];
ne2 -> 4 [constraint=false
,label=head
,style=dotted
,arrowhead=odot];
7 -> four [constraint=false
,label=baz
,style=dotted
,arrowhead=odot];
6 -> two [constraint=false
,label=baz
,style=dotted
,arrowhead=odot];
4 -> 5 [constraint=false
,label=baz
,style=dotted
,arrowhead=odot];
ne2 -> 2 [constraint=false
,label=tail
,style=dotted
,arrowhead=odot];
}
My current graphviz version is:
dot - graphviz version 2.26.3 (20100126.1600)
Did I misunderstand something fundamental about the way these graphs are constructed from dot files? It seems unreasonable to me that the arrow head position should be influenced by the presence of a label.
This is indeed a bug. It was fixed in version 2.28, so upgrading should be sufficient.

How to print a description string near a node?

I have recently started to use the DOT language to describe the structure of a binary tree. The following example allows to draw a binary tree having numbers as labels inside each node.
graph tree {
0 [shape=ellipse]
1 [shape=ellipse]
2 [shape=ellipse]
3 [shape=ellipse]
4 [shape=ellipse]
0 -- 1
0 -- 2
2 -- 3
2 -- 4
}
Now, I would like to print some additional information near each node, but not inside the ellipse containing the label of the node. In other words, how can I print a description string near a node? How should I modify the above code in order to achieve this?
this script, with the added lines,
graph tree {
0 [shape=ellipse]
1 [shape=ellipse]
2 [shape=ellipse]
3 [shape=ellipse]
4 [shape=ellipse]
0 -- 1
0 -- 2
2 -- 3
2 -- 4
node [shape=none]
edge [style="invis"]
rank="same"
subgraph { 0 -- "desc of 0" }
subgraph { 1 -- "desc of 1" }
subgraph { 2 -- "desc of 2" }
subgraph { 3 -- "desc of 3" }
subgraph { 4 -- "desc of 4" }
}
generates a plausible image for your description

GraphViz enforce columns

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.

Finding the root value of a binary tree?

I have an array which stores the relations of values, which makes several trees something like:
So, in this case, my array would be (root, linked to)
(8,3)
(8,10)
(3,1)
(3,6)
(6,4)
(6,7)
(10,14)
(14,13)
And i'd like to set all the root values in the array to the main root in the tree (in all trees):
(8,3)
(8,1)
(8,6)
(8,4)
(8,7)
(8,10)
(8,14)
(8,13)
What algorithm should i investigate?
1) Make a list of all the unique first elements of the tuples.
2) Remove any that also appear as the second element of a tuple.
3) You'll be left with the root (8 here). Replace the first elements of all tuples with this value.
EDIT:
A more complicated approach that will work with multiple trees would be as follows.
First, convert to a parent lookup table:
1 -> 3
3 -> 8
4 -> 6
6 -> 3
7 -> 6
10 -> 8
13 -> 14
14 -> 10
Next, run "find parent with path compression" on each element:
1)
1 -> 3 -> 8
gives
1 -> 8
3 -> 8
4 -> 6
...
3)
3 -> 8
4)
4 -> 6 -> 3 -> 8
gives
1 -> 8
3 -> 8
4 -> 8
6 -> 8
7 -> 6
...
6)
6 -> 8 (already done)
7)
7 -> 6 -> 8
etc.
Result:
1 -> 8
3 -> 8
4 -> 8
6 -> 8
7 -> 8
...
Then convert this back to the tuple list:
(8,1)(8,3)(8,4)...
The find parent with path compression algorithm is as find_set would be for disjoint set forests, e.g.
int find_set(int x) const
{
Element& element = get_element(x);
int& parent = element.m_parent;
if(parent != x)
{
parent = find_set(parent);
}
return parent;
}
The key point is that path compression helps you avoid a lot of work. In the above, for example, when you do the lookup for 4, you store 6 -> 8, which makes later lookups referencing 6 faster.
So assume you have a list of tuples representing the points:
def find_root(ls):
child, parent, root = [], [], []
for node in ls:
parent.append(node[0])
child.append(node[1])
for dis in parent:
if (!child.count(dis)):
root.append(dis)
if len(root) > 1 : return -1 # failure, the tree is not formed well
for nodeIndex in xrange(len(ls)):
ls[nodeIndex] = (root[0], ls[nodeIndex][1])
return ls

Resources