如何定位自动机\图形的边缘

如何定位自动机\图形的边缘

我懂了: 在此处输入图片描述

但我想得到的是: 在此处输入图片描述

这是代码:

\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

使用chainsfitpositioning\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在节点上使用,而不是缩短所有线路。
  • 使用 ascope作为填充节点,这样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-dur-ud我将其设置为!du!uddu并且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}

输出

在此处输入图片描述

相关内容