5.2. The Acceptance Problem for Turing Machines

We are ready to find an uncomputable problem.

On the preceding page, we asked if it is computable to determine whether a given DFA accepts a given string.

This time, we ask a similar question about a Turing machine (or any program in a sufficiently general model of computing).

Definition. ACCEPTTM = {(‹M›, s) | Turing machine M accepts s}

Theorem. ACCEPTTM is not computable.

Proof. The reasoning is by contradiction. Assume that ACCEPTTM is computable. It will suffice to derive a contradiction.

Since, by assumption, ACCEPTTM is computable, there must be some Turing machine A that solves it. That is,

(1) φA(‹M›, s) = true  ⇔  φM(s) = true

(2) φA(‹M›, s) = false  ⇔  φM(s) ≠ true

Let's build another Turing machine (or, if you prefer, program) F that takes just a Turing machine M as its argument. Since we have A in hand, we can use it to build F.

  F(‹M›)
    If A answers true on input (‹M›, ‹M›) then
      loop forever
    else
      return true
    end if    

Notice

φF(‹M›) answers true
 ⇔  φA(‹M›, ‹M›) ≠ true (*)
 ⇔  φM(‹M›) ≠ true (by fact (1) above)

(*) From inspection of the definition of F and the fact that A must stop on every input.

But that reasoning holds for every M. In particular, it holds when M = F! Substituting M = F into that equivalence yields

φF(‹F›) true  ⇔  φF(‹F›) ≠ true

That is nonsense. No value can be true if and only if it is not true.

That contradiction proves the theorem. ◊

Notice that the proof is actually quite constructive. If you give me a program A that claims to solve ACCEPTTM, then I build F and give you (‹F›, ‹F›) as an input on which A gives the wrong answer, since

F accepts ‹F›  ⇔  A rejects (‹F›, ‹F›)

If F accepts ‹F›, then A says that it doesn't. If F does not accept ‹F›, then A says that it does.