如何使用 TikZ 在自动机中连接边

如何使用 TikZ 在自动机中连接边

这是 Sipser 的《计算理论简介》中的一张图: 在此处输入图片描述

我们可以看到,右侧的转换在指向另一个节点之前“连接在一起”。我该如何用 TikZ 绘制这样的自动机?谢谢!

编辑:这是我正在研究的类似自动机的代码:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata,positioning,arrows.meta,shapes}
\def\eps{\varepsilon}
\def\a{\texttt{a}}
\begin{document}
\begin{tikzpicture}[>={Stealth[width=6pt,length=9pt]}, accepting/.style={double distance = 2pt, outer sep = 1pt + \pgflinewidth}, shorten >=1pt, auto]
\draw (0.0pt, -40.0pt)node[state, initial, initial text =,ellipse](0){$q_{\rm start}$};
\draw (0.0pt, -110.0pt)node[state](1){};
\draw (0.0pt, -180.0pt)node[state,ellipse](2){$q_{\rm loop}$};
\draw (0.0pt, -400.0pt)node[state, accepting,ellipse](3){$q_{\rm accept}$};
\draw (200.0pt, -150.0pt)node[state](4){};
\draw (350.0pt, -150.0pt)node[state](5){};
\draw (200.0pt, -200.0pt)node[state](6){};
\draw (350.0pt, -200.0pt)node[state](7){};
\draw (200.0pt, -250.0pt)node[state](8){};
\draw (350.0pt, -250.0pt)node[state](9){};
\path[->] (2) edge[loop left] node[align=center]{\a, \a; $\eps$\\ +, +; $\eps$\\ (, (; $\eps$\\ ), ); $\eps$\\ $\times$, $\times$; $\eps$\\ $\eps$, $F$; \a\\ $\eps$, $E$; $T$\\ $\eps$, $T$; $F$}(2);
\path[->] (7) edge node{$\eps$, $\eps$; $T$}(2);
\path[->] (2) edge node{$\eps$, $E$; $T$}(4);
\path[->] (9) edge node{$\eps$, $\eps$; (}(2);
\path[->] (4) edge node{$\eps$, $\eps$; +}(5);
\path[->] (6) edge node{$\eps$, $\eps$; $\times$}(7);
\path[->] (2) edge node{$\eps$, \$; $\eps$}(3);
\path[->] (5) edge node{$\eps$, $\eps$; $E$}(2);
\path[->] (2) edge node{$\eps$, $F$; )}(8);
\path[->] (0) edge node{$\eps$, $\eps$; \$}(1);
\path[->] (1) edge node{$\eps$, $\eps$; $E$}(2);
\path[->] (2) edge node{$\eps$, $T$; $F$}(6);
\path[->] (8) edge node{$\eps$, $\eps$; $E$}(9);
\end{tikzpicture}
\end{document}

这个输出的右侧相当混乱。 在此处输入图片描述

答案1

没有简单的方法吗?看这里:弯曲的线和三条线的连接边:

\documentclass{scrartcl}

\usepackage{tikz}
\usetikzlibrary{arrows.meta, intersections, automata, shapes, positioning, calc}

\begin{document}
    \begin{tikzpicture}
        [
            state/.style = {circle, draw, inner sep = 0cm, minimum size = 10pt},
            tip/.style = {
                ->,
                >={Stealth[width=6pt,length=9pt]}
            },
            rtip/.style = {
                <-,
                >={Stealth[width=6pt,length=9pt]}
            }
        ]
        \node[state,ellipse, inner sep = 3pt] (start) {$q_\mathrm{loop}$};
        \node[state, above right = 2cm and 4cm of start](ll){};
        \node[state, right = of ll] (lr) {};
        \node[state, above = of ll] (ml) {};
        \node[state, right = of ml] (mr) {};
        \node[state, above = of ml] (ul) {};
        \node[state, right = of ul] (ur) {};

        \draw[rtip] (ll) -- ++(-2, 0) -- (start);
        \draw[rtip] (ml) -- ++(-2, 0) -- (start);
        \draw[rtip] (ul) -- ++(-2, 0) -- (start);
        \draw[tip] (ll) -- (lr);
        \draw[tip] (ml) -- (mr);
        \draw[tip] (ul) -- (ur);
        \draw[tip] (ur) -| ($(start.east -| lr.east)+(2, 1.5)$) coordinate (c0) -- (start.east);
        \draw[tip] (mr) -| ($(c0)!0.1!(start.east)$);
        \draw[tip] (lr) -| ($(c0)!0.2!(start.east)$);
    \end{tikzpicture}
