Aligning Subgraphs, Ordering Nodes, and Relocating Edges in Graphviz

dotgraphviz

I'm trying to draw a GraphViz graph (using version 2.38.0 (20140413.2041)), and having a lot of trouble getting it to lay out the way I want it. I've tried many different combinations of hidden edges, constraint manipulation, subgraphs (both cluster and non-cluster), etc., and nothing seems to be doing what I want.

Here's my current code:

digraph G {
  subgraph clustera {
    style=invis;rank=same
    A->B->C
  }

  subgraph clusterb {
    style=invis;rank=same;rankdir=LR
    D->E [constraint=false]
  }

  subgraph clusterc {
    style=invis;rank=same
    F->G [constraint=false]
  }

  C -> D
  D -> F  [constraint=false]
  E -> C

  F -> A  [constraint=false]
  F -> C  [constraint=false]
  F -> E  [constraint=false]
}

And here's how it renders with dot -Tpng:

current dot graph

(All the F edges have "constraint" turned off, because almost anything else distorts the graph horribly.)

What I want is:

  • node F above node G
  • F and G more or less centered vertically on the graph
  • F and G to the right of A through E
  • A through E in more or less the arrangement they're in now
  • the edges from F to A, C, and E, and from D to F, following more or less straight lines (i.e. not routing around the right-hand side of the F/G group)
  • as a bonus, I'd kind of like to get A through C to center properly above D and E, but that's less important

(One thing I very much don't want is for F to appear above A, as if it were the root of the graph.)

Here's an approximation of what I'm looking for, laid out by hand in yEd:

yEd graph

Is this doable in GraphViz?

(I should note that I'm perfectly willing to use one of the other GraphViz tools, it's just that dot is the only one I'm at all familiar with.)

Best Answer

Here's my approach without subgraphs and weigths, only groups to vertically align nodes, and constraint=false as well as dir=back to preserve layout distortion.

digraph G {
  // nodes without a group
  D;
  E;

  // group left side
  node[group=left];
  A -> B -> C -> D;
  C -> E [dir=back];
  D -> E [constraint=false];

  // group right side
  node[group=right];
  F -> G;

  // inter group edges
  F -> C;
  edge [constraint=false];
  D -> F;
  F -> A;
  F -> E;
}

The result can be seen here and corresponds to your approximation.

Related Topic