# Linking 2 subgraphs with dot

**URL:** <https://forum.graphviz.org/t/linking-2-subgraphs-with-dot/1674>\
**Category:** Help\
**Created:** [June 18, 2023, 4:36am UTC](https://forum.graphviz.org/t/linking-2-subgraphs-with-dot/1674 "2023-06-18T04:36:29Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![dse](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@dse](https://forum.graphviz.org/u/dse)\
**Post date:** [June 18, 2023, 4:36am UTC](https://forum.graphviz.org/t/linking-2-subgraphs-with-dot/1674/1 "2023-06-18T04:36:29Z")

</div>

Hello,

Below are the code with corresponding image.

I need to link two subgraphs (“cluster\_A1” and “cluster\_B1”, arrow tail starting on the subgraph’s border)  
Please advise me on the best way to do this.

I tried adding invisible nodes, but it does not give me the output I want (here I made the dots visible just for clarity) :

- The invisible node should be right below the subgraph labels (A1 and B1), not at the bottom
  - Or if possible, right beside the labels, left or right

- I want to minimize the space taken by the invisible node

Thank you.

```auto
digraph G {
rankdir=LR
splines=ortho
edge [fontsize=12]
    subgraph "cluster_A1" {
    "A1_invis"[shape=point style=invisx pin=true]
    "A3"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
    label = "A1"
    style = "filled, rounded"
    fillcolor = "lightgray"
        subgraph "cluster_A2" {
        label = "A2"
        style = "filled, rounded"
        fillcolor = "lightblue"
        "A4"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
        }
    }
    subgraph "cluster_B1" {
    "B1_invis"[shape=point style=invisx pin=true]
    label = "B1"
    style = "filled, rounded"
    fillcolor = "lightgray"
        subgraph "cluster_B2" {
        label = "B2"
        style = "filled, rounded"
        fillcolor = "lightblue"
        "B3"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
        "B4"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
        }
    }
     A1_invis->B1_invis[xlabel="\E", style="solid"]
}

```

![image](https://global.discourse-cdn.com/graphviz/original/2X/7/7fde59beb4f84a289d5d689f3bb567a8061cf949.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:** [June 18, 2023, 2:29pm UTC](https://forum.graphviz.org/t/linking-2-subgraphs-with-dot/1674/2 "2023-06-18T14:29:43Z")

</div>

A bit of a challenge, but by putting the invisible nodes inside clusters of their own, we get **dot** to place them at the top of the surrounding clusters. [Nope, not documented, I made a guess].  
Wasn’t sure what to do with the edge xlabel/label. What do you really want?

Removed:

- **pin** doesn’t hurt, but ignored by **dot**

Added:

- **compound**
- **peripheries**
- **lhead** & **ltail**
- **margin**
- **minlen** to push B1 to the right

Look up any of these attributes here: [Attributes | Graphviz](https://graphviz.org/doc/info/attrs.html)  
So:

```auto
digraph G {
rankdir=LR
splines=ortho // ortho is buggy, but OK for this use
compound=true // allow edges that seem to be to/from clusters

  edge [fontsize=12]    
    subgraph "cluster_A1" {
      subgraph clusterI1{
        peripheries=0 // no surrounding box
        margin=0 // reduce vertical space 
        "A1_invis"[shape=point style=invis] // pin ignored by dot pin=true]
      }
      "A3"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
      label = "A1"
      style = "filled, rounded"
      fillcolor = "lightgray"
        subgraph "cluster_A2" {
        label = "A2"
        style = "filled, rounded"
        fillcolor = "lightblue"
        "A4"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
        }
    }
    subgraph "cluster_B1" {
    subgraph clusterI2{
      peripheries=0 // no surrounding box
      margin=0 // reduce vertical space 
      "B1_invis"[shape=point style=invis] // ignored pin=true]
      }
    label = "B1"
    style = "filled, rounded"
    fillcolor = "lightgray"
        subgraph "cluster_B2" {
        label = "B2"
        style = "filled, rounded"
        fillcolor = "lightblue"
        "B3"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
        "B4"[shape=rectangle, style="rounded,filled", fillcolor=khaki]
        }
    }
    // added lhead & ltail to appear cluster-to-cluster
    // what label/xlabel do you really want, if any?
    A1_invis->B1_invis [XXXXXxlabel="\E", style="solid"
      minlen=2 // push cluster_B1 to the right (down a rank)
      ltail=cluster_A1 lhead=cluster_B1 ]
}

```

Giving:  
 ![cluster2clusterForum1](https://global.discourse-cdn.com/graphviz/original/2X/4/4cb3ff4b85b7aa8900dda62a32027bf5f8cdb5aa.png)

---

<div class="post-metadata">

**Author:** ![dse](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@dse](https://forum.graphviz.org/u/dse)\
**Post date:** [June 24, 2023, 9:10pm UTC](https://forum.graphviz.org/t/linking-2-subgraphs-with-dot/1674/3 "2023-06-24T21:10:09Z")

</div>

Thank you for the answer !

- However sometimes the invisible nodes a set in between nodes, and not at the top or bottom like they should
- Do you know why the arrow from A1\_invis to B1\_invis in the graph below doesn’t start/end at the border of the subgraphs ?

> **graph**
>
> ![image](https://global.discourse-cdn.com/graphviz/original/2X/6/6890416caece98cf20764dbfbdc7c2f6136bd3d3.png)

I also tried recreating this using tables:

> **code**
>
> ```auto
> digraph test {
> rankdir=LR
> // splines="polyline"
> ranksep=1.2
> node [label="\N", fontsize=15, shape=plaintext];
> atbl [label=<
> <TABLE BGCOLOR="lightgray" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="a1">
> <TR><TD BORDER="0" >title</TD></TR>
> 
> <TR> 
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="a2">
> <TR><TD BORDER="0" PORT="f1">A</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" PORT="l1" WIDTH="50">a</TD></TR> 
> </TABLE>
> </TD>
> </TR>
>           
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">A</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >a</TD></TR> 
> </TABLE>
> </TD>
> </TR>
> </TABLE>
> >, ];
>     
> btbl [label=<
> <TABLE BGCOLOR="lightgray" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">title</TD></TR>
> 
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">B</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >b</TD></TR> 
> </TABLE>
> </TD>
> </TR>
>           
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">B</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="b1">b</TD></TR> 
> </TABLE>
> </TD>
> </TR>
> </TABLE>
> >, ];
>     
> ctbl [label=<
> <TABLE BGCOLOR="lightgray" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">title</TD></TR>
> 
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">C</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >c</TD></TR> 
> </TABLE>
> </TD>
> </TR>
>           
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">C</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="c1">c</TD></TR> 
> </TABLE>
> </TD>
> </TR>
> </TABLE>
> >, ];
>     
>     
>     
> dtbl [label=<
> <TABLE BGCOLOR="lightgray" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">title</TD></TR>
> 
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">D</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >d</TD></TR> 
> </TABLE>
> </TD>
> </TR>
>           
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">D</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="d1">d</TD></TR> 
> </TABLE>
> </TD>
> </TR>
> </TABLE>
> >, ];
>     
> etbl [label=<
> <TABLE BGCOLOR="lightgray" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">title</TD></TR>
> 
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">E</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >e</TD></TR> 
> </TABLE>
> </TD>
> </TR>
>           
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">E</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="e1">e</TD></TR> 
> </TABLE>
> </TD>
> </TR>
> </TABLE>
> >, ];
> 
> ftbl [label=<
> <TABLE BGCOLOR="lightgray" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50">
> <TR><TD BORDER="0">title</TD></TR>
> 
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="f0">
> <TR><TD BORDER="0">F</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >f</TD></TR> 
> </TABLE>
> </TD>
> </TR>
>       
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">F</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" PORT="f1">f</TD></TR> 
> </TABLE>
> </TD>
> </TR>
> </TABLE>
> >, ];
> 
> gtbl [label=<
> <TABLE BGCOLOR="lightgray" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">title</TD></TR>
> 
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">G</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >g</TD></TR> 
> </TABLE>
> </TD>
> </TR>
>   
> <TR>
> <TD BORDER="0">
> <TABLE BGCOLOR="lightblue" STYLE="ROUNDED" CELLSPACING="5" WIDTH="50" >
> <TR><TD BORDER="0">G</TD></TR> 
> <TR><TD BGCOLOR="khaki" STYLE="ROUNDED" PORT="g1" CELLSPACING="5" WIDTH="50" >g</TD></TR> 
> </TABLE>
> </TD>
> </TR>
> </TABLE>
> >, ];
> 
>     
> atbl:a1->btbl:b1[xlabel="A-b"]
> atbl:a1->ctbl:c1[xlabel="A-c"]
> atbl:a1->dtbl:d1[xlabel="A-d"]
> btbl:b1->dtbl:d1[xlabel="b-d"]
> atbl:a1->etbl:e1[xlabel="A-e"]
> etbl:e1->ctbl:c1[xlabel="e-c"]
> atbl:a1->ftbl:f0[xlabel="A-F"]
> btbl:b1->ftbl:f1[xlabel="b-f"]
> atbl:a1->gtbl:g1[xlabel="A-g"]
> }
> 
> ```

> **img**
>
> ![image](https://global.discourse-cdn.com/graphviz/original/2X/8/851b99ea7033e015271035caebeecf4714580f1c.png)

But splines=“ortho” doesn’t work with ports.

Is there another way to get this output but with orthogonal lines ?  
(with or without tables, and if possible without invisible nodes)

Thank you !

---

<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:** [June 25, 2023, 4:03am UTC](https://forum.graphviz.org/t/linking-2-subgraphs-with-dot/1674/4 "2023-06-25T04:03:16Z")

</div>

Please include the failing version of your input.  
(Unfortunately, ortho does not work with ports, currently a lost cause. So ortho & tables are quite unlikely)
