Positioning Nodes With `{rank=same ...}` Side Effects - graphviz

I have a graph defined as such:
digraph G {
rankdir=LR
node[shape=circle]
q_[shape=none label=""]
q3[shape=doublecircle]
q4[shape=doublecircle]
q_->q0
q0->q1[label="λ"]
q0->q2->q4[label=a]
q1->q4->q2[label=b]
q1->q3[label=a]
q3->q4[label="λ"]
{rank=same; q4 q3}
{rank=same; q1 q2}
}
The graph outputs the following image:
You can play with the graph here: http://graph.gafol.net/derive/effpjWfSD
My question is:
Why is q4 pointing to q3 in the rendered graph and not the way I specified it in the markup? Is it because {rank=same; q4 q3} has more semantic meaning than just positioning nodes? If that is the case, how can I position the nodes so that the output is not as hideous as the output is without using {rank=same; ...}?

There is no hidden semantic meaning in rank=same, this is simply a bug.
The edge is correctly drawn when for example omitting the label of the edge or rankdir=LR.
You may correct this particular graph by adding the dir attribute to the incorrectly drawn edge:
q3->q4[label="λ", dir=back]
This is of course of no help when dynamically creating graphs.
This bug may be related to one of the other known bugs caused by rankdir=LR, reported on http://www.graphviz.org:8080/bugs/openbugs.html

Changing {rank=same; q4 q3} to {rank=same; q3 q4} may also work (not tested). Reading from top to bottom, left to right, the most recent layout instruction for those nodes (q3 and q4) changes previous lines' ordering and overrides prior arrows:
{rank=same; q4 q3}
Maybe this is not a bug.

Related

How to efficiently update restricted pieces in the game of Hive?

I am making an engine for the game of Hive (https://www.gen42.com/games/hive) in C++ and I need it to be highly efficient as I will have an AI searching through many thousands of positions. Note that it is not essential to be familiar with Hive to answer this, as this question is more related to graph theory. There is an example at the end.
Representation
In the game of Hive, pieces can be placed and moved around on an infinite hexagonal grid. There is a crucial rule, the One Hive Rule, that states: The pieces in play must be linked at all times (i.e., the Hive may never be broken)
In other words, the hive can be represented as a connected undirected planar graph, where:
The vertices are the pieces
The edges are the connections between adjacent pieces
The articulation points of this graph represent pieces restricted by the One Hive Rule. Also, no vertex can have more than six edges. (pieces on top of the hive are not included in the graph)
Problem
The problem I have is recalculating these articulation points efficiently after the graph is changed and I am wondering if there is some efficient data structure that could handle this.
Specifically, the data structure would need to accommodate the following updates:
Add a vertex to the graph along with its connecting edges (i.e., placing a piece/moving a piece to its new location)
Remove a vertex from the graph along with its connected edges (i.e., removing a piece when it is being moved to a new location)
When queried, the data structure would return which vertices are articulation points.
Also note that the graph begins empty, and the number of vertices can never decrease. (pieces cannot be removed from the hive)
Ideas
I am aware of algorithms like Tarjan’s which calculate the articulation points of a graph in a single DFS traversal. However, most of the time in Hive when a piece is moved, only a few pieces become restricted/unrestricted by this rule (usally no more than 2), and therefore only a few vertices in the graph should have to be updated. (rather than re-traversing the entire graph every time)
Can anyone provide me with an efficient data structure and/or algorithm for this?
Example
(You don’t need to know how the pieces move)
In the current position, the white ant (blue) is about to move to the location south-east of the black bee (yellow). In the graph, I have shown in dark blue the updates that would be required.
The vertices in the graph circled in red are articulation points (immobile pieces). Also note that after the ant has moved to its new location, the vertex corresponding to the black bee will also become an articulation point.
Example Image
A block-cut tree may be useful in solving the problem, but more to the point of this answer, it may help you understand that there is no easy solution to the problem.
Consider the graph shown below (source:wikipedia with modifications in color)):
The graph with 18 vertices (black) is shown on the left. The corresponding block-cut tree is shown to the right. Notice that the cut points (aka articulation points) are considered to be part of the blocks that they connect. So for example, cut point 1 (C1) in the tree, which is vertex 2 (V2) in the graph is a member of blocks B1, B2, and B3.
I propose to add vertex 19 (magenta), and then consider the consequences. I've circled the cut points in the graph. Those circled in red (V2, V8, and V10) remain as cut points when V19 is added. But V7 (aka C2) ceases to be a cut point when V19 is added. That's because C2 in the block-cut tree is part of a cycle that is created by adding V19. And unlike C1, C3, and C4, it doesn't connect to any blocks that aren't part of the cycle. It only connects B3 and B4, which are both part of the cycle.
So after adding V19, there are only 4 blocks and 3 cut points. B2, B5, and B7 continue to exist as separate blocks, connected by C1, C3, and C4 respectively. B1, C1, B3, C2, B4, C3, C4, and B6 are now all part of a single large block. The resulting block-cut tree is shown below (source:ibid with modifications in color):
Finally getting to the point, notice that V7 is about as far away from V19 as it can possibly be. So the effects of adding a vertex aren't localized to the neighbors of the added vertex. The effects can propagate throughout the graph.
And then it gets worse.
We've seen the effects of adding a vertex. Now consider the reverse. After adding V19, the player decides to move the piece that V19 represents, thereby removing V19 from the graph. Suddenly, block B19 explodes into four blocks (B1, B3, B4, and B6), and C2 appears as a cut point. Basically restructuring the entire block-cut tree. So by the time the code finds the newly formed cut point, and rearranges the block-cut tree, it may have been possible (or even faster) to run Tarjan's again.

