使用 Tikz 和布局管理器绘制决策图

使用 Tikz 和布局管理器绘制决策图

我正在尝试以自动化方式绘制决策图 (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}

上面的代码运行得很好,特别是因为我可以单独指定每个弧。接下来我正在寻找一种方法来执行以下操作:

  1. 如何指定层之间的垂直空间?答案:使用level sep=2cm
  2. 如何在同一对节点之间绘制多条边?在最右边的图中,您会看到具有 2 条边的节点,例如 v2、v4。同一对节点之间可以有 2 条以上的边。绘制的边必须不重叠。例如,如果我在同一对节点之间有 10 条带有不同标签的边,会怎么样?
  3. 最左边的图表旁边有标签 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);(可以使用edges 稍微缩短)。

如果您想要更自动化的版本,那么以下内容可能会提供一个起点。

\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}

在此处输入图片描述

我选择该输出是因为它显示了未解决的问题:上图中的线条连接得不太好,而且控制边缘标签更加困难。这两个问题都可以解决,但这需要更多努力。

相关内容