CSCI 341 Theory of Computation

Fall 2025, with Schmid

Languages and acceptance

Today, we are going to return to the idea behind a solution space, which consisted of all of the sequences of legal moves that brought our puzzles into a "winning configuration". Just like how sequences of legal moves get abstracted to words, solution spaces are abstracted to languages.

(Language) Let \(A\) be a set of input symbols. A language from \(A\) is a set of words from \(A\). That is, a language is a subset \(L \subseteq A^*\).

The "winning configurations" of automata are the accepting states: in the definition of an automaton \(\mathcal A = (Q, A, \delta, F)\), these are the states \(x \in F \subseteq Q\). So the "solution space" of an automaton is, so to speak, the sequences of input letters that transition whichever state you start from to an accepting state.

(Language Acceptance) Let \(\mathcal A = (Q, A, \delta, F)\) be an automaton, \(x \in Q\) be a state, and \(w \in A^*\) be a word from \(A\). Then \(w\) is accepted (or recognized) by \(x\) if there is an accepting state \(y \in F\) such that \(y \in \delta(x, w)\). The word \(w\) is rejected by \(x\) if it is not accepted by \(x\). The language accepted (or decided) by \(x\) is the set of words accepted by \(x\), \[ \mathcal L(\mathcal A, x) = \big\{ w \in A^* \mid \text{\(x\) accepts \(w\)} \big\} \] If \(\mathcal A\) is clear from context, we will just write \(\mathcal L(x)\) instead of \(\mathcal L(\mathcal A, x)\).

A common turn of phrase you will see written is the statement "\(x\) accepts the language \(L\)". What this means is that \(L = \mathcal L(\mathcal A, x)\).

There are two common mistakes you are going to make at least a few times: the first one is to say that "an automaton accepts a language \(L \subseteq A^*\)". Automata do not accept languages, states do. Remember: states are programs, automata are the machines that can run them.

The second mistake is to say that a state \(x \in Q\) accepts a language \(L \subseteq A^*\) if every \(w \in L\) is accepted by \(x\). This is equivalent to saying that \(\mathcal L(\mathcal A, x) \subseteq L\), not \(\mathcal L(\mathcal A, x) = L\)! The terminology "\(x\) decides \(L\)" is really a lot clearer, but the standard literature usually uses the word "accept". Not sure why. 🙄

Notation. Given two sets \(X\) and \(Y\), we are going to write \(X \setminus Y\) for the set of elements of \(X\) that are not in \(Y\). Formally, \( X \setminus Y = \{x \in X \mid x \notin Y\} \). The set \(X \setminus Y\) is the complement of \(Y\) in \(X\).

(Let 'em Cook) For each of the following languages \(L_i \subseteq A^*\) below, design an automaton \(\mathcal A_i = (Q_i, A, \delta_i, F_i)\) with a state \(x \in Q_i\) such that \(x\) accepts \(L_i\), and briefly explain why your automaton accepts \(L_i\). Note that \(A = \{a, b\}\) in all of the cases below.
  1. \(L_1 = \{a, aa, aaa\}\)
  2. \(L_2 = \{w \in A^* \mid \text{\(w\) ends with \(b\)}\}\)
  3. \(L_3 = \{w \in A^* \mid \text{\(w\) has an even number of \(a\)'s}\}\)
  4. \(L_4 = \{w \in A^* \mid \text{\(w\) has \(3k+1\) many \(a\)'s for some \(k \ge 0\)}\}\)
  5. \(L_5 = \{w \in A^* \mid \text{\(w\) either has \(3k+1\) or \(3k + 2\) many \(a\)'s for some \(k \ge 0\)}\}\)
  6. \(L_6 = A^* \setminus L_2\)
(Cooking Deterministically) For each of the languages in Let 'em Cook, if you drew a nondeterministic or partial automaton, also draw a total deterministic one.
What should you do with the hidden "b"s?

Common descriptions of languages

In the Let 'em Cook problem, we saw some descriptions of languages of the form \[ L = \{w \in A^* \mid \textit{(something that has to be true about \(w\))}\} \] As you have probably gathered so far, the sentence to the right of the \(\mid\) tells you explicitly when a particular \(w \in A^*\) is in \(L\) or not. This method of defining sets is called set comprehension, because you are giving a comprehensive description of which elements are in the set. Set comprehension is the most common way of describing sets of things in general, and it will come up frequently in this course.

(One mod Two) Consider the automaton below with input letters \(A = \{a, b\}\).
Starting from either \(x_0\) or \(x_1\), reading a \(b\) does not change whether or not the word is accepted/rejected. But reading an \(a\) switches from accepting to rejecting: starting from \(x_0\), reading any \(a\) will activate the accepting state, and from \(x_1\) reading an \(a\) will deactivate the accepting state. So, starting from \(x_0\), every word of the form \[ b^{n_1}\ a\ b^{n_2}\ a\ b^{n_3}\ a\ b^{n_4} \] is accepted, where here, \(n_1, n_2, n_3, n_4 \in \mathbb N\). But we also, the words of the form \[ b^{n_1}\ a\ b^{n_2}\ a\ b^{n_3}\ a\ b^{n_4}\ a\ b^{n_5}\ a\ b^{n_6} \] are accepted. It's not feasible to write down the language accepted by \(x_0\) this way, so we use a set comprehension to capture the idea for us. \[ \mathcal L(x_0) = \{w \in A^* \mid \text{\(w\) contains \(2k + 1\) many \(a\)'s}\} \]
(One More Than) Using set comprehension, describe the languages accepted by the states \(x_0\) in the automata below.

Later, we will see a more compact notation for writing down languages.

States as literal programs

Returning to the idea that states of automata are programs, we can implement an automaton reading a string of input letters in any programming language rather easily. Working from the code back to an automaton isn't always as easy.

(Pythonic Automaton I) Go take a look at the Jupyter notebook linked here: (External link to code). This Python program under the Pythonic Automaton I header corresponds to a state in an automaton \(\mathcal A = (Q, A, \delta, F)\) where \(A = \{0,1\}\).
  1. Run the program and test out which of the following strings are accepted/rejected (type "quit" to stop the program):
    • \(1\)
    • \(010\)
    • \(\varepsilon\)
    • \(011011\)
  2. Write down a transition table for \(\mathcal A\) and draw a state diagram of \(\mathcal A\).
  3. Which state does the program correspond to?
  4. Using set comprehension, describe the language accepted by this state.
Make sure to thoroughly test out your state diagram of \(\mathcal A\) against the program.
(Pythonic Automaton II) Write a Python script in the same format as the Pythonic Automaton I (you can use Pythonic Automaton II as a template) that implements the state in the automaton \(\mathcal A_4\) you designed to accept \(L_4\) in Let 'em Cook.
(Pythonic Automaton III) Write a Python script in the same format as the Pythonic Automaton I that implements state \(s_1\) in abstract state diagram (A) from the games and puzzles section. Submit your program as a .py file. In some sense, you just made a Sokoban game!
Top