\end{document}

我简化了你的代码,只显示相关问题,这是你应该做的。不仅对我们,对你也是如此。你提到你的输出“​​一团糟”。通过简化问题,你可以领先于此类事情,所以这真的是为了,不适合我们(对我们来说也很好,很多人更愿意帮助结构良好的问题。我也是这样的人,但你的代码太乱了,我不得不回答)(*)。请参阅我的示例(我敢说)好的 tikz 代码。我使用的代码很少明确的定位,它不会滥用绘制命令来放置节点,您对边的使用是无稽之谈(请阅读手册了解它们的需要)。

对于实际问题的绘制:它充分利用了库calc。第一行:

    \draw[tip] (ur) -| ($(start.east -| lr.east)+(2, 1.5)$) coordinate (c0) -- (start.east);

从右上方节点 ( ur) 开始,绘制到由 -节点的 y 分量q_loop和 -节点的 x 分量定义的点ur,向右移动 2cm,向上移动 1.5cm。既然我使用了移位,为什么还要分别指定 x 和 y 部分呢?如果您移动某个节点,这将跟踪正确的点。最后,绘制到节点。

接下来的两行:

\draw[tip] (mr) -| ($(c0)!0.1!(start.east)$);
\draw[tip] (lr) -| ($(c0)!0.2!(start.east)$);

从中右节点和右下节点到由坐标c0q_loop-节点定义的线绘制一条线。!0.1!!0.2!distance modifier和 调整以使其适合。

结果如下: 绘画

*:有些人可能会说我粗鲁,但这并不是故意粗鲁。这真的是建议。处理这类事情需要有一个好的方法,复杂性并不是失败的借口。改编自手册页xxd:“完全为了你自己的乐趣而使用。阅读手册。画画。成为一名巫师。”如果你觉得某件事可以做,那么它可能可以在 tikz 中实现。

答案2

matrix使用节点定位和定义用于绘制边的坐标的示例 -使用 TikZ 库来标记边quotes

在此处输入图片描述

完整的 MWE:

\documentclass[tikz, margin=7pt]{standalone}
\usetikzlibrary{arrows.meta, automata, chains, calc, matrix, quotes, shapes}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{mathtools}

\begin{document}
    \begin{tikzpicture}[
            > = {Stealth[width=5pt,length=9pt]},
accept/.style = {draw, double distance = 2pt, outer sep = 1pt + \pgflinewidth},
                auto
                        ]
\matrix (m) [matrix of nodes,
             nodes={ellipse, inner sep=2pt, minimum size=1ex},
             nodes in empty cells,
             row sep=9mm, column sep=17mm]
         column 5/.append style={column sep=5mm},
         column 6/.append style={column sep=5mm},
         column 7/.append style={column sep=5mm},             
         ]
{        
\node (m1) [draw,initial,initial text=] {$q_{\text{start}}$};
            &   &                       &                       &   &   &   \\
            &   & \node[draw] (m5) {};  & \node[draw] (m6)  {}; &   &       &   \\

\node (m2) [draw] {};   
            &   & \node[draw] (m7) {};  & \node[draw] (m8)  {}; &   &       &   \\
            &   & \node[draw] (m9) {};  & \node[draw] (m10) {}; &   &       &   \\
\node (m3) [draw] {$q_{\text{loop}}$};  
            &   &                       &                       &   &       &   \\
            &   &                       &                       &   &       &   \\
\node (m4) [accept] {$q_{\text{accept}}$};
            &   &                       &                       &   &       &   \\
};
%
\draw[->]   (m1) edge ["${\epsilon, \epsilon; \$}$"]    (m2)
            (m2) edge [pos=0.25,"{$\epsilon$, $\epsilon$; $E$}"] (m3)
            (m3) edge ["{$\epsilon$, \$; $\epsilon$}"]  (m4)
%
            (m5) edge ["{$\epsilon$, $\epsilon$; +}"]   (m6)
            (m7) edge ["{$\epsilon$, $\epsilon$; $\times$}"]    (m8)
            (m9) edge ["{$\epsilon$, $\epsilon$; $E$}"]  (m10);
