State Machines and Finite Automata
State machines and their state diagrams, runs, deterministic finite automata and their languages, designing automata, and state-transition tables
The topics of this chapter follow the course calendar, and their order follows Kameron Decker Harris’s Fall 2026 lecture notes introducing the theory of computation. These come from those notes:
- the three parts of the theory of computation, computability, complexity and automata theory, with the halting problem and the P versus NP problem as examples of the first two;
- automata as the precise form of “computer”, and the question of whether a machine accepts a string as the precise form of “problem”;
- a state machine drawn as a directed graph, with an arrow into the initial state and a double circle for an accepting state.
These follow the course’s handout on graph extensions:
- a finite automaton seen as a directed graph whose vertices are states and whose labeled edges are transitions, with a start state and accepting states;
- reading a string one symbol at a time, following the edge labeled with each symbol, and accepting the string when the machine ends in an accepting state.
The transition function, runs, the extended transition function, languages, dead states, complements and state-transition tables are added here. The notes do not cover nondeterministic automata or regular expressions, so this chapter does not either. The examples, the exercises, the Racket functions and the proofs are new.
1 State machines
2 Runs
Proof. We show, by induction (Definition: Proof by induction) on \(k = 0, 1, \ldots, n\), that \(r_k = \delta^*(s, x_1 \cdots x_k)\), where \(x_1 \cdots x_0\) is the empty string \(\lambda\).
Base case. For \(k = 0\), \(r_0 = s = \delta^*(s, \lambda)\), by Definition 3 and the base case of Definition 4.
Inductive step. Suppose \(r_{k - 1} = \delta^*(s, x_1 \cdots x_{k - 1})\) for some \(k\) with \(1 \le k \le n\). Then
\[ \begin{aligned} r_k &= \delta(r_{k - 1}, x_k) && \text{(definition of the run)} \\&= \delta\mathopen{}\left(\delta^*(s, x_1 \cdots x_{k - 1}), x_k\right)\mathclose{} && \text{(induction hypothesis)} \\&= \delta^*(s, x_1 \cdots x_{k - 1} x_k). && \text{(recursive rule for } \delta^* \text{)} \end{aligned} \]
By induction, the equation holds for every \(k \le n\), and \(k = n\) gives \(r_n = \delta^*(s, w)\).
Proof. Let \(r_0, \ldots, r_n\) be the run of \(M\) on \(w\) from \(s\).
There is such a walk. For each \(i = 1, \ldots, n\), the state diagram has an edge \(e_i\) from \(r_{i - 1}\) to \(\delta(r_{i - 1}, x_i) = r_i\), labeled \(x_i\). So \(r_0, e_1, r_1, \ldots, e_n, r_n\) is a walk from \(r_0 = s\) whose edges are labeled \(x_1, \ldots, x_n\).
There is only one. Let \(v_0, e_1, v_1, \ldots, e_n, v_n\) be any walk from \(s\) with each \(e_i\) labeled \(x_i\). We show, by induction (Definition: Proof by induction) on \(k\), that \(v_k = r_k\) for \(k = 0, \ldots, n\). For \(k = 0\), \(v_0 = s = r_0\). Suppose \(v_{k - 1} = r_{k - 1}\) for some \(k\) with \(1 \le k \le n\). The edge \(e_k\) starts at \(v_{k - 1} = r_{k - 1}\) and is labeled \(x_k\), and the only such edge in the state diagram goes to \(\delta(r_{k - 1}, x_k) = r_k\). So \(v_k = r_k\). The edge \(e_k\) is that one edge, so the edges of the two walks are the same too.
3 Deterministic finite automata
Proof. Sort the strings over \({\mathopen{}\left\{\mathtt{a}, \mathtt{b}\right\}\mathclose{}}\) into three classes:
- class 0: no two \(\mathtt{a}\)s in a row, and not ending in \(\mathtt{a}\);
- class 1: no two \(\mathtt{a}\)s in a row, and ending in \(\mathtt{a}\);
- class 2: two \(\mathtt{a}\)s in a row somewhere.
Every string is in exactly one class. A string has every \(\mathtt{a}\) immediately followed by a \(\mathtt{b}\) exactly when it is in class 0, since an \(\mathtt{a}\) that is not followed by a \(\mathtt{b}\) is followed either by an \(\mathtt{a}\) (class 2) or by nothing (class 1). Let \(P(w)\) be the statement
\[ \text{if } w \text{ is in class } k, \text{ then } \delta^*(q_0, w) = q_k. \]
We prove \(P(w)\) for every \(w\) by structural induction (Definition: Structural induction) on the recursive definition of strings (Definition: String).
Base case. The empty string \(\lambda\) is in class 0, and \(\delta^*(q_0, \lambda) = q_0\) (Definition 4), so \(P(\lambda)\) holds.
Inductive step. Suppose \(P(w)\), and let \(x \in {\mathopen{}\left\{\mathtt{a}, \mathtt{b}\right\}\mathclose{}}\). By Definition 4, \(\delta^*(q_0, w x) = \delta\mathopen{}\left(\delta^*(q_0, w), x\right)\mathclose{}\). We split into cases on the class of \(w\).
- \(w\) in class 0. By \(P(w)\), \(\delta^*(q_0, w) = q_0\). Since \(w\) does not end in \(\mathtt{a}\), adding \(x\) makes no two \(\mathtt{a}\)s in a row, so \(w x\) has none, as \(w\) has none. If \(x = \mathtt{a}\), then \(w x\) is in class 1, and \(\delta(q_0, \mathtt{a}) = q_1\). If \(x = \mathtt{b}\), then \(w x\) is in class 0, and \(\delta(q_0, \mathtt{b}) = q_0\).
- \(w\) in class 1. By \(P(w)\), \(\delta^*(q_0, w) = q_1\). If \(x = \mathtt{a}\), then \(w x\) ends in two \(\mathtt{a}\)s, so it is in class 2, and \(\delta(q_1, \mathtt{a}) = q_2\). If \(x = \mathtt{b}\), then \(w x\) still has no two \(\mathtt{a}\)s in a row and ends in \(\mathtt{b}\), so it is in class 0, and \(\delta(q_1, \mathtt{b}) = q_0\).
- \(w\) in class 2. By \(P(w)\), \(\delta^*(q_0, w) = q_2\). Then \(w x\) has two \(\mathtt{a}\)s in a row too, so it is in class 2, and \(\delta(q_2, x) = q_2\).
In every case \(\delta^*(q_0, w x) = q_k\) for the class \(k\) of \(w x\), so \(P(w x)\) holds. By structural induction, \(P(w)\) holds for every string \(w\).
Now let \(w\) be any string, in class \(k\). By \(P(w)\), \(\delta^*(q_0, w) = q_k\), and \(A\) accepts \(w\) (Definition 6) exactly when \(q_k \in F = {\mathopen{}\left\{q_0\right\}\mathclose{}}\), that is, when \(k = 0\). So \(A\) accepts exactly the strings of class 0, which are the strings with every \(\mathtt{a}\) immediately followed by a \(\mathtt{b}\).
Proof. The extended transition function \(\delta^*\) (Definition 4) is built from \(S\), \(\Sigma\) and \(\delta\) alone, so \(M\) and \(M'\) have the same \(\delta^*\). Let \(w \in \Sigma^*\). By the language of a DFA (Definition 8) and the definition of accepting (Definition 6),
\[ \begin{aligned} w \in L(M') &\iff M' \text{ accepts } w && \text{(language of a DFA)} \\&\iff \delta^*(s_0, w) \in S \setminus F && \text{(definition of accepting)} \\&\iff \delta^*(s_0, w) \notin F && \text{(since } \delta^*(s_0, w) \in S \text{)} \\&\iff M \text{ does not accept } w && \text{(definition of accepting)} \\&\iff w \notin L(M). && \text{(language of a DFA)} \end{aligned} \]
So \(L(M')\) is the set of strings in \(\Sigma^*\) that are not in \(L(M)\).
The step from \(\delta^*(s_0, w) \in S \setminus F\) to \(\delta^*(s_0, w) \notin F\) uses that \(\delta\) is a function on all of \(S \times \Sigma\), so that \(\delta^*(s_0, w)\) is a state of \(S\) for every string \(w\). Some drawings of automata leave out a dead state (Definition 9) and the arrows into it, so that some states have no arrow for some input. Swapping the accepting states of such a drawing does not give the complement: a string whose run would enter the missing dead state is rejected before and after the swap. Put the dead state back before swapping.






