Search code examples
graphvizdirected-acyclic-graphs

Graphviz: forbid horizontal edges, always show vertical orientation


I have a directed acyclic graph that I am trying to visualize using Graphviz's dot. By default it's laid out top-to-bottom.

Usually, all directed edges have their head lower than their tail. But in certain cases they're drawn as a horizontal straight line section, i.e. head and tail are at the same level. In my case this happened after I defined subgraph clusters.

Is their a way to forbid this and force it to always position nodes so that the arrows are pointing "downwards"?

Sample source:

digraph {
  rankdir=TB;
  subgraph cluster_1 { "8"; "7"; "9"; "11"; "10" }
  subgraph cluster_2 { "3"; "4"; "5"; }

  "1" -> "3";
  "2" -> "5";
  "3" -> "6";
  "3" -> "5";
  "2" -> "8";
  "2" -> "4";
  "2" -> "3";
  "2" -> "6";
  "2" -> "7";
  "1" -> "8";
  "7" -> "8";
  "4" -> "6";
  "6" -> "10";
  "3" -> "11";
  "7" -> "10";
  "7" -> "6";
  "1" -> "2";
  "6" -> "5";
  "7" -> "9";
  "7" -> "5";
  "4" -> "5";
  "6" -> "8";
  "3" -> "4";
  "10" -> "11";
  "4" -> "11";
  "3" -> "8";
  "8" -> "9";
  "6" -> "9";
  "9" -> "10";
  "3" -> "10";
  "3" -> "7";
}

Solution

  • I know this is an old question, but I will provide this answer for future reference:

    You could use newrank = true; which does the following according to the graphviz.org website:

    The original ranking algorithm in dot is recursive on clusters. This can produce fewer ranks and a more compact layout, but sometimes at the cost of a head node being place on a higher rank than the tail node. It also assumes that a node is not constrained in separate, incompatible subgraphs. For example, a node cannot be in a cluster and also be constrained by rank=same with a node not in the cluster.

    If newrank=true, the ranking algorithm does a single global ranking, ignoring clusters. This allows nodes to be subject to multiple constraints. Rank constraints will usually take precedence over edge constraints.

    So your source only changes as follows:

      digraph {
          rankdir=TB;
          newrank = true;
          ...
    

    And the result will be much nicer for this example:

    enter image description here