我正在尝试以自动化方式绘制决策图 (DD)。DD 是有向无环图,其中所有节点都按层划分。边通常从第 l 层的一个节点到第 l+1 层的另一个节点。每条边都有一个标签,同一对节点之间可以有多条边。下面有两个示例 DD。这些是通过手动指定所有节点的所有坐标来绘制的。由于我需要绘制大量的 DD,所以我想自动完成这一操作。因此我使用了 tikz 的布局管理器。下面是一个例子:
\RequirePackage{luatex85}
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{graphs,graphdrawing,quotes}
\usegdlibrary{layered}
\begin{document}
\begin{tikzpicture}[rounded corners]
\graph [layered layout,
edge quotes={fill=white,inner sep=1pt,font=\scriptsize,pos=0.2},
nodes={circle,draw,inner sep=.1,outer sep=0, minimum size=.35cm},
level sep=1cm
]
{
r ->["a"] 1,
r ->["b"] 0,
r ->["c"] 2,
r ->["d"] 3,
3 ->["e"] 4,
1 ->["f"] 4,
1 ->["g"] 6,
0 ->["h"] 4,
0 ->["i"] 5,
0 ->["j"] 6,
2 ->["k"] 6,
4 ->["l"] t,
5 ->["m"] t,
6 ->["n"] t;
};
\end{tikzpicture}
\end{document}
上面的代码运行得很好,特别是因为我可以单独指定每个弧。接下来我正在寻找一种方法来执行以下操作:
- 如何指定层之间的垂直空间?答案:使用
level sep=2cm
- 如何在同一对节点之间绘制多条边?在最右边的图中,您会看到具有 2 条边的节点,例如 v2、v4。同一对节点之间可以有 2 条以上的边。绘制的边必须不重叠。例如,如果我在同一对节点之间有 10 条带有不同标签的边,会怎么样?
- 最左边的图表旁边有标签 pi_1、pi_2。这些标签垂直对齐,位于边缘旁边。我该如何添加它们?
注意:我并不想完全复制图中的图形。其他美观的东西就足够了。
答案1
以下解决方案似乎有效:
\RequirePackage{luatex85}
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{graphs,graphdrawing,quotes}
\usegdlibrary{layered}
\begin{document}
\begin{tikzpicture}[rounded corners]
\graph [layered layout,
edge quotes={fill=white,inner sep=1pt,font=\scriptsize},
nodes={circle,draw,inner sep=.1,outer sep=0, minimum size=.35cm},
level sep=1.5cm, %vertical distance between layers
sibling distance=2cm, %distance between nodes of the same connected component in the same layer
component sep=0cm %distance between connected components
]
{
{
[nodes={draw=none,text opacity=0}, edge={draw=none}]
l1 ->["$\pi_1$"] l2 ->["$\pi_2$"] l3 ->["$\pi_3$"] l4,
},
{
[edge={pos=.45}]
r ->["a"] 1,
r ->["b"] 0,
r ->["c"] 2,
r ->["c'",bend left=-20] 2,
r ->["c''",bend left=20] 2,
r ->["d"] 3,
3 ->["e"] 4,
1 ->["f"] 4,
1 ->["g"] 6,
0 ->["h"] 4,
0 ->["i"] 5,
0 ->["j"] 6,
2 ->["k"] 6,
4 ->["l"] t,
5 ->["m"] t,
6 ->["n"] t;
}
};
\end{tikzpicture}
\end{document}
结果:
此解决方案将 pi 标签绘制在左侧作为第二张图。标签会自动对齐。
答案2
这有点取决于你想要什么。如果你只想添加额外的弯曲箭头和圆周率,那很容易。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{graphs,graphdrawing,quotes}
\usegdlibrary{layered}
\begin{document}
\begin{tikzpicture}[rounded corners]
\begin{scope}[local bounding box=graph]
\graph [layered layout,
edge quotes={auto,inner sep=1pt,font=\scriptsize},
nodes={circle,draw,inner sep=.1,outer sep=0, minimum size=.35cm},
level sep=1cm
]
{
r ->["a"] 1,
r ->["b"] 0,
r ->["c"] 2,
r ->["d"] 3,
3 ->["e"] 4,
1 ->["f"] 4,
1 ->["g"] 6,
0 ->["h"] 4,
0 ->["i"] 5,
0 ->["j"] 6,
2 ->["k"] 6,
4 ->["l"] t,
5 ->["m"] t,
6 ->["n"] t;
};
\begin{scope}[nodes={auto,inner sep=1pt,font=\scriptsize}]
\draw[->] (r) to[bend left,"$c'$"] (2);
\end{scope}
\path (r) -- (3) coordinate[pos=0.5] (p1)
(3) -- (4) coordinate[pos=0.5] (p2) (4) -- (t) coordinate[pos=0.5] (p3);
\end{scope}
\foreach \X in {1,2,3}
{\node at ([xshift=-1cm]graph.west|-p\X) {$\pi_{\X}$}; }
\end{tikzpicture}
\end{document}
这样做的好处是输出接近屏幕截图,不好的地方是您需要发出许多此类命令\draw[->] (r) to[bend left,"$c'$"] (2);
(可以使用edge
s 稍微缩短)。
如果您想要更自动化的版本,那么以下内容可能会提供一个起点。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{graphs,graphdrawing,quotes}
\usetikzlibrary{decorations.pathreplacing}
\usegdlibrary{layered}
\tikzset{extra bent arrow/.style={decoration={show path construction,
lineto code={
\draw (\tikzinputsegmentfirst) to[bend left=40,#1]
(\tikzinputsegmentlast);
}},postaction=decorate},
extra straight arrow/.style={decoration={show path construction,
curveto code={
\draw (\tikzinputsegmentfirst) -- node[pos=0.5,auto,font=\scriptsize]{#1}
(\tikzinputsegmentlast);
}},postaction=decorate}}
\begin{document}
\begin{tikzpicture}[rounded corners]
\begin{scope}[local bounding box=graph]
\graph [layered layout,
edge quotes={auto,inner sep=1pt,font=\scriptsize},
nodes={circle,draw,inner sep=.1,outer sep=0, minimum size=.35cm},
level sep=1cm
]
{
r ->["a"] 1,
r ->["b"] 0,
r ->[bend left,"c",extra straight arrow=c1] 2,
r ->["d"] 3,
3 ->["e"] 4,
1 ->["f"] 4,
1 ->["g"] 6,
0 ->["h"] 4,
0 ->["i"] 5,
0 ->["j"] 6,
2 ->["k"] 6,
4 ->["l"] t,
5 ->["m"] t,
6 ->["n"] t;
};
\path (r) -- (3) coordinate[pos=0.5] (p1)
(3) -- (4) coordinate[pos=0.5] (p2) (4) -- (t) coordinate[pos=0.5] (p3);
\end{scope}
\foreach \X in {1,2,3}
{\node at ([xshift=-1cm]graph.west|-p\X) {$\pi_{\X}$}; }
\end{tikzpicture}
\end{document}
我选择该输出是因为它显示了未解决的问题:上图中的线条连接得不太好,而且控制边缘标签更加困难。这两个问题都可以解决,但这需要更多努力。