簡體   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