Graphviz - aligning nodes and clusters
Asked Answered
D

1

6

I'm trying to draw a finite state diagram with Graphviz but I cannot get it like I want it. Here's what I have written so far :

digraph G {
    rankdir = LR;

    subgraph cluster_op1 {

        subgraph cluster_0 {
            1 -> 2 [label="a"]  
        }

        subgraph cluster_1 {
            3 -> {4 6} [label="ε"]
            4 -> 5 [label="b"]
            5 -> 4 [label="ε"]
            5 -> 6 [label="ε"]
        }

        subgraph cluster_2 {
            7 -> {8 10} [label="ε"]
            8 -> 9 [label="c"]
            9 -> 8 [label="ε"]
            9 -> 10 [label="ε"]
        }   

        2 -> 3 [label="ε"]
        6 -> 7 [label="ε"]
    }

    subgraph cluster_op2 {

        subgraph cluster_3 {
            11 -> {12 14} [label="ε"]
            12 -> 13 [label="ab"]
            13 -> 12 [label="ε"]
            13 -> 14 [label="ε"]
        }   

        subgraph cluster_4 {
            15 -> 16 [label="c"]    
        }

        14->15 [label="ε"]
    }

    0 -> {1 11} [label="ε"]
    {10 16} -> 17 [label="ε"]
}

Here's what it looks like : enter image description here

What I want is :

  1. All the nodes within cluster_op1 to be aligned horizontally (same for cluster_op2)
  2. cluster_op2 to be centered below cluster_op1
  3. The edges from node 0 to cluster_op1 and cluster_op2 to be the same length (same for the edges from those two clusters to node 17)
Defect answered 18/3, 2018 at 13:53 Comment(2)
Thanks for useful code and clear questions!Lakesha
By the way, your requirement 2. and 3. are contradictoryLakesha
L
7

This is a hack more than a real solution but it gives you what you want, at least for the case presented here.

It uses three elements:

group to facilitate straight lines between nodes,

weight to help if group gets confused by one node pointing to two other nodes, all of which being in the same group; and to bring the clusters in line between them,

invis edge to align cluster_op2 below cluster_op1 - so it's not centered but manually adjusted.

In addition, I have replaced b -> a with a -> b[ dir = back ] where applicable; this I regard just as good practice to avoid bugs that are difficult to discover.

So this is your edited code:

digraph G {
    rankdir = LR;
    0, 1, 2, 15, 16, 17
    3, 4, 5, 6     [ group = 1 ];
    7, 8, 9, 10    [ group = 2 ];
    11, 12, 13, 14 [ group = 3 ];
    2 -> 11[ style = invis ];

    subgraph cluster_op1 {

        subgraph cluster_0 {
            1 -> 2 [ label="a" ]; 
        }

        subgraph cluster_1 {
            3 -> 4 [ label="ε", weight = 4 ];
            3 -> 6 [ label="ε" ];
            4 -> 5 [ label="b" ];
            4 -> 5 [ label="ε", dir = back];
            5 -> 6 [ label="ε", weight = 4 ];
        }

        subgraph cluster_2 {
            7 -> {8 10} [label="ε"]
            8 -> 9 [label="c"]
            8 -> 9 [ label="ε", dir = back ];
            9 -> 10 [label="ε"]
        }   

        2 -> 3 [ label="ε", weight = 10 ;]
        6 -> 7 [ label="ε" ];
    }

    subgraph cluster_op2 {

        subgraph cluster_3 {
            11 -> 12 [ label="ε", weight = 4 ];
            11 -> 14 [ label="ε" ];
            12 -> 13 [ label="ab" ];
            12 -> 13 [ label="ε", dir = back ];
            13 -> 14 [ label="ε", weight = 4 ];
        }   

        subgraph cluster_4 {
            15 -> 16 [label="c"]    
        }

        14->15 [ label="ε", weight = 10 ];
    }

    0 -> {1 11} [label="ε"]
    {10 16} -> 17 [label="ε"]
}

which yields

enter image description here

Lakesha answered 19/3, 2018 at 5:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.