Is it possible to define subgraphs (clusters) in Graphviz with a specified, fixed layout

How can I create subgraphs/clusters in Graphviz, with nodes at specific positions, and then have Graphviz rotate and arrange these subgraphs according to a set of interconnecting edges (i.e. edges not within the subgraphs)?
Here's my current attempt. Problem is that I want to be able to define the internal ordering of the nodes, such that, as an example, the nodes in subgraph "3" are aligned in a row (and always ordered A-B-C):
graph {
forcelabels=true
color=lightgrey
subgraph cluster_1 {
node[shape=point]
{rank=same r1A r1B}
label="1"
r1A [xlabel="A", fontsize=7]
r1B [xlabel="B", fontsize=7]
}
subgraph cluster_2 {
node[shape=point]
{rank=same r2A r2B}
label="2"
r2A [xlabel="A", fontsize=7]
r2B [xlabel="B", fontsize=7]
}
subgraph cluster_3 {
node[shape=point]
{rank=same volA volB volC}
label="3"
volA [xlabel="A", fontsize=7]
volB [xlabel="B", fontsize=7]
volC [xlabel="C", fontsize=7]
}
}
If I add edges, I want Graphviz to be able to rotate the subgraphs, but while preserving that internal layout and ordering. Here, using engine fdp, subgraph "3" gets all rearranged (for obvious reasons, since I haven't got any way of fixing the layout):
And what about more advanced "layouts"? Is it possible/feasible to make a subgraph resembling a microcontroller, something like this:
Unfortunately, none of the Graphviz engines do node rotation. You would have to create a complete engine for node rotation (the architecture supports this) or a pre/post processor just for node rotation (more later)
Also Graphviz only seems to support text rotation at a Root graph level. This might be a killer, depending on your requirements.
If you want to use clusters (suggestion: nope), you probably need to use the dot engine to line up your nodes.
Html-records (possibly with included images) would probably be a "better" choice for the ICs. Again, none of the engines will rotate them, but ...
Cycles are cheap, so if there are not "too many" ICs, generate all possibilities (each IC rotated & not) and then eyeball evaluate or write a post-processing program to determine the "best" result.
Also note that Graphviz edge routing might not produce what you want.

Make digraph edge arrow follow node pen width

I would like to increase the border width of my nodes, but I find that the arrow heads in digraph edges do not respect the added width. Instead, they sink into the border. Here's my simple graph.
strict digraph {
a [penwidth="10.0"];
b [penwidth="10.0"];
a -> b;
}
How could I either increase the node width safely, or distance the edges further back? Reading through the attribute list, I didn't find a way. The closest was peripheries, but it makes multiple narrow peripheries instead of a thick one, but the edges do stick to the outermost periphery.
This is a known bug: https://forum.graphviz.org/t/allign-nodes-stroke-with-end-of-the-arrows-path-width/462
The only work-around I know is to "move" node b or shorten the edge - described in the bug report.

How to center a cluster in graphviz

Having a example graph like this:
digraph g{
subgraph cluster_test{
john;
mike;
}
amy->john;
jack->mike;
jack->john;
james->john;
}
How could the cluster_test subgraph be positioned so each other nodes are getting places around it.
The fdp layout uses a "spring" model and may suit your needs better than the hierarchical graphs dot produces. It's the only other layout besides dot which supports clusters.

Graphviz: Stacking fields vertically within a subraph

I am trying to stack a group of fields vertically (there are 8 specific fields, so I would preferably have 4x4) within Graphviz. I have a subgraph cluster containing 8 fields, which by default are lined up side by side horizontally, making connections extremely messy. I feel it would be much more clear if the subfields were stacked vertically.
A common technique to layout nodes is to use invisible edges.
In the following example, the nodes n1-n8 are layed out vertically within a cluster, but no edges are displayed.
digraph g{
subgraph cluster0 {
edge[style=invis];
n1->n2->n3->n4->n5->n6->n7->n8;
}
// some visible edges from nodes outside of the cluster to nodes within the cluster
a -> b;
a -> {n2;n7;n8};
b -> {n4;n6;n7;};
}

Resources