我们可以看到,右侧的转换在指向另一个节点之前“连接在一起”。我该如何用 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)$);
从中右节点和右下节点到由坐标c0
和q_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}