Search code examples
graphviz

Positioning same-ranked nodes in a graph


The following is my graphviz code, and the produced image:

digraph D{
    rankdir = TB
    node[ 
        shape = rect
        style = filled;
        fillcolor = "#C0C0C033"
        fontname = "Roboto"
        width = 5
    ]
    
    A[ label = "Formalize Problem Into Optimization Model" ]
    B[ label = "Is it Possbile To Find A Solving Algo ?" ]
    C[ label = "Is The Problem NP-Hard ?" ]
    D[ label = "Is It Solvable Using Approximation Algo ?" ]
    E[ label = "Is the Problem Inapproximable ?" ]
    
    Done1, Done2[ 
        label = "Done"
        width = 1
        fillcolor = "#44663355"
    ]
    
    Reform[
        label = "Reformulate The Problem"
        width = 3;
    ]
    
    // Invis nodes to simulate ortho-like edges
    invisA2, invisB1, invisC1, invisD1, invisE1[
        shape = point;
        width = 0;
    ]
    
    edge[ 
        style = default;
        fontname = "Roboto"
        weight = 100;
    ]
    
    A -> B 
    B -> C
    C -> D
    D -> E
    
    edge[
        constraint = false;
    ]
    
    // Should Be at the Left Side
    C -> invisC1
    invisC1 -> invisB1
    invisB1 -> B
    B -> Done1
    
    E -> invisE1
    invisE1 -> invisD1
    invisD1 -> D
    D -> Done2
    
    // Should be at the right side (Working Correctly)
    Reform -> invisA2
    invisA2 -> A [label = "                                         "]
    
    {rank = same; invisB1, B, Done1}
    {rank = same; invisC1, C}
    {rank = same; invisD1, D, Done2}
    {rank = same; invisE1, E, Reform}
}

Graphviz image

As you can see, the points appears to be between the Done nodes and the main (A, B, C, D, E) nodes; also for no reason they seems to be jiggly.

Since I am going to add labels to the edges, couldn't be using splines = ortho. Is there any ways to make them (To be specific, invisB1, invisC1, invisD1 and invisE1) appear at the left, also keeping all edges straight?


Solution

  • Several smallish tweaks, some just for aesthetics:

    • dir=none - aesthetics
    • dir=back and reversed edge direction - help position invis nodes on the left
    • group=X - help vertical alignment
    • turned constraints back to true
    • splines=false straight line edges
    digraph D{
        rankdir = TB
        splines=false // straight-lines
    
        node[ 
            shape = rect
            style = filled;
            fillcolor = "#C0C0C033"
            fontname = "Roboto"
            width = 5
        ]
        { node [group=E]  // force/encourage vertical alignment
        A[ label = "Formalize Problem Into Optimization Model" ]
        B[ label = "Is it Possbile To Find A Solving Algo ?" ]
        C[ label = "Is The Problem NP-Hard ?" ]
        D[ label = "Is It Solvable Using Approximation Algo ?" ]
        E[ label = "Is the Problem Inapproximable ?" ]
        }
        
        Done1, Done2[ 
            label = "Done"
            width = 1
            fillcolor = "#44663355"
        ]
        
        Reform[
            label = "Reformulate The Problem"
            width = 3;
            group= B
        ]
        
        // Invis nodes to simulate ortho-like edges
        invisB1, invisC1, invisD1, invisE1[
            shape = point;
            width = 0;
        ]
        invisA2 [ group=B
            shape = point;
            width = 0;
        ]
    
        edge[ 
            style = solid  //default;
            fontname = "Roboto"
            weight = 100;
        ]
        
        A -> B 
        B -> C
        C -> D
        D -> E
    
    //    we need constraints to be in effect, to influance positioning
    //      the constraint documentation may not be complete as to the effect
    //    edge[
    //        constraint = false;
    //    ]
        
        // Should Be at the Left Side
        //C -> invisC1
        invisC1 -> C   [dir=none]
        invisC1 -> invisB1 [dir=none]
        invisB1 -> B
        B -> Done1
        
        //E -> invisE1
        invisE1 -> E   [dir=none]
        invisE1 -> invisD1   [dir=none]
        invisD1 -> D
        D -> Done2
    
        E -> Reform
        // Should be at the right side (Working Correctly)
        Reform -> invisA2 [dir=none]
        //invisA2 -> A [label = "                                         "]
        A -> invisA2  [dir=back label = "                             "]
    
        {rank=same   A invisA2}
        {rank = same; invisB1, B, Done1}
        {rank = same; invisC1, C}
        {rank = same; invisD1, D, Done2}
        {rank = same; invisE1, E, Reform}
    }
    

    Giving:
    enter image description here