Rendering produces varying and frequently wrong results

Hello Graphviz team,

experimenting with a diagram definition containing 3 subgraphs of type “cluster”, I found that the result of rendering it varies almost with every invocation and often doesn’t include one of the subgraphs.

The definition is

digraph R {
	node [shape=record style=rounded]
	layout=dot;
	splines=true;
	
	subgraph cluster_flow1 {
		label="first flow" style="filled" color="lightgreen"
		0
	} 
	
	subgraph cluster_flow2 {
		label="second flow" style="filled" color="azure"
		1
		2
		t[shape=ellipse label="'First task'"];
		0->1
		1->t
		1->2:n
	}

	subgraph cluster_flow3 {
		label="third flow" style="filled" color="azure"
		5
		6
		0->5
		5->6:n
		6->6
	}
}

The command that I use to produce an image (I tried PNG and SVG) is:

dot -Tpng -O erratic-layout.gv

The results vary almost call by call.

The subgraph with ID “cluster_flow1” is shown correctly at times:
erratic-layout.gv-a

But often it is missing, and the node “0” (which is declared in that subgraph) appears in subgraph “cluster_flow2” instead.
In addition, the horizontal positions of “cluster_flow2” and “cluster_flow3” are exchanged at times.

I’m using version 2.47.1 (20210417.1919) on Windows 10 (64 bit) at the command-line.

Do I have a mistake in my definition file or did I stumble over a known (or unknown) bug?

Regards,
Tillmann

Curious, on my Linux system, two versions of dot consistently give the “correct” answer

  • dot - graphviz version 2.47.2~dev.20210515.1947 (20210515.1947)
  • dot - graphviz version 2.43.0 (0)
1 Like

I tried the same code on http://webgraphviz.com, this also produced the correct result consistently.

I can reproduce it in the latest wasm version (GraphViz 2.47.1) - you can see it here:
Possible Issue / Gordon Smith / Observable (observablehq.com)

(Click the “play” button in the top right hand corner of the DOT text)

1 Like

The “workaround” is to move the 0 → 1 and 0 → 5 edges out of the subgraphs…

1 Like

Hello schmoo2k,
do you think the problem hinges on the specific value 0 of the edge sources or
is it generally a good idea to make edge definitions outside the subgraph blocks?

I have always put my edges at what I would consider a logical scope (IOW 0->1 doesn’t belong inside the second subgraph because “0” is not in that subgraph).
I am not saying this is correct behaviour, just its the way I felt was “correct” and it stood out when I looked at it, which is how I stumbled onto the workaround…

1 Like

No simply changing “0” to “10” in your example has the same issue.

The original graph description exposes a known problem in dot. As the documentation notes:

If an edge belongs to a cluster, its endpoints belong to that cluster. Thus, where you put an edge can effect a layout, as clusters are sometimes laid out recursively.

Unfortunately, dot does not allow a node to be in multiple clusters, which can cause problems, such as a cluster disappearing, depending on which cluster dot chooses to place the node in. The dot program warns about this in some cases but it doesn’t check that every node only occurs in a single cluster. Barring adding such a check, the above note should probably be made stronger.

In any case, the suggested workaround is the correct fix: The two edges should be moved out of the clusters.

4 Likes

Thank you erg and schmoo2k,

unfortunately, I cannot mark two answers as solution. I chose schmoo2k’s as his was the first to put me on the right track, though yours, erg, definitely adds to my understanding - please share the credits!

Sounds like we should implement a checker that creates warnings in these cases. I don’t want to think how many people gave up on Graphviz because they didn’t ask here.