2008年8月1日

Graphviz 筆記



最近找到 Graphviz 這個 graph drawing tool. 太好用了。


今天才搞懂為什麼有的論文可以畫很複雜的圖了,我還以為要用 Latex 之類來畫哩


◎ Graphviz 的特點就是只要提供 nodes 之間的關係,它就用其 layout 的演算法,將美美的圖畫出來,比如只要寫下面的 Code..
digraph gr { 
a -> b;
a -> c;

d -> e;
d -> f;
}


就幫你畫出下述的圖


graphviz01.png


◎ 當然,就一般簡單的需求,這樣似乎就夠用了,但事實上仍有需要微調的情形,比如上述的圖,加上一個條件,比如
 
c->f


會畫出這樣的圖


graphviz02.png


這樣看起來也蠻合理,但我的需求是要 a, d 兩點對齊,那加 rank=same 的條件,來達到目的,code 如下:
 
digraph gr {
a -> b;
a -> c;

d -> e;
d -> f;
c -> f;

{rank=same; a; d;}
{rank=same; b; c;}
{rank=same; b; f;}
}


分別 (a,d) (b,c) (b,f) 兩兩對齊,現在就可以產生下述的圖:


graphviz03.png


◎ 上面還是有個問題,e, f 兩個節點,順序我並不想換啊...


它錯了嗎?也沒有,因為它的邏輯在於算最小的 edge 距離和最小排序,這樣是最佳解是沒錯的。


另外,有 ordering=out 的 option 可以用,這個選項是指, node 的 output nodes 由左至右排序。


但我加了這個項目後,畫出來的圖也沒變,d node 的兩個 childs 順序也沒變。它錯了嗎?它也沒錯,我猜因為 a->c->f 這條路早於 d->f 這條路先算,所以,f 還是要排左邊。


有解嗎? 有的.. 如下

  • ordering=out 要加

  • 為 e, f 增加一個 pseudo parent,並將 e,f 順序列為該 node 的 childs.  



即增加 ordering=out 的權重,如下圖的 pseudo parent z


graphviz04.png


 這樣 e,f 兩個 nodes 順序就交換過來了,然後,將 z 隱藏起來,並提高 z 的 rank 就成了。


 graphviz051.png


最後的 Code 如下:
 
digraph gr {
ordering = out
a -> b;
a -> c;

d -> e;
d -> f;

c -> f;

{rank=same; a; d;}
{rank=same; b; c;}
{rank=same; b; f;}

z [style=invis];
z -> e [style=invis];
z -> f [style=invis];
{rank=source; z;}
}


◎ 這種只給關係式,然後畫出「可接受」的圖,背後的理論應該蠻有趣,也蠻不容易的。




Orignal From: Graphviz 筆記