Graphviz中的图的图 [英] Graph of Graphs in Graphviz

查看:96
本文介绍了Graphviz中的图的图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些用DOT语言编码的有向图.我想构造一个图图,以使超图中的每个节点都是这些图中的一个.在GraphViz框架中有没有办法做到这一点?

I have a collection of digraphs encoded in the DOT language. I want to construct a graph-of-graphs such that each node in the super-graph is one of these digraphs. Is there a way to do this within the GraphViz framework?

我知道gvpack将使我可以将多个图形组合到一个.dot文件中.但是我不知道是否允许我在这些图之间声明边.

I know that gvpack will allow me to assemble multiple graphs into one .dot file. But I don't know if it will allow me to declare edges between those graphs.

推荐答案

简短的答案是gvpack不在子图之间声明边.实际上,当子图之间存在公共节点名称时,gvpack将其重命名以避免冲突.但是,这是可以解决的.

The short answer is that gvpack does not declare edges between the sub-graphs. Indeed, when there are common node names between sub-graphs, gvpack renames them to avoid clashes. However, that is fixable.

例如,给定三个.dot文件1.dot:

digraph {
    A -> B
    A -> C
    }

2.dot:

digraph {
    D -> E
    E -> F
    }

...和3.dot:

digraph {
    D -> G
    G -> A
    }

...运行gvpack -u 1.dot 2.dot 3.dot | dot -Tjpg -ogvp1.jpg会给出以下图形gvp1.jpg:

... running gvpack -u 1.dot 2.dot 3.dot | dot -Tjpg -ogvp1.jpg gives the following graph gvp1.jpg:

如您所见,gvpack重新标记了重复的节点名称.但是,我们可以轻松地使用gvpack -u 1.dot 2.dot 3.dot | sed 's/_gv[0-9]\+//g' | dot -Tjpg -ogvsub.jpg反转重新标记,这将产生以下图形gvsub.jpg:

As you can see, gvpack has relabelled the duplicate node names. However, we can easily reverse the re-labelling using gvpack -u 1.dot 2.dot 3.dot | sed 's/_gv[0-9]\+//g' | dot -Tjpg -ogvsub.jpg, which produces the following graph gvsub.jpg:

此方法依赖于具有相同节点名称的子图,因此可能有必要在子图.dot文件中插入其他节点以实现此目的.

This approach relies on the subgraphs having node names in common, so it might be necessary to insert additional nodes in the sub-graph .dot files to achieve this.

(上面的解决方案显示了节点合并的图,但不包含集群中的子图.以下解决方案显示了集群中的子图.)

( The solution above showed the graph with nodes merged but not with the sub-graphs in clusters. The following solution shows the sub-graphs in clusters.)

给出.dot个文件1.dot(这些文件与上面的文件相同,除了我给每个图有一个名字):

Given .dot files 1.dot (these are the same as the files above, except I've given each digraph a name):

digraph g1 {
    A -> B
    A -> C
    }

2.dot:

digraph g2 {
    D -> E
    E -> F
    }

...和3.dot:

digraph g3 {
    D -> G
    G -> A
    }

...和hdr.dot:

digraph GMaster {
    compound = true;
    g1 [style=invisible, height = 0, width = 0, label=""];
    g2 [style=invisible, height = 0, width = 0, label=""];
    g3 [style=invisible, height = 0, width = 0, label=""];
    g1 -> g2 [lhead=clusterg2, ltail=clusterg1];
    g1 -> g3 [lhead=clusterg3, ltail=clusterg1]

...和tail.dot:

}

...我们可以运行cat 1.dot 2.dot 3.dot | sed 's/digraph \(\w*\) *{/subgraph cluster\1 { \1/' | cat hdr.dot - tail.dot | dot -Tjpg -oclust1.jpg来提供文件clust1.jpg:

... we can run cat 1.dot 2.dot 3.dot | sed 's/digraph \(\w*\) *{/subgraph cluster\1 { \1/' | cat hdr.dot - tail.dot | dot -Tjpg -oclust1.jpg to give the file clust1.jpg:

因此,在头文件中,我向每个子图添加了一个不可见节点,其名称与子图相同,并使用compound=true允许簇之间的边缘.我指定了要在聚类之间绘制的边缘,并为不可见节点之间的每个边缘设置了lheadltail,以确保将正确的聚类用作这些边缘中的每个的头和尾.在使用sed将每个子图转换为群集的过程中,我还向每个子图添加了适当的不可见节点.

Thus, in the header file, I've added an invisble node to each subgraph, with the same name as the sub-graph, used compound=true to allow edges between clusters. I've specified the edges to draw between the clusters and I've set lhead and ltail for each of the edges between the invisible nodes to ensure that the right cluster is used as the head and tail of each of those edges. I've also added the appropriate invisible node to each subgraph in the process of transforming each subgraph into a cluster using sed.

显示了节点D,G和A之间的边缘,因为这些节点在群集之间是公共的.此外,它们每个仅显示在一个群集中.如果节点对于群集是唯一的,则群集之间唯一显示的边缘将是不可见节点之间的边缘.可以在下图中看到,其中我已将3.dot中的节点重命名为:

The edges between nodes D, G and A are shown because those nodes are common between the clusters. Also, each of them is only shown in one cluster. If the nodes were unique to the clusters, the only edges that would be shown between clusters would be the edges between the invisible nodes. This can be seen in the following graph, where I've renamed the nodes in 3.dot:

还有一个我还无法修复的缺陷.不可见的节点仍占据一点空间,因此群集框看起来偏斜,因为不可见的节点与可见节点并排放置.这也意味着群集之间的边缘的头部指向群集框的一侧而不是中间.目前,我看不到该怎么办,除非我们准备查看每个子图并找到该子图/集群中已经存在的节点作为该子图/集群的代表节点(即我们向该群集绘制边缘或从中绘制边缘).手动完成几个子图就可以很容易地做到这一点,但是如果有很多子图,那将是乏味的.

There is one remaining flaw that I haven't quite been able to fix. The invisible nodes still take up a little bit of space so the cluster boxes look lopsided because the invisble nodes sit alongside the visible nodes. This also means that the heads of the edges between the clusters point at one side of the cluster box rather than the middle. At present, I can't see what could be done about that, unless we are prepared to look at each subgraph and find a node that is already in that subgraph/cluster to serve as the representative node for that subgraph/cluster (i.e. the one to or from which we draw edges for that cluster). That could be done easily enough by hand for a few subgraphs but it would be tedious if there were many subgraphs.

相比之下,我上面使用的方法仅要求我们知道集群的名称并将其插入到hdr.dot文件中即可.

In contrast, the approach I've used above requires only that we know the name of the cluster and can insert it into the hdr.dot file.

在这种情况下,我已经手动构造了hdr.dot文件,但是hdr.dot文件的内容可以使用sedawkperlpython如果有需要.如果某个地方有应连接哪些集群的信息,该脚本还可以插入边缘以将集群链接到hdr.dot中.

I've constructed the hdr.dot file by hand for this case but the content of the hdr.dot file could be extracted from the other .dot files with sed, awk, perl or python if there was a need. The script could also insert the edges to link the clusters into hdr.dot if information about which clusters should be connected was available somewhere.

这篇关于Graphviz中的图的图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