我有一个用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
-language)图形中反转每条边的方向?
最简单的方法是包含一个图形级别的dir
语句,您可以在其中反转箭头的方向。默认情况下,方向是forward
。如果您在图表的顶部反转它,那么在不更改任何其他行的情况下,图表将以您希望的方式显示。
你现在拥有的是:
digraph G
{
dir="forward"; /* implied */
A -> B [label="foo"];
A -> B [label="bar"];
B -> A;
C;
}
你想要的是这个:
digraph G
{
edge [dir="back"]; /* note the change to this line */
A -> B [label="foo"];
A -> B [label="bar"];
B -> A;
C;
}
到目前为止我提出的最好的是
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
调用它。
这确实为所有结果边添加了“关键”属性,但我不确定如何避免这种情况,并且仍然保留同一对节点之间的多个边。
当我做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;
}
我不知道这会有多强大,但看起来很有希望。
Python库NetworkX有一个有向多图类型MultiDiGraph,它有一个reverse()方法。它还使用pydot来加载和写入DOT文件。