2

I got this: enter image description here

But I would like to get that: enter image description here

This is the code:

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

Can anyone help me get the automaton from the second figure?

3
  • You should extend your code fragment to complete small document.
    – Zarko
    Commented Apr 24, 2022 at 13:25
  • I added some suggestions to my answer in case you find them helpful. I know you wanted the vertical spacing of the rows to be even.
    – Sandy G
    Commented Apr 24, 2022 at 13:32
  • If you need an edge that is not covered by the provided by the default to paths, you can always define your own style or just use to path ad hoc with the edge: (s) edge[to path={(\tikztostart.south)--++(down:5mm)-|(\tikztotarget)\tikztonodes}] (a). Commented Jun 18, 2023 at 1:10

3 Answers 3

1

With use of the chains, fit, positioning and \quotes` libraries, most of nodes are positioned in loop:

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

enter image description here

2

I would just \draw them separately:

enter image description here

...
(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}

Somewhat off topic, but here are some suggestions for shortening and simplifying your code, that provide a more uniform look and make global changes much easier:

  • Use tikzset so that you can reuse your styles in another tikzpicture in the same document.
  • Use outer sep on your nodes instead of shortening all your lines.
  • Use a scope for your filled nodes so that every node doesn't affect the root node or edge nodes.
  • Set a default value for pos in itslabel. Then you can use itslabel=0.32 to set pos=, or itslabel to get the default (set to .5).
  • To even the spacing for the three rows, you can add a yshift to the appropriate nodes.

enter image description here

Here is the revised code

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

In case you have to use this kind of diagram more than once, I'd tackle this with a matrix via the TikZ-CD package.

I'm also using the ext.paths.ortho from my tikz-ext package which gives us access to the path operation r-du and r-ud which I setup to be used as !du and !ud (du and ud would conflict technically with TikZ-CD's own directional option). The !ud around = <dist>:<node name> makes it easy to draw a return arrow around another node (here the ε of the other ud arrow).

I've also setup the macros \e (for ε), \1 and \0 inside the tikzcd environment so that they act as shortcuts for \arrow[r, "\varepisolon"] and so on (since the majority of your arrows seem to go to the cell to the right). The optional argument can be used to specify a different target as well as all other options that the \arrow macro accepts.

TikZ-CD's own end anchor key allows us to specify a transformation for the end point without us having to specify the actual point on the border.


Don't forget that you could put all those options that I've used with tikzcd environment in your own style, say

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

so that you only need to say

\begin{tikzcd}[my automaton]
…
\end{tikzcd}

without having to repeat the whole long list of options.

Code

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

Output

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .