Friends, sometimes during an automata keynote, I have to present a string recognition step-by-step example. Please consider the following TikZ code:
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [right=of q_0] {$q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
which outputs the following automaton:
So far so good. Then, for an example, I take a string and show how the execution will happen. Let's say I want to check aab
:
I achieve these slides by manually highlighting the specific parts of my automaton. The full code is as follows:
\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{automata,positioning}
\begin{document}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [right=of q_0] {$q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
\end{frame}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,every initial by arrow/.style={draw=blue},/tikz/initial text=]
\node[state,initial,draw=blue] (q_0) {\color{blue} $q_0$};
\node[state] (q_1) [right=of q_0] {$q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
\end{frame}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [right=of q_0] {$q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge [draw=blue] node {\color{blue} a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
\end{frame}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [draw=blue,right=of q_0] {\color{blue} $q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
\end{frame}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [right=of q_0] {$q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [draw=blue,loop above] node {\color{blue} a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
\end{frame}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [draw=blue,right=of q_0] {\color{blue} $q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
\end{frame}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [right=of q_0] {$q_1$};
\node[state,accepting] (q_2) [right=of q_1] {$q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge [draw=blue] node {\color{blue} b} (q_2);
\end{tikzpicture}
\end{frame}
\begin{frame}{String recognition}
\begin{itemize}
\item \textbf{String:} \texttt{aab}
\end{itemize}
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=]
\node[state,initial] (q_0) {$q_0$};
\node[state] (q_1) [right=of q_0] {$q_1$};
\node[state,accepting,draw=blue] (q_2) [right=of q_1] {\color{blue} $q_2$};
\path[->]
(q_0) edge node {a} (q_1)
(q_1) edge [loop above] node {a} ()
(q_1) edge node {b} (q_2);
\end{tikzpicture}
\end{frame}
\end{document}
As you can see, the drawing is basically the same for every step, apart from the highlighting. I thought of creating a new command called \myautomaton
which takes an integer as parameter, representing the current step. In the drawing definition itself, I tried to use the \ifthenelse
command from the xifthen
package to check if, e.g., state q_0
should be highlighted. Unfortunately, I had some problems, as I tried to insert them like:
\node[state,initial\ifthenelse{#1=2}{,draw=blue}{} ] (q_0) {\ifthenelse{#1=2}{\color{blue}}{}$q_0$};
Anyway, I was wondering if there's any technique to highlight specific parts of a TikZ drawing without so much code repetition. Any ideas?
UPDATE: I'd like to say that all answers to this question are equally awesome! The accepted answer is the one that better suits my needs.
Usually, my automata representations tend to become more and more complex. Besides, the string complexity also follows the model tendency.
When I have several states and transitions, I find the \automaton{}
approach better, as it gives me the flexibility of setting which highlight step I want based on a state number and not on the input string. That way, I can map all the possible highlights in my automaton and call them when needed.
For conventional automata representations, all answers are feasible. Thanks to all the answerers.