Title

ECS 120 Theory of Computation
Undecidability: More Undecidable Problems
Julian Panetta
University of California, Davis

Review: No-input halting problem is undecidable

Simple example of a Turing reduction:
showing that the no-input Halting problem is undecidable

\[ \probHALT_\emptystring = \setbuild{\encoding{M}}{M \text{ is a Turing machine and } M(\emptystring) halts} \]

Theorem: \(\probHALT_\emptystring\) is undecidable.

Proof:

  • Suppose that \(\probHALT_\emptystring\) is decidable by an algorithm:

    from typing import Callable
    def H_๐œ€(M: Callable[[str], bool]) -> bool: raise NotImplementedError()
  • We can use this to decide \(\probHALT\) as follows:

    def H(M: Callable[[str], bool], w: str) -> bool:
        # Create a new algorithm T_Mw that ignores its input
        # and has the original input w "hardcoded".
        def T_Mw(x: str) -> bool:  # This is algorithm is never actually run!!!
            M(w)                   # Executing these lines merely *defines* T_Mw.
        return H_๐œ€(T_Mw)           # ... but instead is *analyzed* by H_๐œ€.
  • If M(w) halts, then:
    • T_Mw halts on every input (including \(\emptystring\)).
    • So H_๐œ€(T_Mw)returns True.
  • If M(w) loops (doesnโ€™t halt), then:
    • T_Mw loops on every input (including \(\emptystring\)).
    • So H_๐œ€(T_Mw) returns False.
  • Therefore H decides \(\probHALT\), a contradiction.

Undecidability of algorithm โ€œbehaviorโ€: General recipe

  • The previous argument follows a pattern we will use to show that many other questions we might ask about an algorithmโ€™s eventual behavior are undecidable.

  • We prove that an algorithm \(A\) deciding that other question cannot exist by showing it can be used to solve the Halting problem.

  • We will use it to solve \(\probHALTe\), which is slightly more convenient than \(\probHALT\). (one fewer variable)

  • The steps to construct an algorithm for \(\probHALTe\) are:

    1. Take as input an arbitrary Turing machine/Python function \(M\); we want to know if \(M(\varepsilon)\) halts.
    2. Construct a new Turing machine \(T_M\) that:
      1. Runs \(M(\emptystring)\).
      2. Has opposite โ€œbehaviorโ€ (that \(A\) is looking for) if \(M(\emptystring)\) halts than if it does not halt.
    3. Pass \(T_M\) to algorithm \(A\); use the result to decide if \(M(\emptystring)\) halts.
  • We did (essentially) this when reducing \(\probHALT\) to \(\probHALTe\) by:

    1. Taking as input \((M,w)\).
    2. Constructing \(T_{M,w}\) that ignores its input and runs \(M(w)\).
    3. Passing \(T_{M,w}\) to hypothetical decider for \(\probHALTe\), noting \(T_{M,w}(\emptystring)\) halts if and only if \(M(w)\) halts, tying the โ€œbehaviorโ€ of \(\probHALT\) (\(M(w)\) halting or not) to the โ€œbehaviorโ€ of \(\probHALTe\) (\(T_{M,w}(\emptystring)\) halting or not).

More undecidable problems: Acceptance problem

Letโ€™s apply this recipe to the following problem:

\[ \probAccepts = \setbuild{\encoding{M, w}}{M \text{ is a Turing machine that accepts } w} \]

Theorem: \(\probAccepts\) is undecidable.

Proof:

  • Suppose that \(\probAccepts\) is decidable by alg. A:

    def A(M, w): raise NotImplementedError()
  • We can use A to decide \(\probHALTe\) as follows:

    def H_๐œ€(M):
        # Create a new algorithm T_M that accepts any input
        # if and only if M halts on the empty string.
        def T_M(w):          # Input is ignored!
            M('')
            return True
        return A(T_M, '011') # Analyze T_M using hypothetical decider A
  • If M('') halts, then:
    • T_M accepts all inputs (including \(011\)).
    • So A(T_M, w) and H_๐œ€ return True.
  • If M('') loops (does not halt), then:
    • T_M never reaches the return, so accepts no inputs (including \(011\)).
    • So A(T_M, w) and H_๐œ€ return False.
  • Formally: \[ \begin{aligned} M(\emptystring) \text{ halts } &\iff T_M \text{ accepts } \string{011} \\ &\iff A \text{ accepts } \encoding{T_M, 011} \\ &\iff H_๐œ€ \text{ accepts } \encoding{M} \end{aligned} \]
  • Therefore H_๐œ€ decides \(\probHALTe\),
    a contradiction.

More undecidable problems: Empty language problem

\[ \probEmpty = \setbuild{\encoding{M}}{M \text{ is a Turing machine and } L(M) = \emptyset} \]

In other words: \(M\) accepts no inputs.

