如何在Graphviz(dot语言)图中反转每个边的方向?

10

我有一个以Graphviz的dot语言指定的有向图,例如:

digraph G { A -> B [label="foo"]; A -> B [label="bar"]; B -> A; C; }

我想自动将它处理成一个反向边的图,即

digraph G { B -> A [label="foo"]; B -> A [label="bar"]; A -> B; C; }
我想使用一个强大的解决方案(即一个能理解图形并因此可能不使用sed的解决方案),它保留任何现有的边缘标签和其他属性。请注意,我不仅仅是说要让dot用箭头指向后面来渲染我的图形;我真正需要的是一个边缘被反转的图形。(在这种情况下,我打算反转边缘,应用prune,然后再次反转边缘。)
如何在Graphviz (dot-语言)图中将每个边缘的方向反转?
3个回答

12

最简单的方法是在图层级别包含一个 dir 语句,通过它可以反转箭头的方向。默认情况下,方向是正向的(forward)。如果你在图形的顶部将其反转,那么在不改变任何其他行的情况下,该图形将以你想要的方式显示。

现在您拥有的是这个:

digraph G
{
    edge [dir="forward"]; /* implied */
    A -> B [label="foo"];
    A -> B [label="bar"];
    B -> A;
    C;
}
你想要的是这个:

What you want is this:

digraph G
{
    edge [dir="back"]; /* note the change to this line */
    A -> B [label="foo"];
    A -> B [label="bar"];
    B -> A;
    C;
}

7
我认为你需要在边上设置属性,而不是整个图。像这样:edge [dir="back"]; - Scott McIntyre
1
是的,@ScottMcIntyre 是正确的:您必须在图的主体开头放置一个 edge [dir="back"]; 指令才能让它正常工作。 - juandesant

2
到目前为止,我想到的最好的解决方案是:
BEG_G {
    graph_t g = graph($.name + " reversed", "D");
    int edge_id = 0;
}

N {
    clone(g, $);
}

E {
    node_t newHead = clone(g, $.head);
    node_t newTail = clone(g, $.tail);
    edge_t newEdge = edge_sg(g, newHead, newTail, edge_id);
    copyA($, newEdge);
    edge_id++;
}

END_G {
    $O = g;
}

我随后使用 gvpr 调用它。这确实给所有结果边添加了“key”属性,但我不确定如何避免这种情况,同时仍然保留相同节点对之间的多个边。
当我执行echo 'digraph G { A -> B [label="foo"]; A -> B [label="bar"]; B -> A; C; }' | gvpr -f reverseAllEdges.gvpr时,输出如下:
digraph "G reversed" {
    A -> B [key=2];
    B -> A [key=0, label=foo];
    B -> A [key=1, label=bar];
    C;
}

我不知道这个会有多可靠,但它看起来很有前途。

0
Python库NetworkX有一个有向多图类型MultiDiGraph,它具有reverse()方法。它还使用pydot来加载和写入DOT文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接