% right loops out
\draw[->]   (m3) -- (m-2-2.center) to ["{$\epsilon, E; T$}"]   (m5);
\draw[->]   (m3) -- (m-3-2.center) to ["{$\epsilon, T; F$}"]   (m7);
\draw[->]   (m3) -- (m-4-2.center) to ["{$\epsilon, F; )$}"]   (m9);
% right loops in
\draw[->]   (m6)  to ["{$\epsilon,\epsilon;E$}"] (m-2-5.center) -- (m-2-7.center) |- (m3);
\draw[->]   (m8)  to ["{$\epsilon,\epsilon;T$}"] (m-3-5.center) -- (m-3-6.center) -| (m-5-6.center);
\draw[->]   (m10) to ["{$\epsilon,\epsilon;( $}"] (m-4-5.center) -| (m-5-5.center);
% left loop
\draw[->]   (m3) edge [loop left] node[left,align=right]   {%
                    \texttt{a}, \texttt{a}; $\epsilon$\\
                    $+$, $+$; $\epsilon$\\
                    (, (; $\epsilon$\\ ), ); $\epsilon$\\
                    $\times$, $\times$; $\epsilon$\\
                    $\epsilon$, $F$; \texttt{a}\\
                    $\epsilon$, $E$; $T$\\
                    $\epsilon$, $T$; $F$}  ();

\end{tikzpicture}
\end{document}

答案3

我猜测没有简单的出路,所以我想出了一个非常非常人为的解决方案,但它效果很好:

\begin{tikzpicture}[>={Stealth[width=6pt,length=9pt]}, accepting/.style={double distance = 2pt, outer sep = 1pt + \pgflinewidth}, auto]
\draw (0.0pt, 0.0pt)node[state, initial, initial text =,ellipse](0){$q_{\rm start}$};
\draw (0.0pt, -70.0pt)node[state,minimum size=6pt](1){};
\draw (0.0pt, -140.0pt)node[state,ellipse](2){$q_{\rm loop}$};
\draw (0.0pt, -280.0pt)node[state, accepting,ellipse](3){$q_{\rm accept}$};
\coordinate (ph4) at (50.0pt, -25.0pt);
\draw (2) -- (ph4);
\coordinate (ph6) at (50.0pt, -50.0pt);
\draw (2) -- (ph6);
\coordinate (ph8) at (50.0pt, -75.0pt);
\draw (2) -- (ph8);
\draw (150.0pt, -25.0pt)node[state,minimum size=6pt](4){};
\draw (250.0pt, -25.0pt)node[state,minimum size=6pt](5){};
\draw (150.0pt, -50.0pt)node[state,minimum size=6pt](6){};
\draw (250.0pt, -50.0pt)node[state,minimum size=6pt](7){};
\draw (150.0pt, -75.0pt)node[state,minimum size=6pt](8){};
\draw (250.0pt, -75.0pt)node[state,minimum size=6pt](9){};

\path[->] (2) edge[loop left] node[align=center]{\a, \a; $\eps$\\ +, +; $\eps$\\ (, (; $\eps$\\ ), ); $\eps$\\ $\times$, $\times$; $\eps$\\ $\eps$, $F$; \a\\ $\eps$, $E$; $T$\\ $\eps$, $T$; $F$}(2);

\path[->] (ph4) edge node{$\eps$, $E$; $T$}(4);
\path[->] (4) edge node{$\eps$, $\eps$; +}(5);
\path[->] (6) edge node{$\eps$, $\eps$; $\times$}(7);
\path[->] (2) edge node{$\eps$, \$; $\eps$}(3);
\path[->] (ph8) edge node{$\eps$, $F$; )}(8);
\path[->] (0) edge[left] node{$\eps$, $\eps$; \$}(1);
\path[->] (1) edge[left] node{$\eps$, $\eps$; $E$}(2);
\path[->] (ph6) edge node{$\eps$, $T$; $F$}(6);
\path[->] (8) edge node{$\eps$, $\eps$; $E$}(9);

\coordinate (ph5) at (350.0pt, -25.0pt);
\path[-] (5) edge node{$\eps$, $\eps$; $E$}(ph5);
\coordinate (ph7) at (330.0pt, -50.0pt);
\path[-] (7) edge node{$\eps$, $\eps$; $T$}(ph7);
\coordinate (ph9) at (310.0pt, -75.0pt);
\path[-] (9) edge node{$\eps$, $\eps$; (}(ph9);

\coordinate (phjoin) at (350.0pt, -100.0pt);
\draw (ph5) -- (phjoin);
\path[->] (phjoin) edge (2);
\path[->] (ph7) edge (intersection of 2--phjoin and 330.0pt,0.0pt--330.0pt,-10.0pt);
\path[->] (ph9) edge (intersection of 2--phjoin and 310.0pt,0.0pt--310.0pt,-10.0pt);
\end{tikzpicture}

最终稿

相关内容