Theorem: \(\probEmpty\) is undecidable.

Proof:

  • Suppose that \(\probEmpty\) is decidable by algorithm E:

    def E(M): raise NotImplementedError()
  • We can use E to decide \(\probHALTe\) as follows:

    def H_๐œ€(M):
        # Create a new algorithm that accepts a string
        # if and only if M halts on the empty string.
        def T_M(w):
            M('')
            return True
        return not E(T_M) # Analyze T_M using hypothetical decider E
  • If M('') halts, then:
    • T_M accepts all inputs, so \(L(T_M) \ne \emptyset\).
    • So E(T_M) returns False, so
      H_๐œ€ returns True.
  • If M('') loops, then:
    • T_M never reaches the return, so accepts no inputs, so \(L(T_M) = \emptyset\).
    • So E(T_M) returns True, so
      H_๐œ€ returns False.
  • Therefore H_๐œ€ decides \(\probHALTe\),
    a contradiction.

Could we instead make T_M return False and H_๐œ€ return E(T_M)?

  • Yes
  • No

More undecidable problems: Rejecting problem

\[ \probRejects = \setbuild{\encoding{M}}{M \text{ is a Turing machine that rejects at least one input}} \]

Theorem: \(\probRejects\) is undecidable.

Proof:

  • Suppose that \(\probRejects\) is decidable by algorithm R:

    def R(M): raise NotImplementedError()
  • We can use R to decide \(\probHALTe\) as follows:

    def H_๐œ€(M):
        # Create a new algorithm that rejects a string
        # if and only if M halts on the empty string.
        def T_M(w):
            M('')
            return False
        return R(T_M) # Analyze T_M using hypothetical decider R
  • If M('') halts, then:
    • T_M rejects all inputs.
    • So R(T_M) returns True, so
      H_๐œ€ returns True.
  • If M('') does not halt, then:
    • T_M never reaches the return, so rejects no inputs.
    • So R(T_M) returns False, so
      H_๐œ€ returns False.
  • Therefore H_๐œ€ decides \(\probHALTe\),
    a contradiction.

How to spot undecidability at a glance

  • When faced with a new problem, we can always follow the recipe to show itโ€™s undecidable.
  • But often we can spot at a glance that the problem must be undecidable.
  • Questions about โ€œeventualโ€ algorithm โ€œbehaviorโ€ are undecidable.
  • Example: given program \(P\) and input \(x\):
    • Does \(P\) accept x?
    • Does \(P\) reject x?
    • Does \(P\) loop on x?
    • Does \(P(x)\) ever call subroutine \(f\)?
  • Example questions about general program behavior:
    • Does \(P\) accept at least one input?
    • Does \(P\) accept all inputs?
    • Is \(P\) total?
    • Is there an input \(x\) such that \(P(x)\) returns 42?
    • Does some input cause \(P\) to call subroutine \(f\)?
    • Do \(P\) and \(Q\) decide the same language?
    • Is \(P\) a polynomial-time machine?

Decidable problems about programs

  • Not all questions we can ask about a program are undecidable though!
  • Questions about syntax are decidable:
    • Does \(P\) have 100 lines of code?
    • Does \(P\) have 2 and 3 in its input alphabet?
    • Does \(P\) halt immediately because its first line is an immediate return without a subroutine call?
    • Does \(P\) have a subroutine named f (whether or not it is ever called)?
  • โ€œBoundedโ€ questions about behavior are decidable:
    • Does \(P(x)\) halt within 10 steps?
    • Does \(P(x)\) halt within \(|x|^3\) steps?
    • Given \(P\) and \(n\), does \(P\) halt within \(n^3\) steps for all inputs of length \(n\)? (โ€œonlyโ€ takes time \(O(n^3 \cdot 2^n)\))
    • Does \(P(x)\) call subroutine \(f\) in the fifth step?
  • Careful: if the question is bounded but about infinitely many inputs, it may still be undecidable!
    • Given \(P\), is there an input \(x\) such that \(P(x)\) halts within \(|x|\) steps? (looks superficially like an \(\NP\) question, but \(x\) could be huge compared to \(|\encoding{P}|\))
    • Given \(P\), does \(P\) halt within \(|x|\) steps for all inputs \(x\)?

Some examples

Which of the following problems, about program \(P\) (and possibly input \(x\)) is decidable?

  • Given \(P,x\), does \(P(x)\) halt in \(|x| \log |x|\) steps?
  • Given \(P\), does \(P\) run in time \(O(n \log n)\) for all inputs?
  • Given \(P\), does \(P\) decide the language \(\setbuild{\encoding{n}}{n \text{ is prime}}\)?
  • Given \(P\), does \(P\), as a Turing machine, have only transitions that move the second tape head to the right?
  • Given \(P,x\), does \(P(x)\) ever move its second tape head to the right?