如何通过Graphviz的dot引擎生成更紧凑的有向图布局
Graphviz dot布局优化问题
我有一个包含31个节点的有向图,使用Graphviz的dot布局引擎生成的初始布局如下:
我对该布局不满意,因为8-10-20-21四节点簇周围存在大量空白。修改25-21边的方向后,得到了紧凑很多的布局:
问题
- 可以调整哪些设置来优化这类图的布局?
- 推测dot默认倾向于让所有边向下指向,是否可以设置允许部分边向上指向?
对应的dot代码
digraph "" { graph [bgcolor=transparent, dpi=150, fontname=Inconsolata, rankdir=TB, ranksep=0.3, splines=true ]; node [fillcolor=white, shape=box, style=filled, width=0.55 ]; edge [arrowsize=0.7, fontsize="10pt" ]; 1 -> 18; 20 -> 18; 10 -> 20; 18 -> 14; 14 -> 17; 14 -> 21; 14 -> 19; 8 -> 21; 2 -> 27; 3 -> 27; 4 -> 16; 9 -> 31; 9 -> 25; 11 -> 31; 12 -> 30; 13 -> 30; 27 -> 22; 16 -> 20; 16 -> 22; 21 -> 20; 31 -> 25; 31 -> 28; 31 -> 24; 31 -> 26; 25 -> 21; 25 -> 17; 30 -> 28; 30 -> 24; 30 -> 26; 30 -> 29; 30 -> 7; 22 -> 15; 28 -> 23; 24 -> 23; 26 -> 29; 17 -> 6; 29 -> 23; 19 -> 16; 19 -> 5; 15 -> 31; 15 -> 30; 23 -> 22; }
解决方案
一、优化布局的调整设置
- 调整节点与层级间距:当前
ranksep=0.3控制层级间距,可尝试缩小至0.2;新增nodesep=0.2控制同层级节点间距,进一步压缩空白。 - 手动指定节点层级:使用
rank约束将相关节点归到同一层级或指定层级位置,比如针对8-10-20-21簇,添加{rank=same; 8; 10; 20; 21;}强制它们处于同一层级,避免分散;或用rank=min/rank=max指定节点的层级优先级。 - 优化边的样式:将
splines设为ortho(正交边),让边的走向更规整,减少不规则空白;启用concentrate=true合并同方向的边,减少边占用的空间。 - 启用自动紧凑打包:添加
pack=true和packmode=graph,让Graphviz自动紧凑排列图元素,减少冗余空白。 - 尝试不同布局方向:暂时不修改边方向的前提下,将
rankdir改为LR(左右布局),可能会得到更紧凑的横向布局。
二、允许部分边向上指向的设置
- 使用反向边属性:不修改边的逻辑方向,而是在边上添加
dir=back属性。比如将25->21改为21->25 [dir=back],这样视觉上仍显示25指向21,但dot会按21到25的层级关系计算布局,自然允许边向上延伸。 - 强制节点层级关系:通过
rank约束指定节点的层级高低,比如{rank=above; 25;}{rank=below; 21;},强制25处于21的上层,即使边是25->21,dot也会生成向上的边。 - 取消边的层级约束:在特定边上添加
constraint=false,让这条边不参与层级计算,dot可以更灵活地安排节点位置,比如25->21 [constraint=false],允许节点跨层级排列,边自然可能向上。
内容的提问来源于stack exchange,提问作者Changed My Name Again
相关产品推荐
相关产品推荐

