For any sets \(A\) and \(B\), we say \(|A| \ge |B|\) if and only if there exists an onto function \(f: A \to B\).
The following theorem changed the course of science:
Theorem: Let \(X\) be any set. Then there is no onto function \(f: X \to \powerset(X)\).
Proof:
Let \(f: X \to \powerset(X)\); we must show that \(f\) is not onto.
This means we must show that for some \(D \subseteq X\), for all \(a \in X\), \(f(a) \ne D\).
Define the set: \[ D = \setbuild{a \in X}{a \notin f(a)} \]
This is weird/tricky to parse but it’s well defined!
Let \(a \in X\) be arbitrary. Since \(D \in \powerset(X)\), it suffices to show that \(D \ne f(a)\).
By the definition of \(D\), \(a \in D \iff a \notin f(a)\).
Therefore, \(D \ne f(a)\), so \(f\) is not onto.
| 0 | 1 | 2 | 3 | \(\cdots\) | k | |
|---|---|---|---|---|---|---|
|
\(f(0) = \{1, 3, \ldots\}\)
Each cell value indicates whether the “column element” is in the set. |
0 | 1 | 0 | 1 | \(\cdots\) | |
| \(f(1) = \{0, 1, 2, 3 \ldots\}\) | 1 | 1 | 1 | 1 | \(\cdots\) | |
| \(f(2) = \{2, \ldots\}\) | 0 | 0 | 1 | 0 | \(\cdots\) | |
| \(f(3) = \{0, 2, \ldots\}\) | 1 | 0 | 1 | 0 | \(\cdots\) | |
|
|
\(\ddots\) | |||||
|
\(f(k) = D\)
Row \(k\) (corresponding to \(D\)) is constructed by taking each diagonal element and flipping it! |
1 | 0 | 0 | 1 | \(\cdots\) |
??
Assigning a value to \((k, k)\) using this rule is impossible! |
We can also claim \(D\) can’t be on this table since it differs from every row.
A set \(X\) is countable if \(|X| \le |\N|\). There are two possible cases:
A set \(X\) is uncountable if \(|X| > |\N|\).
In other words: a set is countable if it can be enumerated, \[ X = \{x_0, x_1, x_2, \ldots\} \] so that any given element can be found at some finite index \(n\).
This enumeration implicitly defines an onto function
\(f: \N \to X\).
Observation: \(\powerset(\N)\) is uncountable.
Finally getting back to computation:
Observation: There exist undecidable languages \(L \subseteq \binary^*\).
Proof:
But we still haven’t proved any specific language to be undecidable!
We are finally ready for Turing’s diagonalization argument proving the undecidability of:
\[ \probHALT = \setbuild{\encoding{M, w}}{M \text{ is a Turing machine that halts on } w} \]
Theorem: \(\probHALT\) is undecidable.
Proof:
Assume for contradiction that \(\probHALT\) is decidable by the algorithm:
def H(M, w): raise NotImplementedError()
Define the following algorithm (analogous to the set \(D\) we constructed earlier):
import inspect
def D(M):
M_src = inspect.getsource(M)
if H(M, M_src):
while True: pass # Loop forever
else:
return # Halt
D loops if TM \(M\) halts on \(\encoding{M}\) (if \(\encoding{M, \encoding{M}} \in \probHALT\)),
and halts if TM \(M\) loops on \(\encoding{M}\) (if \(\encoding{M, \encoding{M}} \notin \probHALT\)).
Theorem: \(\probHALT\) is undecidable.
Proof:
Assume for contradiction that \(\probHALT\) is decidable by the algorithm:
def H(M, w): raise NotImplementedError()
Define the following algorithm (analogous to the set \(D\) we constructed earlier):
def D(M):
if H(M, inspect.getsource(M)):
while True: pass # Loop forever
else: return # Halt
D loops if TM \(M\) halts on \(\encoding{M}\) (if \(\encoding{M, \encoding{M}} \in \probHALT\)),
and halts if TM \(M\) loops on \(\encoding{M}\) (if \(\encoding{M, \encoding{M}} \notin \probHALT\)).
D(D) do?
D halts on itself, then H(D, D_src) returns True, so D loops forever (a contradiction!).D loops on itself, then H(D, D_src) returns False, so D halts (a contradiction!).H must not exist, so \(\probHALT\) is undecidable!def D(M):
if H(M, inspect.getsource(M)):
while True: pass # Loop forever
else: return # Halt
Expressing the previous argument in Turing machine notation:
\[\begin{align*} D \text{ halts on }& \encoding{D} \\ &\iff H \text{ accepts }\encoding{D, \encoding{D}} \quad \quad \color{green} (\text{Since } H \text{ solves }\probHALT) \\ &\iff D \text { loops on } \encoding{D} \quad \quad \quad \; \; \, \color{green} (\text{Implementation of } D) \end{align*}\]
This argument doesn’t just show \(H\) can’t analyze this weird algorithm \(D\).
It shows \(H\) itself cannot exist!
Let’s consider the (countable) set of all Turing machines and try running each on
strings that encode Turing machines.
These inputs probably don’t make sense, but the TMs will nonetheless either loop or halt.
We can organize the results in a table:
| \(\encoding{M_0}\) | \(\encoding{M_1}\) | \(\encoding{M_2}\) | \(\encoding{M_3}\) | \(\cdots\) | \(\encoding{D}\) | |
|---|---|---|---|---|---|---|
| \(M_0\) | loop | halt | loop | halt | \(\cdots\) | |
| \(M_1\) | halt | halt | halt | halt | \(\cdots\) | |
| \(M_2\) | loop | loop | halt | loop | \(\cdots\) | |
| \(M_3\) | halt | loop | halt | loop | \(\cdots\) | |
| \(\;\,\vdots\) | \(\ddots\) | |||||
| \(D\) | halt | loop | loop | halt | \(\cdots\) | ?? |
The row for machine \(D\) is constructed by taking each diagonal result and flipping it!
Assigning a value to \((D, \encoding{D})\) using this rule is impossible!