Search code examples
graphgraphvizstate-machinedotfinite-state-automaton

Aligning nodes in dot with group does not give the desired result


I tried to create graph from here Improving graphviz layout and want to get the exact picture
1
like in post, but can't vertically align nodes and get nice curve in q3->q3. My question is about how fix this:
2

digraph {
    layout=dot
    rankdir = LR
    
    node [shape=circle]
    
    Start [shape=plaintext group=g1]
    q0 [shape = doublecircle label=<<I>q</I><SUB>0</SUB>> group=g1]
    q1 [label=<<I>q</I><SUB>1</SUB>> group=g1]
    q2 [label=<<I>q</I><SUB>2</SUB>> group=g2]
    q3 [label=<<I>q</I><SUB>3</SUB>> group=g2]
    
    Start -> q0
    q0 -> q1 [label="1"]
    q1 -> q0 [label="0"]
    q1 -> q3 [label="0"]
    q3:s -> q3:e [label="0,1"]
    q0 -> q2 [label="1"]
    q2 -> q0 [label="0"]
    q2 -> q3 [label="1"]
    
    {rank = same; q2;q0;}
    {rank = same; q1;q3;}
}

Online editor

P.S. I came up with another variant, it's better than the first one, but not yet what I visually expected:

digraph {
    layout=dot
    ranksep=0.2;
    
    node [shape=circle]
    
    Start [shape=plaintext group=g1]
    q0 [shape = doublecircle label=<<I>q</I><SUB>0</SUB>> group=g1]
    q1 [label=<<I>q</I><SUB>1</SUB>> group=g1]
    q2 [label=<<I>q</I><SUB>2</SUB>> group=g2]
    q3 [label=<<I>q</I><SUB>3</SUB>> group=g2]
    
    Start -> q0
    q0:ne -> q1:nw [label="1"]
    q1:sw -> q0:se [label="0"]
    q1 -> q3 [label="0"]
    q3:se -> q3:e [label="0,1";]
    q0 -> q2 [label="1"]
    q2 -> q0 [label="0"]
    q2 -> q3 [label="1"; constraint=false]
    
    {rank=same; Start; q0; q1}
    {rank=same; q2; q3}
    
    //hack starting
    //invisnode [shape=point, width=0]
    edge [style=invis]
    q0 -> q2
    //q0 -> invisnode -> q1
}

Result:
4


Solution

  • Image: finite-state machine graph made by graphviz
    Script:

    digraph {
        ranksep=1;
        nodesep=0.5;
    
        node [shape=circle]
    
        Start [margin=0 width=0 shape=plaintext]
        q0 [shape = doublecircle label=<<I>q</I><SUB>0</SUB>>]
        q1 [label=<<I>q</I><SUB>1</SUB>>]
        q2 [label=<<I>q</I><SUB>2</SUB>>]
        q3 [label=<<I>q</I><SUB>3</SUB>>]
    
        Start -> q0
        q1 -> q0 [xlabel="1"]
        q0 -> q1 [xlabel="0"]
        q1 -> q3 [label=" 0"]
        q3:se -> q3:e [label=" 0,1"]
        q2 -> q0 [xlabel="0 "]
        q0 -> q2 [xlabel="1 "]
        q2 -> q3 [label="1"]
    
        {rank=same; Start; q0; q1}
        {rank=same; q2; q3}
    }
    

    Answer's sources: how group attribute works, solution

    P.S. I think I can get a nice curve q3->q3 using the neato engine with pos node attribute for positioning nodes and pos edge attribute for spline control points. Solution still in work.