仅使用graphviz工具生成传递闭包

时间:2013-09-09 16:35:05

标签: graphviz

我需要以点格式处理有向图并获得子图的传递闭包(实际上是一个节点)。

例如,给定

 A -> B;
 E -> B;
 B -> C;
 C -> D;

我想获得由节点A形成的子图的传递闭包:

 A -> B;
 B -> C;
 C -> D;

我知道这在python和许多其他语言中是可能的,但我试图仅使用命令行graphviz工具来实现这一点。

有没有简单的方法呢? (我做了 rtfm of dot,tred,patchwork ......没有任何运气)。

1 个答案:

答案 0 :(得分:3)

gvpr应该能够执行此任务。现在我会试试......

编辑不是很容易,但这可能是一个起点

- file closure.gprv

BEGIN {
 int to_visit[];
 void add_req(node_t N) {
  edge_t e;
  for (e = fstout(N); e; e = nxtout(e))
   to_visit[e.head.name] = 1;
 }
}

BEG_G {
 $tvtype = TV_fwd;
 $tvroot = node($, "A");
 to_visit[$tvroot.name] = 1;
 add_req($tvroot);
 graph_t g = graph("A closure", "D");
}

N {
 if (to_visit[$.name]) {
  copy(g, $);
  add_req($);
 }
}

END_G {
 $O = g;
}

- file closure.gv

digraph closure {
 A -> B;
 E -> B;
 B -> C;
 C -> D;
}

- 命令和结果

gvpr -f closure.gprv closure.gv
digraph "A closure" {
    A;
    B;
    C;
    D;
}

编辑这个其他版本更完整,因为它也构建边缘

BEGIN {
 int to_visit[];
 void add_req(node_t N) {
  edge_t e;
  for (e = fstout(N); e; e = nxtout(e))
   to_visit[e.head.name] = 1;
 }
}

BEG_G {
 $tvtype = TV_fwd;
 $tvroot = node($, "A");
 to_visit[$tvroot.name] = 1;
 add_req($tvroot);
 graph_t g = graph("A closure", "D");
}

E {
 if (to_visit[$.tail.name]) {
  copy(g, $);
  add_req($.head);
 }
}

END_G {
 $O = g;
}

产量

gvpr -f closure.gprv closure.gv
digraph "A closure" {
    A -> B;
    B -> C;
    C -> D;
}