这是代码:
\begin{center}
\begin{tikzpicture}[
node distance=1.5cm,
every node/.style={draw, fill, circle, inner sep=1.102pt},
endnode/.style={fill=none, inner sep=5pt},
every edge/.style={draw, ->, shorten >=5pt, shorten <=5pt},
itslabel/.style={draw=none, fill=none, above=0pt, pos=0.5, font=\footnotesize},
]
% position the nodes a..d
\node (a) [draw=none,fill=none] {I};
\node (b) [right=of a] {};
\node (c) [above right=of b] {};
\node (d) [above right=of c] {};
\node (e) [right=of d] {};
\node (f) [right=of e] {};
\node (g) [right=of f] {};
\node (gend) [endnode] at (g) {};
\node (h) [below right=of c] {};
\node (i) [right=of h] {};
\node (j) [right=of i] {};
\node (k) [right=of j] {};
\node (l) [right=of k] {};
\node (m) [right=of l] {};
\node (mend) [endnode] at (m) {};
\node (n) [below right=of b] {};
\node (o) [right=of n] {};
\node (p) [right=of o] {};
\node (q) [right=of p] {};
\node (r) [right=of q] {};
\node (s) [right=of r] {};
\node (send) [endnode] at (s) {};
%[shorten >=1em] final
\path (a.center) edge (b)
(b) edge node [itslabel, pos=0.38, above=5pt] {\(\varepsilon\)} (c)
(c.center) edge node [itslabel, pos = 0.4, above = 0.1] {\(\varepsilon\)} (d)
(d) edge node [itslabel] {\(1\)} (e)
(e) edge node [itslabel] {\(\varepsilon\)} (f)
(f) edge [shorten >=1em] node [itslabel] {\(0\)} (g)
(c) edge node [itslabel, pos = 0.32, below = 0.2] {\(\varepsilon\)} (h)
(h) edge node [itslabel] {\(0\)} (i)
(i) edge [shorten >=1em] node [itslabel] {\(\varepsilon\)} (j)
(j) edge node [itslabel] {\(0\)} (k)
(k) edge node [itslabel] {\(\varepsilon\)} (l)
(l) edge [shorten >=1em] node [itslabel] {\(1\)} (m)
(b) edge node [itslabel, pos = 0.32, below = 0.2] {\(\varepsilon\)} (n)
(n) edge node [itslabel] {\(0\)} (o)
(o) edge node [itslabel] {\(\varepsilon\)} (p)
(p) edge node [itslabel] {\(1\)} (q)
(q) edge node [itslabel] {\(\varepsilon\)} (r)
(r) edge [shorten >=1em] node [itslabel] {\(0\)} (s)
(g) edge node [itslabel] {\(\varepsilon\)} (a)
(m) edge node [itslabel] {\(\varepsilon\)} (a)
(s) edge node [itslabel] {\(\varepsilon\)} (a);
\end{tikzpicture}
\end{center}
有人能帮我从第二个图中得到自动机吗?
答案1
使用chains
、fit
和positioning
\quotes` 库,大多数节点都定位在循环中:
\documentclass{article}
\usepackage{geometry}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,
chains,
fit,
positioning,
quotes}
\begin{document}
\begin{center}
\begin{tikzpicture}[
node distance = 12mm and 12mm,
start chain = going right,
arr/.style = {draw, semithick, rounded corners, -Straight Barb},
N/.style = {circle, fill, minimum size=1pt, outer sep=3pt,
node contents={}},
EN/.style = {circle, draw, inner sep=0pt, outer sep=2pt,
fit={#1}, node contents={}},
every edge/.style = {draw, arr},
]
% position the nodes a...d
\coordinate[label=left:I] (a);
\node (b) [N, right=of a];
\node (c) [N, above right=of b];
% position the nodes d...i
\begin{scope}[nodes={on chain}]
\node (d) [N, below right=of c];
\foreach \i in {e, f,...,i}
\node (\i) [N];
\end{scope}
\node (ei) [EN=(i)];
\path (a) edge (b)
(b) edge["$\varepsilon$"] (c)
(c) edge["$\varepsilon$"] (d)
(d) edge["0"] (e)
(e) edge["$\varepsilon$"] (f)
(f) edge["0"] (g)
(g) edge["$\varepsilon$"] (h)
(h) edge["1"] (ei)
;
\draw[arr] (ei) |- ([yshift=45mm] b.north west)
to ["$\varepsilon$" '] (b.north west);
%%%%
\begin{scope}[nodes={on chain}]
\node (j) [N, above right=of c];
\foreach \i in {k, l, m}
\node (\i) [N];
\end{scope}
\node (em) [EN=(m)];
\path (c) edge["$\varepsilon$"] (j)
(j) edge["1"] (k)
(k) edge["$\varepsilon$"] (l)
(l) edge["0"] (em);
\draw[arr] (em) |- ([yshift=42mm] b.north)
to ["$\varepsilon$"] (b);
%%%%
\begin{scope}[nodes={on chain}]
\node (n) [N, below right=of b];
\foreach \i in {o, p,...,s}
\node (\i) [N];
\end{scope}
\node (es) [EN=(s)];
\path (b) edge["$\varepsilon$"] (n)
(n) edge["0"] (o)
(o) edge["$\varepsilon$"] (p)
(p) edge["1"] (q)
(q) edge["$\varepsilon$"] (r)
(r) edge["0"] (es);
\draw[arr] (es) |- ([yshift=-22mm] b.south)
to ["$\varepsilon$"] (b);
\end{tikzpicture}
\end{center}
\end{document}
答案2
我会将\draw
它们分开:
...
(p) edge node [itslabel] {\(1\)} (q)
(q) edge node [itslabel] {\(\varepsilon\)} (r)
(r) edge [shorten >=1em] node [itslabel] {\(0\)} (s);
\draw[->, shorten >=5pt, shorten <=5pt](s)--++(0,-.5)-|node[below,pos=.25,draw=none,fill=none]{$\varepsilon$}(b);
\draw[->, shorten >=5pt, shorten <=5pt](g)--++(0,.5)-|node[above,pos=.25,draw=none,fill=none]{$\varepsilon$}(b.north east);
\draw[->, shorten >=5pt, shorten <=5pt](m)--++(0,3.5)-|node[above,pos=.25,draw=none,fill=none]{$\varepsilon$}(b.north west);
\end{tikzpicture}
有点离题,但这里有一些缩短和简化代码的建议,它们提供更统一的外观并使全局更改变得更容易:
- 使用
tikzset
,以便您可以在tikzpicture
同一个文档中的另一个文档中重复使用您的样式。 outer sep
在节点上使用,而不是缩短所有线路。- 使用 a
scope
作为填充节点,这样every node
就不会影响根节点或边缘节点。 pos
在 中设置 的默认值itslabel
。然后您可以使用itslabel=0.32
设置pos=
,或itslabel
获取默认值(设置为.5
)。- 为了使三行间距均匀,您可以
yshift
向相应的节点添加。
以下是修改后的代码
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\tikzset{
endnode/.style={draw, circle, fill=none, inner sep=5pt, outer sep=3pt},
every edge/.style={draw, ->},
itslabel/.style={above=0pt, pos=#1, font=\footnotesize},
itslabel/.default=.5
}
\begin{document}
\begin{center}
\begin{tikzpicture}[node distance=1.5cm]
\node (a) {I};
% position the nodes a..d
\begin{scope}[every node/.style={draw, fill, circle, inner sep=1pt, outer sep=4pt}]
\node (b) [right=of a] {};
\node (c) [above right=of b] {};
\node (d) [above right=of c, yshift=-.375cm] {};
\node (e) [right=of d] {};
\node (f) [right=of e] {};
\node (g) [right=of f] {};
\node (gend) [endnode] at (g) {};
\node (h) [below right=of c, yshift=.375cm] {};
\node (i) [right=of h] {};
\node (j) [right=of i] {};
\node (k) [right=of j] {};
\node (l) [right=of k] {};
\node (m) [right=of l] {};
\node (mend) [endnode] at (m) {};
\node (n) [below right=of b] {};
\node (o) [right=of n] {};
\node (p) [right=of o] {};
\node (q) [right=of p] {};
\node (r) [right=of q] {};
\node (s) [right=of r] {};
\node (send) [endnode] at (s) {};
\end{scope}
%[shorten >=1em] final
\path (a) edge (b)
(b) edge node [itslabel=0.38, above=5pt] {\(\varepsilon\)} (c)
(c.center) edge node [itslabel=0.4, above = 0.1] {\(\varepsilon\)} (d)
(d) edge node [itslabel] {\(1\)} (e)
(e) edge node [itslabel] {\(\varepsilon\)} (f)
(f) edge [] node [itslabel] {\(0\)} (gend)
(c) edge node [itslabel=0.32, below = 0.2] {\(\varepsilon\)} (h)
(h) edge node [itslabel] {\(0\)} (i)
(i) edge [] node [itslabel] {\(\varepsilon\)} (j)
(j) edge node [itslabel] {\(0\)} (k)
(k) edge node [itslabel] {\(\varepsilon\)} (l)
(l) edge [] node [itslabel] {\(1\)} (mend)
(b) edge node [itslabel=0.32, below = 0.2] {\(\varepsilon\)} (n)
(n) edge node [itslabel] {\(0\)} (o)
(o) edge node [itslabel] {\(\varepsilon\)} (p)
(p) edge node [itslabel] {\(1\)} (q)
(q) edge node [itslabel] {\(\varepsilon\)} (r)
(r) edge [] node [itslabel] {\(0\)} (send);
\draw[->, shorten <=-3pt](send)--++(0,-.5)-|node[itslabel=.25, below]{$\varepsilon$} (b);
\draw[->, shorten <=-3pt](gend)--++(0,.5)-|node[itslabel=.25]{$\varepsilon$}([xshift=1pt]b.north);
\draw[->, shorten <=-3pt](mend)--++(0,3.5)-|node[itslabel=.25]{$\varepsilon$}([xshift=-1pt]b.north);
\end{tikzpicture}
\end{center}
\end{document}
答案3
如果您必须多次使用这种图表,我会通过 TikZ-CD 包使用矩阵来解决这个问题。
我还使用了ext.paths.ortho
来自我的tikz-ext
包的,它允许我们访问路径操作r-du
,r-ud
我将其设置为!du
和!ud
(du
并且ud
在技术上与 TikZ-CD 自己的方向选项相冲突)。这!ud around = <dist>:<node name>
使得绘制变得容易返回箭头围绕另一个节点(这里是另一个ud
箭头的 ε)。
我还设置了宏\e
(用于 ε),\1
并\0
在环境中设置了宏tikzcd
,以便它们充当 等的快捷方式\arrow[r, "\varepisolon"]
(因为大多数箭头似乎都指向右侧的单元格)。可选参数可用于指定不同的目标以及宏接受的所有其他选项\arrow
。
TikZ-CD 自己的end anchor
键允许我们为终点指定变换,而无需我们指定边界上的实际点。
别忘了,你可以把我用过的所有tikzcd
环境选项放在你自己的风格中,比如说
\tikzcdset{
my automaton/.style={
/tikz/d/.style={…},
/tikz/D/.style={…},
create ar shortcuts/.list={\e{"\varepsilon"},\1{"1"},\0{"0"}},
shorten >=+4\pgflinewidth,
arrows={-Latex},
}
}
所以你只需要说
\begin{tikzcd}[my automaton]
…
\end{tikzcd}
而不必重复整个长长的选项列表。
代码
\documentclass[tikz]{standalone}
\usetikzlibrary{cd, calc, ext.paths.ortho}
\tikzset{columns/.style 2 args={
/utils/temp/.style={/tikz/column ##1/.append style={nodes={#2}}},
/utils/temp/.list={#1}}}
\tikzcdset{
/utils/temp/.style args={#1:#2:#3}{
!#1/.style={/tikz/ortho/#1 distance={##1},
/tikz/to path={r-#1(\tikztotarget)\tikztonodes}},
!#1 around/.style args={##1:##2}{
!#1={##1}, /tikz/execute at begin to=
\tikzset{insert path={let \p0=($(##2.#2)-(\tikztostart.#2)$) in},
ortho/#1 distance/.expanded=abs(#30)
+\pgfkeysvalueof{/tikz/ortho/#1 distance}}}},
/utils/temp/.list={ud:north:\y, du:south:\y},
create ar shortcuts/.code n args={2}{%
\providecommand*#1{}\renewcommand*#1[1][r]{\arrow[#2,##1]}}}
\begin{document}
\begin{tikzcd}[
/tikz/d/.style={circle, fill, inner sep=+.2em},
/tikz/D/.style={circle, path only, draw, inner sep=+.4em,
label={[d, yshift=-axis_height]center:}},
columns={2,...,9}{d, yshift=axis_height},
create ar shortcuts/.list={\e{"\varepsilon"},\1{"1"},\0{"0"}},
shorten >=+4\pgflinewidth, arrows={-Latex},
]
& & & \1 & \e & \0 & |[D]| \\
& & \e[ur]\e[dr, swap] \\
I \rar & \e[ur]\e[dr, swap] & & \0 & \e & \0 & \e & \1 & |[D]| \\
& & \0 & \e & \1 & \e & \0 & |[D]| \e[llllllu, !du]
\e[from=1-7, to=3-2, !ud, swap, nodes={name=X}, end anchor={[xshift=2pt]}]
\e[from=3-9, to=3-2, !ud around=2.5mm:X, swap, end anchor={[xshift=-2pt]}]
\end{tikzcd}
\end{document}