在GraphViz的DOT语言中,我试图表示一个依赖关系图。我需要能够在容器中有节点,并能够使节点和/或容器依赖于其他节点和/或容器。

我用子图来表示容器。节点链接工作得很好,但我不知道如何连接子图。

给定下面的程序,我需要能够用箭头连接cluster_1和cluster_2,但我所尝试的任何事情都会创建新的节点,而不是连接集群:

digraph G {

    graph [fontsize=10 fontname="Verdana"];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Renders fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Both of these create new nodes
    cluster_1 -> cluster_2;
    "Container A" -> "Container C";
}


当前回答

确保在有向图选项中compound=true(参考):

digraph {
  compound=true;

  subgraph cluster_a {
    label="Cluster A";
    node1; node3; node5; node7;
  }
  subgraph cluster_b {
    label="Cluster B";
    node2; node4; node6; node8;
  }

  node1 -> node2 [label="1"];
  node3 -> node4 [label="2" ltail="cluster_a"];
  
  node5 -> node6 [label="3" lhead="cluster_b"];
  node7 -> node8 [label="4" ltail="cluster_a" lhead="cluster_b"];
}

其他回答

确保在有向图选项中compound=true(参考):

digraph {
  compound=true;

  subgraph cluster_a {
    label="Cluster A";
    node1; node3; node5; node7;
  }
  subgraph cluster_b {
    label="Cluster B";
    node2; node4; node6; node8;
  }

  node1 -> node2 [label="1"];
  node3 -> node4 [label="2" ltail="cluster_a"];
  
  node5 -> node6 [label="3" lhead="cluster_b"];
  node7 -> node8 [label="4" ltail="cluster_a" lhead="cluster_b"];
}

为了便于参考,HighPerformanceMark的答案中描述的解决方案直接应用于原始问题,看起来像这样:

digraph G {

    graph [fontsize=10 fontname="Verdana" compound=true];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Edges between nodes render fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Edges that directly connect one cluster to another
    "Item 1" -> "Item 3" [ltail=cluster_0 lhead=cluster_1];
    "Item 1" -> "Item 5" [ltail=cluster_0 lhead=cluster_2];
}

重要的是:

在图形声明中使用compound=true 将子图命名为cluster_* 根据下面的评论,不要以大写字母开始集群名称。我不太清楚那是什么意思。它是否禁止cluster_A?),但想在这里突出显示它以防它是一个陷阱。

产生输出:

注意,我将边更改为集群中的引用节点,为每条边添加tail和lhead属性,指定集群名称,并添加图形级属性'compound=true'。

对于可能想要连接一个内部没有节点的集群的担忧,我的解决方案(上面没有显示)是始终向每个集群添加一个节点,使用style=明文呈现。使用此节点标记集群(而不是集群内置的“label”属性,该属性应该设置为空字符串(在Python中,label='""')。这意味着我不再添加直接连接集群的边,但它适用于我的特定情况。

DOT用户手册给出了以下图的例子,图中集群之间有边:

重要提示:开头复合=true语句是必需的。

digraph G {
  compound=true;
  subgraph cluster0 {
    a -> b;
    a -> c;
    b -> d;
    c -> d;
  }
  subgraph cluster1 {
    e -> g;
    e -> f;
  }
  b -> f [lhead=cluster1];
  d -> e;
  c -> g [ltail=cluster0,lhead=cluster1];
  c -> e [ltail=cluster0];
  d -> h;
}

... 节点和集群之间的边:

确保文件使用fdp布局。我认为neato不支持集群。