1

I am trying to draw a FSM in which some of the state nodes contain trees. To achieve this, I am using scopes as suggested in the answer to my last question.

I want to position the state nodes relative to each other, in the hope of getting an image clearly aligned such as this:

nice and tidy looking FSM

But, if I position my state nodes relative to each other, after they are fitted to a scope containing a tree, the content of that scope is not moved with the sorrounding state node.

I tried positioning the scopes themselves like this: \begin{scope}[-, right of=q1, local bounding box=tree2], but it does not seem to work and only causes the nodes to shift to odd positions.

In my current workaround (code pasted below), I am positioning the root node in each of the small trees inside the state nodes relative to another state node, but the result is crooked and ugly:

crooked and ugly FSM

What would be the correct/most pretty way to achieve alignment?

My full code:

\documentclass{scrartcl}

\usepackage{tikz}
\usetikzlibrary{automata, positioning, arrows, fit}

\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background, main, foreground}

\tikzset{
    ->, % makes the edges directed
    >=stealth', % makes the arrow heads bold
    node distance=3cm, % specifies the minimum distance between two nodes. Change if necessary.
    every state/.style={thick, fill=gray!10, inner sep=0}, % sets the properties for each 'state' node
    every scope/.style={level distance = 0.8 cm},    
    initial text=$ $, % sets the text that appears on the start arrow
}

\begin{document}

% The problematic figure
\begin{figure} 
    \begin{tikzpicture}
        \node[state, initial] (q1) {$ \{ q_I \} $};

        \begin{scope}[-, local bounding box=tree2]
        \begin{pgfonlayer}{foreground}        
        \small
            \node[right of=q1] {$ \{ q_I, f \} $}
            child {node {$ \{ q_I \} $}};
        \end{pgfonlayer}        
        \end{scope}

        \node[state, fit=(tree2)] (q2) {};

        \node[state, right of=q2] (q3) {$ \{ f \} $!};


        \begin{scope}[-, local bounding box=tree4]
        \begin{pgfonlayer}{foreground}
        \small
            \node[below of=q3]  {$ \{ q_I, f, g, h, i \} $}
            child {node {$ \{ q_I \} $}}
            child {node {$ \{ f, g, h \} $}
            child {node {$ \{ g \} $}}
            child {node {$ \{ h \} $}}
            };
         \end{pgfonlayer}
         \end{scope}

         \node[state, fit=(tree4)] (q4) {};  

         \node[state, accepting, left of=q4] (q5) {$q_5$};          

        \draw (q1) edge[loop above] node{0} (q1)
              (q1) edge[above] node{1} (q2)
              (q2) edge[loop above] node{1} (q2)
              (q2) edge[bend left, above] node{0} (q3)
              (q3) edge[bend left, below] node{0,1} (q2)
              (q3) edge[bend left, right] node{1} (q4)
              (q4) edge[above] node{0} (q5);
    \end{tikzpicture}
\end{figure}

% How it should look like with "ordinary" state nodes
\begin{figure} 
    \begin{tikzpicture}
        \node[state, initial] (q1) {$ \{ q_I \} $};

        \node[state, right of=q1] (q2) {$q_2$};

        \node[state, right of=q2] (q3) {$ \{ f \} $!};

         \node[state, below of=q3] (q4) {$q_4$};  

         \node[state, accepting, left of=q4] (q5) {$q_5$};          

        \draw (q1) edge[loop above] node{0} (q1)
              (q1) edge[above] node{1} (q2)
              (q2) edge[loop above] node{1} (q2)
              (q2) edge[bend left, above] node{0} (q3)
              (q3) edge[bend left, below] node{0,1} (q2)
              (q3) edge[right] node{1} (q4)
              (q4) edge[above] node{0} (q5);
    \end{tikzpicture}
\end{figure}

\end{document}
1

Everything works as expected in your code, but not as you want it to work. When you are saying

 \node[right of=q1] {$ \{ q_I, f \} $}
        child {node {$ \{ q_I \} $}};

this will place the parent node right of the q1 node, and not the full tree. If you want to place the full tree right of q1, you could for instance store it in a \savebox such that it is safe to be nested.

\documentclass{scrartcl}

\usepackage{tikz}
\usetikzlibrary{automata, positioning, arrows, fit}

\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background, main, foreground}

\tikzset{
    ->, % makes the edges directed
    >=stealth', % makes the arrow heads bold
    node distance=3cm, % specifies the minimum distance between two nodes. Change if necessary.
    every state/.style={thick, fill=gray!10, inner sep=0}, % sets the properties for each 'state' node
    every scope/.style={level distance = 0.8 cm},    
    initial text=$ $, % sets the text that appears on the start arrow
}
\newsavebox\TreeOne
\newsavebox\TreeTwo
\begin{document}
\savebox{\TreeOne}{\tikz[font=\small,-]{\node {$ \{ q_I, f \} $}
            child {node {$ \{ q_I \} $}};}}
\savebox{\TreeTwo}{\tikz[font=\small,-]{\node  {$ \{ q_I, f, g, h, i \} $}
            child {node {$ \{ q_I \} $}}
            child {node {$ \{ f, g, h \} $}
            child {node {$ \{ g \} $}}
            child {node {$ \{ h \} $}}
            };}}
% The problematic figure
\begin{figure} 
    \begin{tikzpicture}
        \node[state, initial] (q1) {$ \{ q_I \} $};

        \node[state,right of=q1] (q2) {\usebox\TreeOne};

        \node[state, right of=q2] (q3) {$ \{ f \} $!};

         \node[state,below of=q3] (q4) {\usebox\TreeTwo};  

         \node[state, accepting, left of=q4] (q5) {$q_5$};          

        \draw (q1) edge[loop above] node{0} (q1)
              (q1) edge[above] node{1} (q2)
              (q2) edge[loop above] node{1} (q2)
              (q2) edge[bend left, above] node{0} (q3)
              (q3) edge[bend left, below] node{0,1} (q2)
              (q3) edge[bend left, right] node{1} (q4)
              (q4) edge[above] node{0} (q5);
    \end{tikzpicture}
\end{figure}

% How it should look like with "ordinary" state nodes
\begin{figure} 
    \begin{tikzpicture}
        \node[state, initial] (q1) {$ \{ q_I \} $};

        \node[state, right of=q1] (q2) {$q_2$};

        \node[state, right of=q2] (q3) {$ \{ f \} $!};

         \node[state, below of=q3] (q4) {$q_4$};  

         \node[state, accepting, left of=q4] (q5) {$q_5$};          

        \draw (q1) edge[loop above] node{0} (q1)
              (q1) edge[above] node{1} (q2)
              (q2) edge[loop above] node{1} (q2)
              (q2) edge[bend left, above] node{0} (q3)
              (q3) edge[bend left, below] node{0,1} (q2)
              (q3) edge[right] node{1} (q4)
              (q4) edge[above] node{0} (q5);
    \end{tikzpicture}
\end{figure}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.