[Tex/LaTex] Highlighting specific parts of a TikZ drawing

highlightingtikz-pgf

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:

Automaton 1

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:

Image 1
Image 2

Image 3
Image 4

Image 5
Image 6

Image 7
Image 8

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.

Best Answer

fabikw's answer is excellent if you're working with beamer. In order to get this working in a non-beamer application, I would use a /.code key to check whether the id of a part of the drawing is equal to the current step number, and set the color accordingly.

Here's one way of doing that:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata}

\begin{document}

\newif\ifhighlight
\tikzset{
    highlight/.is if=highlight,
    highlight=false,
    step number/.initial=0
}

\pgfkeys{
    /tikz/id/.code={
        \pgfmathparse{ifthenelse(#1==\pgfkeysvalueof{/tikz/step number},"true","false")}
        \pgfkeys{/tikz/highlight=\pgfmathresult}
        \ifhighlight
            \tikzset{
                orange!60!red,
            }
        \fi
    }
}


\newcommand{\automaton}[1]{
\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto,/tikz/initial text=,step number=#1,] 
   \begin{scope}[id=1]  % Necessary to colour the initial arrow
   \node[initial,state] (q_0)   {$q_0$};
   \end{scope}
   \node[state,id=3] (q_1) [right=of q_0] {$q_1$}; 
   \node[state,accepting,id=6] (q_2) [right=of q_1] {$q_2$}; 
    \path[->] 
    (q_0) edge [id=2] node [id=2] {a} (q_1)
    (q_1) edge [loop above,id=4] node {a} ()
    (q_1) edge [id=5] node {b} (q_2);
\end{tikzpicture}
}

\automaton{1}

\automaton{2}

\automaton{3}

\automaton{4}

\automaton{3}

\automaton{5}

\automaton{6}
\end{document}