# Arrange nodes between ranks correctly

**URL:** <https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503>\
**Category:** Help\
**Created:** [October 20, 2024, 1:14pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503 "2024-10-20T13:14:04Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![us12](https://avatars.discourse-cdn.com/v4/letter/u/90ced4/32.png) [@us12](https://forum.graphviz.org/u/us12)\
**Post date:** [October 20, 2024, 1:14pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503/1 "2024-10-20T13:14:04Z")

</div>

\*here in the topic I may use terms incorrectly, but I try to explain in my words, so feel free to suggest me how to use it correctly.

I have graphs like these:

```auto

digraph {
    rankdir=LR;
  
    A1 
    A2
    A3 
 
    B1 
    B2 
    B3 

    C1 
    C2 
    C3 

    A1 -> B1
    B1 -> C1
    
    //A1 -> B2
    A1 -> A2
    A1 -> A3
    A2 -> A3
    
    B1 -> B2
    B2 -> B3
    B1 -> B3
    B2 -> A2
    //B3 -> C2
    
    C1 -> C2
    C2 -> C3
    

  //B1 -> C2
  C3 -> B2
}

```

 ![](https://global.discourse-cdn.com/graphviz/original/2X/3/36b4f94c948151c9677e1bba64429801bba2a568.png)  
I like that arrows are constraints here (I mean, node A2 goes right of the B2).  
But I don’t like that A,B,C-nodes are mixed between each other vertically.  
I want that all A-nodes are placed on its own “line” (rank?) and only A-nodes are placed in this horizontal area.  
All B-nodes = in B-line, under A-line…  
All C-nodes = in C-line, under B-line…  
In the certain order, defined manually and strictly for each node.  
Now B and C nodes are mixed in one “line”.

I tried clusters with the code below.  
I like that A-nodes are placed on the same “level” and A-nodes are not mixed with B-nodes vertically, B-nodes not mixed with C-nodes.  
But I don’t like that links between nodes of the different clusters don’t work as constraints…  
I don’t like that B2 is placed under A2.  
I want A2 to be placed right of the B2 due to the corresponding arrow.  
I also would like to have control over placing B1 under C1, or C1 right of the B1, or C1 under B2, but it is somehow shown under B3.

```auto

digraph {
    rankdir=LR;
    
    subgraph cluster_1 {
        A1 
        A2
        A3
    }
    subgraph cluster_2 {
        B1 
        B2
        B3
    }
    
    subgraph cluster_3 {
        C1 
        C2
        C3
    } 
    
    A1 -> B1
    B1 -> C1
    
    A1 -> B2
    A1 -> A2
    A1 -> A3
    A2 -> A3
    
    B1 -> B2
    B2 -> B3
    B1 -> B3
    B2 -> A2
    B3 -> C2
    
    C1 -> C2
    C2 -> C3
    
}

```

 ![](https://global.discourse-cdn.com/graphviz/original/2X/5/52c22a71514f6eeaad0489813170a2d78babd630.png)  
I also tried using rank=same AND groups and it looks better, but I don’t understand how to ensure that the edges work as constraints so that B2 goes right after C3, not on the same level.

```auto

digraph {
    rankdir=TB;

  {rank=same; A1; A2; A3}
  {rank=same; B1; B2; B3}
  {rank=same; C1; C2; C3}
  
    A1 [group=1]
    A2 [group=2]
    A3 
 
    B1 [group=1]
    B2 [group=2]
    B3 

    C1 [group=1]
    C2 
    C3 [group=2]

    A1 -> B1
    B1 -> C1
    
    //A1 -> B2
    A1 -> A2
    A1 -> A3
    A2 -> A3
    
    B1 -> B2
    B2 -> B3
    B1 -> B3
    B2 -> A2
    //B3 -> C2
    
    C1 -> C2
    C2 -> C3
    

  //B1 -> C2
  C3 -> B2
}

```

 ![](https://global.discourse-cdn.com/graphviz/original/2X/6/6706ca7c668f99c40d6f01b4da4c7ed72bdd0cc2.png)

If I remove the group, the arrow from C3 goes left to B2, but I want this arrow to go right to B2 and B2 should be placed right, on a new rank(?) to obey constraint of the edge.  
By the way, sometimes I will need this backward arrows, and sometimes I don’t need them.  
I expected to do it using constraint=true/false.  
But even with default value, it doesn’t take place.

![](https://global.discourse-cdn.com/graphviz/original/2X/c/cc77eea65b6d374e60c65441dfbcb4c8c61e2b70.png)

---

<div class="post-metadata">

**Author:** ![jjlong](https://sea2.discourse-cdn.com/graphviz/user_avatar/forum.graphviz.org/jjlong/32/887_2.png) [@jjlong](https://forum.graphviz.org/u/jjlong)\
**Post date:** [October 20, 2024, 4:07pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503/2 "2024-10-20T16:07:25Z")

</div>

Add `weight` attributes to the edges which you wish to straighten out.

```dot
strict digraph "Graphviz Forum"
{
    rankdir=LR;
    A1;
    A2;
    A3;
    B1;
    B2;
    B3;
    C1;
    C2;
    C3;
    A1 -> B1;
    B1 -> C1;
    A1 -> A2[weight=100];
    A1 -> A3;
    A2 -> A3[weight=100];
    B1 -> B2[weight=100];
    B2 -> B3[weight=100];
    B1 -> B3;
    B2 -> A2;
    C1 -> C2;
    C2 -> C3;
    C3 -> B2;
}

```

yields the following graph:

 ![Graphviz Forum](https://global.discourse-cdn.com/graphviz/original/2X/e/e4b71294cbfb2249a2fcd7e35c971f9f46acf311.png)

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [October 21, 2024, 3:03pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503/3 "2024-10-21T15:03:42Z")

</div>

Another way to produce ~ same result as @jjlong, using **group** and **constraint=false**

```auto
/ ******************************************************************************
  forum - https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503
  - now
    - rankdir=LR
    - removed rank=same - not needed
    - changed grouping A1, A2, A3 ...
    - added constraint=false keeps the groups linear
****************************************************************************** /
digraph {

  rankdir=LR; // changed

    A1 [group=1]
    A2 [group=1]
    A3 [group=1]
 
    B1 [group=2]
    B2 [group=2]
    B3 [group=2]

    C1 [group=3]
    C2 [group=3]
    C3 [group=3]

    A1 -> B1
    B1 -> C1
    
    //A1 -> B2
    A1 -> A2
    A1 -> A3 [constraint=false] // constraint=false keeps the group linear
    A2 -> A3 
    
    B1 -> B2
    B2 -> B3
    B1 -> B3 [constraint=false] // constraint=false keeps the group linear
    B2 -> A2   
    //B3 -> C2
    
    C1 -> C2
    C2 -> C3

  //B1 -> C2
  C3 -> B2
}

```

Giving:

 ![explicitNodeArrange11](https://global.discourse-cdn.com/graphviz/original/2X/2/2208f08f356ef7cd02a9785039f1c5b0331fe5c2.png)

---

<div class="post-metadata">

**Author:** ![us12](https://avatars.discourse-cdn.com/v4/letter/u/90ced4/32.png) [@us12](https://forum.graphviz.org/u/us12)\
**Post date:** [October 21, 2024, 3:41pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503/4 "2024-10-21T15:41:52Z")

</div>

Thanks.

Could you please explain how you choose which edges should have [constraint=false] ?

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [October 21, 2024, 4:18pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503/5 "2024-10-21T16:18:59Z")

</div>

Without the two **constraint=false** additions, the A1, A2, A3 and B1, B2, B3 nodes were not linear (in a line), even with the **group** attributes. I saw that the two “long” edges (multi-hop) were not needed to position A3 and B3 in either the X or Y direction and guessed that the two edges were “pulling” the nodes out of line.  
(Does that make sense?)

---

<div class="post-metadata">

**Author:** ![us12](https://avatars.discourse-cdn.com/v4/letter/u/90ced4/32.png) [@us12](https://forum.graphviz.org/u/us12)\
**Post date:** [October 21, 2024, 6:14pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503/6 "2024-10-21T18:14:28Z")

</div>

If I will want to place C3 under B2, how can I achieve it?  
Click the gif-file below to see my explanation:

![Animation (1)](https://global.discourse-cdn.com/graphviz/original/2X/1/11645f3fd6cad3f817b7f5fae39d2e945e365bac.gif)

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [October 21, 2024, 10:53pm UTC](https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503/7 "2024-10-21T22:53:01Z")

</div>

The answer _should_ be: **B2 → A2 [minlen=0]** ([minlen | Graphviz](https://www.graphviz.org/docs/attrs/minlen/)). It kind of works, except it also flips the graph upside-down. Dang!

 ![explicitNodeArrange11](https://global.discourse-cdn.com/graphviz/original/2X/3/3aea410fd7ad22b084842572037509cce72ed64e.png)

Back to the drawing-board. By adding **cluster** s and **minlen** , we get the desired graph.

```auto
/ ******************************************************************************
  forum - https://forum.graphviz.org/t/arrange-nodes-between-ranks-correctly/2503
  - now
    -rankdir=LR
    - removed rank=same - not needed
    - changed grouping A1, A2, A3 ...
    - added clusters
    - added constraint=false keeps the groups linear
****************************************************************************** /
digraph {

  rankdir=LR; // changed
{
  cluster=true peripheries=0
    A1 [group=1]
    A2 [group=1]
    A3 [group=1]
    A1 -> A2 [minlen=5]
    A1 -> A3 [constraint=false] // constraint=false keeps the group linear
    A2 -> A3
}

{
  cluster=true peripheries=0
    B1 [group=2]
    B2 [group=2]
    B3 [group=2]
    B1 -> B2 [minlen=4]
    B2 -> B3
    B1 -> B3 [constraint=false] // constraint=false keeps the group linear 
}
{
  cluster=true peripheries=0
    C1 [group=3]
    C2 [group=3]
    C3 [group=3]
    C1 -> C2
    C2 -> C3
}
   C3 -> B2
    A1 -> B1
    B1 -> C1
    
    //A1 -> B2
    B2 -> A2 [minlen=0]
    //B3 -> C2
  //B1 -> C2   
}

```

 ![explicitNodeArrange12](https://global.discourse-cdn.com/graphviz/original/2X/8/89fb984d6bc36adf1ec914b81af2836fd7d1959c.png)
