Hello! Welcome to the eleventh lesson in our course on the theory of computation.
In our last lesson, we reached a major milestone by proving that the landscape of computation has boundaries. Using the diagonalization argument, we established that the set of all languages is uncountably infinite, while the set of all Turing Machines is merely countable. This mismatch proves that there must be languages that no Turing Machine can even recognize. We even constructed a concrete example of such a language, .
Today, we will use that same powerful diagonalization technique to investigate one of the most foundational questions in computer science. We will move from the limit of what can be recognized to the limit of what can be decided. Our learning outcome is to: Define the Halting Problem () and prove its undecidability using a proof by contradiction.
This is a landmark result that has profound implications for software engineering, artificial intelligence, and our understanding of what algorithms can and cannot do.
What Is the Halting Problem?
From a practical standpoint, you've likely encountered a version of the Halting Problem in your own coding experience. Have you ever written a program that accidentally fell into an infinite loop? Debugging such issues can be tricky. It raises a natural question: couldn't we build a perfect debugging tool, a program that analyzes any other program and its input, and tells us definitively whether it will run forever or eventually halt?
This is the essence of the Halting Problem. To discuss it formally, we define it as a language.
The Acceptance Problem for Turing Machines, denoted , is the language:
This language represents the set of all pairs of a TM and a string where the TM accepts that string.
Why is this the "Halting Problem"?
A machine that decides would have to halt on all inputs.
- If accepts , the decider would halt and accept.
- If rejects , the decider would halt and reject.
- If loops on , the decider must still halt and reject.
Therefore, a decider for would need to be able to detect infinite loops. Solving the decision problem for is equivalent to solving the Halting Problem.
In a previous lesson, we established that is Turing-recognizable. We can build a Universal Turing Machine (UTM) that simulates on . If accepts, the UTM accepts. The catch is that if loops, the UTM also loops, which is why it's only a recognizer, not a decider. The question we will answer today is whether a true decider can exist.
The following short video provides an excellent, intuitive introduction to the problem and the logic of its proof.
Understanding the Halting Problem
This video from the Spanning Tree channel clearly introduces the Halting Problem from a programmer's perspective and walks through the logic of the proof of its unsolvability.
Watch the entire video. It introduces the problem, sets up the proof by contradiction, constructs the paradoxical 'Opposite' program, and demonstrates the contradiction. This will give you a strong intuitive foundation before we dive into the formal proof.
Proving the Undecidability of
As the video showed, the proof that is undecidable is a proof by contradiction that uses the diagonalization argument you are now familiar with.
The Strategy
- Assume that is decidable.
- This assumption means there must exist a Turing Machine—let's call it —that always halts and correctly decides .
- Construct a new, paradoxical Turing Machine—let's call it —that uses as a subroutine.
- Show that when is run on its own description, its behavior leads to a logical contradiction.
- Conclude that our initial assumption must be false, meaning no such decider can exist. Therefore, is undecidable.
The following video from MIT OpenCourseWare features Professor Michael Sipser (author of a key textbook in this field) presenting the formal proof.
This video segment provides the formal, rigorous proof of the Halting Problem's undecidability. It directly applies the diagonalization logic from last lesson to the context of Turing Machines.
Please watch from 40:51 to 50:43. This is the core of today's lesson. Pay close attention to how the contradictory machine, D, is constructed and why feeding D its own description leads to a paradox. The table visualization at the end connects this proof directly back to the diagonalization method.
Deconstructing the Proof
Let's summarize the key steps from the video with our formal notation.
Step 1: Assume a Decider Exists
We begin by assuming is decidable. This implies the existence of a TM, , that is a decider for . Its behavior is defined as:
The crucial property of is that it always halts.
Step 2: Construct the Diagonal Machine
Now we build a new TM, , which uses as a subroutine.
The machine takes as input the encoding of a single TM, .
Here is the specification for :
On input :
- Run the decider on the input . This step involves feeding a machine its own description as input. This might seem strange, but it's a valid operation—for instance, a C compiler (a program) written in C can compile its own source code (its description).
- Act on 's output:
- If accepts, then rejects.
- If rejects, then accepts.
In short, accepts if and only if does not accept . does the opposite of whatever the machine on the diagonal does.

Step 3: The Contradiction
Since is a Turing Machine, it must have its own encoding, . What happens when we feed as input to itself?
Let's analyze :
-
Case 1: Assume accepts .
Looking at the definition of , it only accepts its input () if the subroutine rejected on the input . According to the definition of , this means that does not accept .
This leads to: accepts does not accept . A contradiction. -
Case 2: Assume does not accept .
Again, by 's definition, it would only reject its input () if the subroutine accepted on the input . According to , this means that does accept .
This leads to: does not accept accepts . Another contradiction.
Both possibilities result in a logical impossibility. The only thing we assumed was the existence of the decider . Therefore, that assumption must be false.
For a formal, written version of this argument, the following notes are an excellent resource.
Lecture 21: Undecidability, halting and diagonalization
This excerpt from lecture notes at the University of Illinois provides a concise and formal write-up of the proof we just covered.
Please read Section 4, 'The Halting theorem.' This presents the same proof by contradiction, naming the machines 'Halt' and 'Flipper', which correspond to our H and D, respectively. Reading the proof helps reinforce the formal steps.
Test your understanding!
In the proof, we constructed machine which takes an input and runs on . Why is it essential that the second component of the input to is (the same as 's input) and not some other fixed string, say ?
Show answer
Using as the second component is the core of the diagonalization argument. It creates a situation where a machine's behavior is defined in terms of its action on its own description. This sets up the self-referential paradox. If we used a fixed string , our contradictory machine would be defined as: "accept iff does not accept ". When we test on , the logic becomes: "D accepts iff does not accept ". This is not a contradiction. It simply tells us a fact about how behaves on two different inputs ( and ). The contradiction only arises when the behavior on one specific input is defined to be the negation of itself.
Conclusion
Today, we have formally proven that no algorithm can ever exist that solves the Halting Problem for all possible program-input pairs. This is not a limitation of our current technology or programming languages; it is a fundamental, mathematical limit on what computation can achieve.
Key Takeaways:
- The Halting Problem (formalized as the language ) asks whether a given Turing Machine will accept a given string.
- is Turing-recognizable, but it is undecidable.
- The proof of undecidability is a classic proof by contradiction that uses diagonalization. It assumes a decider exists, then constructs a paradoxical machine that does the opposite of what predicts about 's behavior on its own code, leading to an inescapable contradiction.
Preview of the Next Lesson:
Now that we have established our first, canonical undecidable problem (), we have a powerful foothold. We no longer need to construct intricate diagonalization proofs from scratch every time. In the next lesson, we will learn about mapping reducibility, a technique for proving that other problems are undecidable by showing that they are "at least as hard as" the Halting Problem. This will allow us to quickly prove the undecidability of a wide range of other problems about Turing Machines.