繁体   English   中英

如何通过消除蛇行和更好的边缘交叉来影响Graphviz /点以制作更好的控制流图?

[英]How can I influence Graphviz/dot to make nicer control-flow graphs by removing snaking and better edge crossings?

我正在为Python程序绘制控制流图,并希望影响不应跨越的边缘类型。 有没有办法做到这一点?

考虑以下简单的Python程序:

try:
    a += 1
except:
    a += 2
else:
    a = 3

还有一个点程序代表通过https://github.com/rocky/python-control-flow/生成的控制流

digraph G {
  mclimit=1.5;
  rankdir=TD; ordering=out;
  graph[fontsize=10 fontname="Verdana"];
  color="#efefef";
  node[shape=box style=filled fontsize=8 fontname="Verdana" fillcolor="#efefef"];
  edge[fontsize=8 fontname="Verdana"];

  node_0 [shape = "oval"][label="Basic Block 0\loffsets: 0..12\lflags=entry, block, unconditional, try\ljumps=[34]\l"];
  node_1 [label="Basic Block 1\loffsets: 14..30\lflags=except, unconditional\ljumps=[38]\l"];
  node_2 [label="Basic Block 2\loffsets: 32..32\lflags=end finally\l"];
  node_3 [label="Basic Block 3\loffsets: 34..36\l"];
  node_4 [label="Basic Block 4\loffsets: 38..40\lflags=no fallthrough\l"];

  node_0 -> node_2 [weight=1][color="red"];
  node_3 -> node_4 [weight=10];
  node_0 -> node_1 [weight=1][color="red"];
  node_2 -> node_3 [weight=10];
  node_0 -> node_1 [weight=10][style="invis"];
  node_1 -> node_2 [weight=10][style="invis"];
  node_1 -> node_4 [weight=1];
  node_0 -> node_3 [weight=1];
}

点为以上生成的图像是 在此处输入图片说明

请注意,一条线如何蜿蜒并向下穿过直线箭头。 相反,我希望没有一个向下的直线箭头会被交叉。 花键边缘将使交叉的位置更好。

如果您查看该点,则有两个不可见的向下边缘,用于对齐。 (在字节码中,它们遵循指令的线性顺序)。

因此,如果需要越过一条向下的直线(此处不需要),则不可见的边缘将优先于可见的边缘。

有什么想法吗?

编辑

到目前为止,一个极好的答案是建议更改边缘的定义顺序,并在某些情况下应指定边缘附件的位置进行指定。

在此应用程序中,我确实具有来自统治者树的层次结构嵌套信息,并且可以对边缘进行分类:那些边缘,那些循环,跳转到复合结构末端的边缘,那些破坏循环的边缘,等等。

因此,现在的问题恰恰变成了人们如何利用这些信息来避免那些蛇行的箭头,并确保了越过循环而越过边缘(例如说“ if” /“ else”跳跃边缘)的问题。

感觉就像是VLSI设计:提出了一套适用于每种(控制流)结构的模式,然后这些模式将正确嵌套和排序。

我已经对边缘的排序和放置进行了实验,但是我对何时早晚放置东西没有直觉。

对于结构化控制流边缘的指导或更好的设计规则将不胜感激。

您需要做两件事来改善这种情况:

  • 比其他边缘更早地绘制要控制的边缘(其中之一),
  • 告诉graphviz您要将它们连接到的位置(北,东...)

我已经相应地编辑了您的代码

digraph G {
  mclimit=1.5;
  rankdir=TD; ordering=out;
  graph[fontsize=10 fontname="Verdana"];
  color="#efefef";
  node[shape=box style=filled fontsize=8 fontname="Verdana" fillcolor="#efefef"];
  edge[fontsize=8 fontname="Verdana"];

  node_0 [shape = "oval"][label="Basic Block 0\loffsets: 0..12\lflags=entry, block, unconditional, try\ljumps=[34]\l"];
  node_1 [label="Basic Block 1\loffsets: 14..30\lflags=except, unconditional\ljumps=[38]\l"];
  node_2 [label="Basic Block 2\loffsets: 32..32\lflags=end finally\l"];
  node_3 [label="Basic Block 3\loffsets: 34..36\l"];
  node_4 [label="Basic Block 4\loffsets: 38..40\lflags=no fallthrough\l"];

  node_0 -> node_3:nw [weight=1];           /* moved up and added directions*/
  node_0 -> node_2 [weight=1][color="red"];
  node_3 -> node_4 [weight=10];
  node_0 -> node_1 [weight=1][color="red"];
  node_2 -> node_3 [weight=10];
  node_0 -> node_1 [weight=10][style="invis"];
  node_1 -> node_2 [weight=10][style="invis"];
  node_1:se -> node_4:ne [weight=1];            /* added directions */
}

这给你

在此处输入图片说明

这里涉及到一些反复试验,但是我相信这会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM