Turing Machines

Turing Machines Algorithms Unsolvability

Turing Machines (TMs)

We saw that finite automata recognize regular languages and pushdown automata recognize context-free languages, but both models have fundamental limitations. The Turing machine, introduced by Alan Turing, removes these limitations by providing an infinite tape that serves as both input and unbounded read/write memory. It is the standard model for defining what it means to compute.

Definition: Turing Machine

A Turing machine is a 7-tuple \((Q, \Sigma, \Gamma, \delta, q_0, q_{\mathrm{accept}}, q_{\mathrm{reject}})\) where \(Q, \Sigma, \Gamma\) are finite sets and

  • \(Q\) is the set of states,
  • \(\Sigma\) is the input alphabet, not containing the blank symbol \(\sqcup\),
  • \(\Gamma\) is the tape alphabet, where \(\sqcup \in \Gamma\) and \(\Sigma \subseteq \Gamma\),
  • \(\delta: Q \times \Gamma \to Q \times \Gamma \times \{L, R\}\) is the transition function,
  • \(q_0 \in Q\) is the start state,
  • \(q_{\mathrm{accept}} \in Q\) is the accept state,
  • \(q_{\mathrm{reject}} \in Q\) is the reject state, where \(q_{\mathrm{accept}} \neq q_{\mathrm{reject}}\).

The key differences between a Turing machine and a finite automaton are:

A Turing machine is strictly more powerful than any finite automaton or pushdown automaton, and is believed to capture the full power of any real computer. By the Church-Turing thesis discussed below, a problem that no Turing machine can solve cannot be solved by any algorithm.

Definition: TM Configuration, Computation, and Acceptance

Let \(M = (Q, \Sigma, \Gamma, \delta, q_0, q_{\mathrm{accept}}, q_{\mathrm{reject}})\) be a Turing machine. A configuration of \(M\) is a triple \((q, t, i)\) consisting of the current state \(q \in Q\), the current tape contents \(t \in \Gamma^{\mathbb{N}}\) (with all but finitely many cells equal to the blank symbol \(\sqcup\)), and the current head position \(i \in \mathbb{N}\). Positions are 1-indexed throughout, in keeping with our convention \(\mathbb{N} = \{1, 2, 3, \ldots\}\).

We write configurations in the linear notation \(u\, q\, v\). This notation means that the tape contents are \(uv\) (followed by infinitely many blanks), the machine is in state \(q\), and the head is positioned on the first symbol of \(v\). If \(v\) is empty, the head is on the blank cell immediately to the right of \(u\). For example, the configuration \(1001\, q_5\, 0110\) represents a tape containing \(10010110\), with \(M\) in state \(q_5\) and the head on the fifth symbol (the first \(0\) after the state label).

Configuration \(C\) yields configuration \(C'\), written \(C \vdash C'\), if \(C'\) is obtained from \(C\) by a single application of \(\delta\) to the current state and the symbol under the head. Such an application writes the new symbol, moves the head one cell left or right, and updates the state. A left move from the leftmost cell leaves the head in place. The relation \(\vdash\) is undefined when the current state is \(q_{\mathrm{accept}}\) or \(q_{\mathrm{reject}}\). Instead, \(M\) halts immediately upon entering either state, regardless of the value of \(\delta\) at that configuration.

The start configuration of \(M\) on input \(w \in \Sigma^*\) is \(q_0 w\) (state \(q_0\), tape contents \(w\) followed by blanks, head on the first symbol of \(w\)). An accepting configuration is any configuration whose state is \(q_{\mathrm{accept}}\), and a rejecting configuration is any whose state is \(q_{\mathrm{reject}}\). We say that \(M\) accepts input \(w\) if there exists a finite sequence of configurations \(C_1, C_2, \ldots, C_k\) with \(C_1\) the start configuration on \(w\), \(C_i \vdash C_{i+1}\) for each index \(i \lt k\), and \(C_k\) accepting. The language recognized by \(M\) is \[ L(M) = \{ w \in \Sigma^* \mid M \text{ accepts } w \}. \]

The machine \(M\) halts on \(w\) if it reaches an accepting or rejecting configuration in finitely many steps, and otherwise it loops on \(w\). It rejects \(w\) if it halts on \(w\) by reaching a rejecting configuration.

Definition: Turing-Recognizable and Turing-Decidable

A language \(L\) is Turing-recognizable (or recursively enumerable) if some Turing machine recognizes it. Such a machine accepts exactly the strings in \(L\). On a string not in \(L\), it may reject or loop forever.

A language \(L\) is Turing-decidable (or simply decidable) if some Turing machine decides it. Such a machine halts on every input, accepting strings in \(L\) and rejecting strings not in \(L\).

For a language \(L\), we call a machine that recognizes \(L\) a recognizer for \(L\), and a machine that decides \(L\) a decider for \(L\). Every decidable language is Turing-recognizable, but the converse does not hold. Some Turing-recognizable languages are not decidable. The distinction hinges on whether the machine is guaranteed to halt.

Example:

Consider the language \[ L_1 = \{0^{2^n} \mid n \geq 0\}, \] which consists of all strings of \(0\)s whose length is a power of 2.

The following Turing machine \(M_1\) decides \(L_1\):

\(M_1 = \) "On input string \(w\):

  1. Read left to right across the tape, crossing out every other \(0\).
  2. If in Stage 1, the tape contained a single \(0\), accept.
  3. If in Stage 1, the tape contained no \(0\), or more than a single \(0\) with the number of \(0\)s odd, reject.
  4. Return the head to the left-hand end of the tape.
  5. Go back to Stage 1."

In the state diagram below, Stage 1's "crossing out every other \(0\)" is realized in two steps. The machine first replaces the leftmost \(0\) with a blank \(\sqcup\), which serves as the left-end marker that the head returns to in Stage 4. It then replaces every other subsequent \(0\) with \(\text{x}\). The trace that follows illustrates exactly this behavior.

Here \(Q = \{q_1, q_2, q_3, q_4, q_5, q_{\mathrm{accept}}, q_{\mathrm{reject}}\}\), \(\Sigma = \{0\}\), and \(\Gamma = \{0, \text{x}, \sqcup\}\). The state diagram of \(M_1\) is as follows:

TM1

For example, if the input is \(0000\), the sequence of configurations is as follows: \[ \begin{align*} &q_1 0 0 0 0 \vdash \sqcup q_2 0 0 0 \vdash \sqcup \text{x} q_3 0 0 \vdash \sqcup \text{x} 0 q_4 0 \\\\ &\vdash \sqcup \text{x} 0 \text{x} q_3 \sqcup \vdash \sqcup \text{x} 0 q_5 \text{x} \sqcup \vdash \sqcup \text{x} q_5 0 \text{x} \sqcup \\\\ &\vdash \sqcup q_5 \text{x} 0 \text{x} \sqcup \vdash q_5 \sqcup \text{x} 0 \text{x} \sqcup \vdash \sqcup q_2 \text{x} 0 \text{x} \sqcup \\\\ &\vdash \sqcup \text{x} q_2 0 \text{x} \sqcup \vdash \sqcup \text{x} \text{x} q_3 \text{x} \sqcup \vdash \sqcup \text{x} \text{x} \text{x} q_3 \sqcup \\\\ &\vdash \sqcup \text{x} \text{x} q_5 \text{x} \sqcup \vdash \sqcup \text{x} q_5 \text{x} \text{x} \sqcup \vdash \sqcup q_5 \text{x} \text{x} \text{x} \sqcup \\\\ &\vdash q_5 \sqcup \text{x} \text{x} \text{x} \sqcup \vdash \sqcup q_2 \text{x} \text{x} \text{x} \sqcup \vdash \sqcup \text{x} q_2 \text{x} \text{x} \sqcup \\\\ &\vdash \sqcup \text{x} \text{x} q_2 \text{x} \sqcup \vdash \sqcup \text{x} \text{x} \text{x} q_2 \sqcup \\\\ &\vdash \sqcup \text{x} \text{x} \text{x} \sqcup q_{\mathrm{accept}}. \end{align*} \]

Multitape Turing Machines

A natural extension of the basic Turing machine model is to allow several tapes, each with its own independent read/write head. Initially the input appears on tape 1, and the remaining tapes start out blank. The transition function is generalized to allow simultaneous reading, writing, and head movement across all tapes.

Definition: Multitape Turing Machine

A multitape Turing machine with \(k\) tapes is a Turing machine whose transition function has the form \[ \delta: Q \times \Gamma^k \to Q \times \Gamma^k \times \{L, R, S\}^k, \] where \(k \geq 1\) is the number of tapes.

The expression \[ \delta(q_i, a_1, \ldots, a_k) = (q_j, b_1, \ldots, b_k, L, R, \ldots, L) \] means that if the machine is in state \(q_i\) and the heads on tapes \(1\) through \(k\) are reading symbols \(a_1\) through \(a_k\), then the machine transitions to state \(q_j\), writes \(b_1\) through \(b_k\) on the corresponding tapes, and directs each head to move left (\(L\)), right (\(R\)), or stay in place (\(S\)) as specified.

Multitape Turing machines appear more powerful than the single-tape model. For instance, a two-tape machine can decide the language \(\{0^k 1^k \mid k \geq 0\}\) in linear time, whereas no single-tape machine can decide it in \(o(n \log n)\) time (a known lower bound whose proof is beyond the scope of this page). Yet in terms of what can be computed (recognizability and decidability), the two models are equivalent.

Theorem: Multitape-Single-Tape Equivalence

Every multitape Turing machine has an equivalent single-tape Turing machine, that is, one that recognizes the same language.

Proof sketch.

Given a \(k\)-tape Turing machine \(M\), we construct a single-tape machine \(T\) that simulates \(M\). The single tape of \(T\) represents the contents of all \(k\) tapes of \(M\) by storing them consecutively, separated by a fresh delimiter symbol \(\#\): \[ \# \, \text{tape}_1 \, \# \, \text{tape}_2 \, \# \, \cdots \, \# \, \text{tape}_k \, \#. \] To track each head's position, \(T\) marks the cell where \(M\)'s head currently sits on each tape with a "dotted" version of that symbol (a new symbol added to the tape alphabet). For instance, if \(M\)'s tape \(i\) contains \(010\) with the head on the middle \(1\), \(T\) records \(\#0\dot{1}0\#\).

On input \(w\), \(T\) first formats its tape into this representation (with \(w\) on tape 1 and the remaining tapes blank). To simulate one step of \(M\), \(T\) scans across its tape from the leftmost \(\#\) to the \((k+1)\)-st \(\#\) to read the symbols under all virtual heads, then makes a second pass to update the contents and head positions according to \(M\)'s transition function.

If a virtual head moves rightward onto a delimiter \(\#\), \(T\) shifts that delimiter, together with all tape contents to its right, one cell further right, and writes a dotted blank in the vacated cell. The virtual head now occupies this fresh blank cell. If a virtual head would move left from the first cell of its tape, \(T\) leaves it in place, following for each tape of \(M\) the convention that a left move from the leftmost cell does not move the head. The machine \(T\) accepts (or rejects) precisely when \(M\) does. Hence \(T\) recognizes the same language as \(M\).

This equivalence justifies our continued use of the single-tape model as the "standard" Turing machine. Multitape machines may be more convenient to design, but they offer no additional computational power. However, when we turn to time complexity, the choice of model does matter. The theorem on single-tape vs. multitape simulation quantifies the time overhead of this simulation.

Algorithms

An algorithm is an effective procedure. By this we mean a finite sequence of precise instructions that, given an input, produces an output in a finite number of steps. Algorithms have been used throughout the history of mathematics, and Euclid's algorithm for the GCD dates to about 300 BCE. Yet the concept was not given a precise mathematical definition until 1936, when Alonzo Church (via the \(\lambda\)-calculus) and Alan Turing (via the Turing machine) independently formalized it.

Thesis: Church-Turing Thesis

Every effective algorithm can be implemented as a Turing machine. Equivalently, any function computable by an algorithm (in the intuitive sense) is computable by a Turing machine.

The thesis is not a theorem in the formal sense, and it cannot be proved, since "algorithm" in the intuitive sense is not a formal concept. It is nevertheless almost universally accepted. The supporting evidence is that every model proposed to capture effective, mechanical computation has turned out to be equivalent to the Turing machine in power. These models include the \(\lambda\)-calculus, recursive functions, and register machines. Later models of computation, such as suitable cellular automata and general-purpose programming languages given unbounded memory, are likewise equivalent.

Now we have a fundamental question: are there problems that no algorithm can solve? The answer is yes. Studying unsolvability is valuable for two reasons. First, recognizing that a problem is algorithmically unsolvable guides us to modify or relax it into a tractable variant. Second, understanding the absolute limits of computation provides deep insight into the structure of problems themselves.

We summarize the key facts about the decidability hierarchy. These results establish the relationships among the language classes we have studied.

Theorem: Decidability Hierarchy
  1. Every context-free language (CFL) is decidable.
  2. Some Turing-recognizable languages are undecidable.
  3. A language \(L\) is decidable if and only if both \(L\) and its complement \(L^c = \Sigma^* \setminus L\) are Turing-recognizable. (A language whose complement is Turing-recognizable is called co-Turing-recognizable. Thus the condition is that \(L\) is simultaneously Turing-recognizable and co-Turing-recognizable.)
Language_Class
Proof sketch.

We sketch each claim in turn.

Claim 1 (every CFL is decidable). Given a CFL \(L\) generated by a context-free grammar \(G\), the membership question "is \(w \in L\)?" can be decided by the Cocke-Younger-Kasami (CYK) algorithm. We assume that \(G\) has been converted into Chomsky Normal Form beforehand. This conversion is a fixed transformation of the grammar, not part of processing the input. The algorithm uses dynamic programming to build up the set of variables that can derive each substring of \(w\), and it accepts if and only if the start variable derives \(w\) itself. The procedure performs \(O(|w|^3)\) table operations and in particular halts on every input, so the Turing machine implementing it decides \(L\).

Claim 2 (some Turing-recognizable languages are undecidable). The canonical example is the acceptance problem \[ A_{\mathrm{TM}} = \{ \langle M, w \rangle \mid M \text{ is a Turing machine that accepts } w \}. \] The language \(A_{\mathrm{TM}}\) is Turing-recognizable. A universal Turing machine takes \(\langle M, w \rangle\) as input, simulates \(M\) on \(w\), and accepts whenever \(M\) accepts. However, \(A_{\mathrm{TM}}\) is undecidable. The proof, a modern form of Turing's diagonal argument, is analogous to the one we develop in the next section. Suppose \(H\) were a decider for \(A_{\mathrm{TM}}\). Let \(D\) be the machine that, on input \(\langle M \rangle\), runs \(H\) on \(\langle M, \langle M \rangle \rangle\) and outputs the opposite answer, rejecting if \(H\) accepts and accepting if \(H\) rejects. Since \(H\) always halts, so does \(D\), and \(D\) accepts \(\langle M \rangle\) exactly when \(M\) does not accept \(\langle M \rangle\). Running \(D\) on its own description \(\langle D \rangle\) then gives that \(D\) accepts \(\langle D \rangle\) if and only if \(D\) does not accept \(\langle D \rangle\), a contradiction.

Claim 3 (decidable if and only if Turing-recognizable and co-Turing-recognizable). (\(\Rightarrow\)) If \(L\) is decidable, a decider \(M\) for \(L\) recognizes \(L\), so \(L\) is Turing-recognizable. Swapping \(q_{\mathrm{accept}}\) and \(q_{\mathrm{reject}}\) in \(M\) yields a decider, hence a recognizer, for \(L^c\). (\(\Leftarrow\)) Suppose \(M_1\) recognizes \(L\) and \(M_2\) recognizes \(L^c\). We build a new Turing machine \(M\) that, on input \(w\), simulates \(M_1\) and \(M_2\) in parallel step by step (advancing each machine by one step in alternation, on a shared input). Since every \(w\) lies in exactly one of \(L\) or \(L^c\), exactly one of \(M_1, M_2\) eventually accepts. The machine \(M\) halts and accepts (resp. rejects) when \(M_1\) (resp. \(M_2\)) accepts. Thus \(M\) decides \(L\).

Modern computers are essentially finite versions of Turing machines. More precisely, they are random-access machines (RAMs) with bounded memory. Any algorithm that runs on a real computer can, in principle, be translated into a Turing machine, although the resulting machine may be inefficient.

Unsolvability

The decidability hierarchy already rules out the possibility that every language is at least recognizable. Since \(A_{\mathrm{TM}}\) is Turing-recognizable but undecidable, item 3 of that theorem shows that its complement is not Turing-recognizable. The main theorem of this section reaches the same conclusion by a counting argument that depends on no particular language. There are languages beyond the reach of any Turing machine whatsoever.

The proof below uses Cantor's diagonalization method, a technique for revealing the limits of any system by constructing an object that disagrees with every candidate the system can produce. We first develop the method in its purest set-theoretic form.

Theorem: Cantor's Theorem (Power Sets)

For any set \(X\), there is no bijection between \(X\) and its power set \(\mathcal{P}(X)\). In particular, \(\mathcal{P}(\mathbb{N})\) is uncountable.

Proof.

Suppose for contradiction that \(f: X \to \mathcal{P}(X)\) is a bijection. Define the set \[ D = \{ x \in X \mid x \notin f(x) \} \in \mathcal{P}(X). \] Since \(f\) is surjective, there exists \(d \in X\) with \(f(d) = D\). Now ask: is \(d \in D\)?

  • If \(d \in D\), then by definition of \(D\) we have \(d \notin f(d) = D\), a contradiction.
  • If \(d \notin D\), then by definition of \(D\) we have \(d \in f(d) = D\), a contradiction.

Either case is contradictory, so no such bijection \(f\) exists. The argument used only the surjectivity of \(f\), so in fact no map \(X \to \mathcal{P}(X)\) is surjective. Taking \(X = \mathbb{N}\) shows that \(\mathcal{P}(\mathbb{N})\) is uncountable. Indeed, by definition a set is countable if and only if it is in bijection with \(\mathbb{N}\) or with a subset of \(\mathbb{N}\). If \(g: S \to \mathcal{P}(\mathbb{N})\) were a bijection with \(S \subseteq \mathbb{N}\), then \(S\) would be nonempty, because \(\mathcal{P}(\mathbb{N})\) is nonempty. Fixing \(s_0 \in S\) and sending every element of \(\mathbb{N} \setminus S\) to \(g(s_0)\) would then extend \(g\) to a surjection \(\mathbb{N} \to \mathcal{P}(\mathbb{N})\), which is impossible.

We now apply the same cardinality contrast to Turing machines. Over a fixed input alphabet, there are, up to renaming of states and auxiliary tape symbols, only countably many machines but, by the theorem above, uncountably many languages.

Theorem: Existence of Non-Recognizable Languages

Some languages are not Turing-recognizable.

Proof.

Fix a nonempty finite alphabet \(\Sigma\). First, we show that, up to renaming, the Turing machines with input alphabet \(\Sigma\) form a countable set. Renaming the states or the tape symbols outside \(\Sigma \cup \{\sqcup\}\) does not change the language a machine recognizes, so we may assume that the states are drawn from a fixed list \(q_1, q_2, \ldots\) and those tape symbols from a fixed list \(\gamma_1, \gamma_2, \ldots\), and we count only such machines. Each such machine \(M\) can then be encoded as a finite string \(\langle M \rangle\) over some fixed finite alphabet \(\Delta\). For instance, we can serialize its 7-tuple specification with appropriate delimiters so that distinct machines produce distinct strings.

The set \(\Delta^*\) of all strings over \(\Delta\) can be written as \[ \Delta^* = \bigcup_{n \geq 0} \Delta^n, \] where \(\Delta^n\) is the set of strings of length \(n\). Each \(\Delta^n\) is finite, so listing the strings of \(\Delta^0\), then those of \(\Delta^1\), and so on, gives a list in which every string of \(\Delta^*\) appears exactly once at a finite position. Hence \(\Delta^*\) is countable. The encoding \(M \mapsto \langle M \rangle\) is injective, so the set of machines we count is in bijection with a subset of \(\Delta^*\), and hence is also countable.

Next, we show that the set of all languages over \(\Sigma\) is uncountable. A language over \(\Sigma\) is, by definition, any subset of \(\Sigma^*\), so the set of all languages is exactly \(\mathcal{P}(\Sigma^*)\). The same listing, applied to \(\Sigma\), enumerates every string of \(\Sigma^*\) exactly once. Since \(\Sigma\) is nonempty, the list is infinite, so it puts \(\Sigma^*\) in bijection with \(\mathbb{N}\). Transporting Cantor's theorem along this bijection, we conclude that \(\mathcal{P}(\Sigma^*)\) is uncountable.

Every Turing-recognizable language over \(\Sigma\) is recognized by one of the machines we count. Indeed, a recognizer whose input alphabet differs from \(\Sigma\) can be converted into one with input alphabet exactly \(\Sigma\): after any auxiliary tape symbol of the original machine that lies in \(\Sigma\) is renamed to a fresh symbol outside \(\Sigma\), the original machine's input symbols outside \(\Sigma\) become auxiliary tape symbols, and a preliminary scan rejects any input containing a symbol of \(\Sigma\) outside the original input alphabet. Since each machine we count recognizes exactly one language over \(\Sigma\), the recognizable languages over \(\Sigma\) are the image of a countable set and therefore form a countable set, while the set of all languages over \(\Sigma\) is uncountable. Hence some language over \(\Sigma\) cannot be recognized by any Turing machine.

Combined with the Church-Turing thesis, this theorem implies that there exist well-defined problems that no algorithm can ever solve. Even among the problems that can be solved, many practically important ones are intractable in the worst case. Such problems can still be addressed through approximation algorithms and heuristics, which find good (if not provably optimal) solutions in reasonable time.

Having established what is and is not computable, we next ask: among the decidable problems, how efficiently can they be solved? This is the subject of time complexity.