45

I want to render several trees simultaneously and place all root nodes and all leaf nodes on the same level.

Here's an example of what I'm trying to do. Root nodes A and X are on the same level, and so are leaf nodes B, D, and Z.

Graph I want

I unsuccessfully tried putting roots in one rank and leaves in another as follows:

digraph G { 
rankdir = TB;
subgraph {
A -> B
A -> C
C -> D
X -> Y
rank = same; A; X;
rank = same; B; D; Y;
} /* closing subgraph */
}

And got this outcome where everything is on the same rank. enter image description here

Any suggestions about what I should be trying? I've already got roots and leaves identified.

Thalecress
  • 2,801
  • 9
  • 30
  • 43

3 Answers3

68

Putting the rank = same; ... statements in braces, e.g.:

digraph G { 
  rankdir = TB;
  subgraph {
    A -> B
    A -> C
    C -> D
    X -> Y
    // note that rank is used in the subgraph
    {rank = same; A; X;}
    {rank = same; B; D; Y;}
  } /* closing subgraph */
}

... gives the desired result:

enter image description here

TmTron
  • 10,318
  • 3
  • 52
  • 97
Simon
  • 9,962
  • 1
  • 26
  • 43
  • 1
    This is great! I thought that rank was always specified as an attribute of a subgraph, not as a statement unto itself. – Jeremy Jun 21 '17 at 19:49
  • 3
    Is the subgraph really necessary? I'm satisfied with this result: digraph { rankdir=LR; 1902387216 [label="h"]; 1902387216 -> 1736863396 [label="child"]; 1736863396 [label="e"]; 1736863396 -> 166482735 [label="peer"]; {rank = same; 1736863396; 166482735;}; 166482735 [label="a"]; 166482735 -> 915735320 [label="child"]; 915735320 [label="n"]; 915735320 -> 1424861798 [label="child"]; 1424861798 [label="d"]; 1736863396 -> 233979847 [label="child"]; 233979847 [label="r"]; } – William John Holden Jan 28 '18 at 05:07
  • 1
    @WilliamJohnHolden: I agree with you that the subgraph isn't really necessary. In the original question it was probably a part of the overall graph, the rest of which was omitted to create a minimal example. – Simon Jan 29 '18 at 23:28
7

Here's a simple example inspired by @William John Holden's comment -

graph {
  rankdir=LR;
  a -- b -- c;
  d -- e -- f;
  b -- d; {rank = same; b; d;};
}

graph

Brian Burns
  • 14,953
  • 5
  • 69
  • 59
7

The ideal structure is actually rank max and rank min. No need for a subgraph or any other shenanigans. GraphViz has explicit facilities for this.

With complex graphs, rank=same will often end up near the middle of the graph. If you mean top and bottom, say top and bottom.

digraph G { 

  rankdir = TB;

  A -> B;
  A -> C -> D;
  X -> Y;

  { rank=min; A; X; }
  { rank=max; B; D; Y; }

}

enter image description here

John Haugeland
  • 7,589
  • 3
  • 35
  • 37