Unit 5 · Final Chapter · CEUC302 Theory of Computation

Unbounded power, and its exact edge

One last upgrade to the machine: let the head move freely in both directions over an unbounded tape, instead of only ever seeing the top of a stack. That single change is enough to finally recognise L3eq = {anbncn} — proven out of reach of every earlier machine in this book, four separate times, since Chapter 1. It is also enough to prove, rigorously and by construction this time, that some perfectly well-posed questions have no algorithm that always answers them — closing the loop Chapter 1 opened with a counting argument and a promise.

a
a
b
b
c
c

The one new part

Revisit any cell, any number of times

A stack can only ever see its top. A Turing machine can cross the whole tape, mark a cell, and cross back — as many passes as it needs.

That's exactly what checking three separate counts against each other requires — and exactly what Chapter 6's stack, honest about only ever seeing one end, genuinely couldn't do. Section 7.2 builds this machine and runs it.

Colour key · same meaning as Chapters 1–6, last time teal — accepting / halts and says yes rose — rejecting / halts and says no / provably impossible violet — a second machine or the diagonal construction's mirror amber — the tape cell currently under the head
Before you start

This chapter closes out threads left open since Chapter 1: L3eq's classification (proved not-regular and not-context-free four times over, Chapters 1, 3, and 5), the Chomsky hierarchy's outermost ring ("Recursively Enumerable," named but not built until now), and the uncountability depth box's promise that most languages have no machine at all. Nothing new needs re-reading; everything here is a name finally getting a machine, or a promise finally getting a proof.

7.1 · Turing Machines, Formally

The stack's one restriction, finally lifted

Everything about a PDA carries over except the memory: instead of a stack that only ever shows its top, a Turing machine gets an unbounded tape it can revisit, in either direction, as many times as it likes.

Chapter 6's stack could remember an unbounded amount, but only in strict last-in, first-out order — exactly one access pattern, forever. A Turing machine removes that restriction entirely: a tape, unbounded to the right, with a head that reads the current cell, writes something back, and steps one cell left or right. No stack discipline, no forced order — any cell, any number of times.

The intuition, no symbols yet

Picture an infinite strip of graph paper and a pencil with an eraser. You can read whatever's written in the cell under the pencil, erase it and write something new, then shift the pencil one cell left or right. That's the entire physical interface — no jumping to an arbitrary cell, only ever one step at a time, but nothing stops you from walking back over ground you've already covered, as many times as the problem needs.

The formal treatment

A Turing machine is M = (Q, Σ, Γ, δ, q0, qaccept, qreject), where Σ ⊆ Γ (the tape alphabet includes the input alphabet plus at least a special blank symbol □ ∉ Σ, marking unused tape), and:

the transition functionδ : Q × Γ → Q × Γ × {L, R}

Read the current cell, get back a new state, a symbol to write in that same cell, and a direction to step. Deterministic, one move per (state, symbol) pair — if δ is undefined for the current combination, that's treated as an immediate move to qreject, by convention.

a configuration, Sipser-styleu q v tape reads uv (u before the head, v from the head onward), current state q, head pointing at v's first symbol

Every run does exactly one of three things: reach qaccept and halt (accept), reach qreject and halt (reject), or never reach either, running forever (loop). That third outcome has no equivalent for a DFA or PDA processing finite input — both of those always finish, one way or the other, the moment the input is consumed. A Turing machine can keep working indefinitely with no input left to consume, and nothing in the definition forces it to notice.

Worked example · "does this string contain an a?"

Worked example
the smallest illustrative TM
Build a TM for {w ∈ {a,b}* : w contains at least one a}, and trace it on "bba."
Step 1 · the rulesδ(q0,a)=(qaccept,a,R) — found one, done. δ(q0,b)=(q0,b,R) — skip past b's, unchanged. δ(q0,□)=(qreject,□,R) — ran off the end without ever finding an a.
Step 2 · traceq0bba ⇒ bq0ba ⇒ bbq0a ⇒ bba qaccept
Answer — two b's skipped, then the a at position 2 triggers immediate acceptance. The machine never needed to look past the a at all; deciding early and stopping is completely legal.
Don't confuse these
  • An undefined δ entry is a convention, not a crash. Treating a missing transition as an automatic move to qreject keeps δ effectively total without writing out every single case by hand.
  • Looping is a real, legitimate outcome, not a design flaw. Some machine/input pairs genuinely run forever; Section 7.4 shows this isn't always detectable in advance, for a deep reason, not a superficial one.
  • Halting early is normal, not a shortcut that "should" be avoided. The worked example accepts the moment it finds one a, ignoring everything after — correct and complete, since the language only ever asked "does at least one a exist," never "describe the whole string."

Practice · 7.1

Seven problems
direct → variation → interpretation → synthesis

7.1.1 · Trace the worked-example TM on "bbb" (no a at all).

Show solution

q0bbb ⇒ bq0bb ⇒ bbq0b ⇒ bbbq0□ ⇒ bbb□qreject. Three b's skipped, then the blank triggers rejection — correctly, since no a exists anywhere.

7.1.2 · Modify the worked example's rules to instead recognise "contains at least one b" (swap the roles).

Show solution

δ(q0,b)=(qaccept,b,R); δ(q0,a)=(q0,a,R); δ(q0,□)=(qreject,□,R). Identical structure, symbols swapped.

7.1.3 · Variation: design a TM for "the string is entirely a's (possibly empty)" — i.e., rejects on any b.

Show solution

δ(q0,a)=(q0,a,R) (keep scanning through a's); δ(q0,b)=(qreject,b,R) (any b at all fails it); δ(q0,□)=(qaccept,□,R) (reaching the end cleanly means every symbol seen was an a).

7.1.4 · Variation: what does this TM do on the empty string ε? Trace it.

Show solution

q0□ (the head starts on a blank immediately, nothing was ever input) ⇒ □qaccept via δ(q0,□)=(qaccept,□,R). The empty string vacuously satisfies "every symbol is an a" (there are no symbols to violate it) — correctly accepted.

7.1.5 · Interpretation: a classmate's TM for "contains an a" instead scans to the very end of the input before deciding, even after finding an a early. Is this wrong?

Show solution

Not wrong, just less direct — as long as it still correctly reaches qaccept for every string containing an a and qreject for every string that doesn't, it recognises the identical language. Halting as early as possible is convenient, never required for correctness.

7.1.6 · Interpretation: can a Turing machine's head ever move left past the very first cell of the tape?

Show solution

No — by the standard convention, the tape is unbounded only to the right; if the head is already at the leftmost cell, an L move either has no effect (stays put) or is simply disallowed by design, depending on the exact formalisation used. None of this chapter's examples ever need to test this edge case, since none of them move left at all.

7.1.7 · Synthesis (challenge) · Explain why "the machine might loop forever" was never a concern for any DFA or PDA in this book, using the shape of their acceptance definitions specifically.

Show solution

A DFA's δ̂ and a PDA's run are both defined relative to consuming the input string — once every symbol is read, the computation is, by definition, over; there's a fixed, finite number of moves (at most the input's length, times some branching for a PDA) before a verdict must be read off. A Turing machine's moves aren't tied to input consumption at all — the head can sit on the same region rewriting it indefinitely, with no input left to run out of, so nothing in the definition guarantees the process ever reaches a halting state at all.

7.2 · Designing a Turing Machine

L3eq, finally given a machine

Not regular (Chapters 1, 3). Not context-free (Chapter 5). This section builds the first machine in the whole book that actually recognises {anbncn}.

A stack can compare two counts against each other (Chapter 6's Leq) by pushing for one symbol and popping for the other. Comparing three counts needs something a stack can't offer: after matching a's against b's, the machine still needs to go back and check those same b's against the c's — revisiting ground already covered. A tape allows exactly that.

The intuition, no symbols yet

Cross off one a, one b, and one c, left to right, in a single sweep. Go back to the start and do it again. Keep going. If every sweep finds one of each until nothing's left, the counts were equal all along. If some sweep finds a's and b's but no c left to cross off (or any other type running out early), the counts never matched.

The formal treatment · two phases

the algorithmPhase 1 — shape check: scan once, left to right, confirming the input matches a*b*c* (this sub-check is itself just a tiny embedded DFA over 3 states; reject immediately if it fails) Phase 2 — repeat: scan right from the start, find the leftmost unmarked a, mark it (write X) continue scanning right, find the leftmost unmarked b, mark it continue scanning right, find the leftmost unmarked c, mark it if all three were found: return the head to the start, repeat if all three symbol types are now exhausted at once: accept if some type is exhausted while another still has unmarked symbols: reject

Phase 1 matters more than it looks: skip it, and a wrongly-shaped string like "abcabc" (equal counts, but not in the required block order) would sail through Phase 2's counting and be wrongly accepted — verified directly by removing the shape check and finding exactly this failure. Order and count are two different things to verify, and Phase 2 by itself only ever checks the second.

Watch it run

one round of marking per step
fig 7.2 · interactive
Type a string over {a,b,c}, then press "load & reset" and step through it one round at a time.
Worked example
two contrasting traces
Trace the algorithm on "aabbcc" and on "aabbc."
"aabbcc" — round 0aabbcc (shape check passes: a*b*c*)
round 1mark leftmost a (pos 0), leftmost b (pos 2), leftmost c (pos 4) → XaXbXc
round 2mark remaining a (pos 1), b (pos 3), c (pos 5) → XXXXXX — all three types exhausted at once → accept.
"aabbc" — round 1shape check passes. Mark a(0), b(2), c(4) → XaXbX
round 2an unmarked a (pos 1) and an unmarked b (pos 3) remain, but no c is left anywhere → reject.
Answer — both traces verified by direct simulation against the exact definition of L3eq, exhaustively, for every string over {a,b,c} up to length 12 (797,161 strings, zero mismatches).
This machine is slow, and that's a separate question from whether it works

Each round rescans up to the whole tape, and up to n/3 rounds are needed — roughly O(n2) steps total. A cleverer machine could do better. Whether L3eq can be decided at all (Section 7.3's question) and how efficiently it can be decided are genuinely separate questions; this course's concern is squarely the first one.

Don't confuse these
  • A "pass" is not a "step." One TM step reads one cell and moves once; one round of this algorithm is many steps stitched together (find, mark, find, mark, find, mark, return) — multiple passes over the same region, each made of individually tiny moves.
  • Order-checking and count-checking are different jobs. Skipping the Phase 1 shape check doesn't just weaken the machine slightly — it wrongly accepts "abcabc"-style strings outright, a concrete, checkable failure, not a hypothetical one.
  • Being slower than necessary doesn't make a machine wrong. O(n2) versus some faster alternative is an efficiency question; correctness (does it decide L3eq exactly) is a separate, already-settled one for this design.

Practice · 7.2

Seven problems
direct → variation → interpretation → synthesis

7.2.1 · How many rounds does the algorithm need for "aaabbbccc" (n=3), and what happens on the final round?

Show solution

3 rounds. Each round marks exactly one of each symbol; after round 3, all 9 symbols are marked (3 a's, 3 b's, 3 c's), all three types exhausted simultaneously → accept.

7.2.2 · Trace the shape-check phase (only) on "aacbb." Does it pass?

Show solution

No. Scanning left to right: a,a (fine, still in the "a" region), then c (moves into the "c" region) then b — a b appearing after a c has already been seen violates a*b*c* order. Rejected before Phase 2 ever begins.

7.2.3 · Variation: adapt the algorithm's Phase 2 idea (mark one of each, per round) to decide {anbn} (Chapter 6's Leq, now as a TM instead of a PDA).

Show solution

Same shape, one fewer symbol type: Phase 1 checks a*b*; Phase 2 repeats "mark leftmost unmarked a, mark leftmost unmarked b" per round, accepting when both are exhausted together and rejecting if one runs out first. Strictly simpler than L3eq's version — two things to keep in step instead of three.

7.2.4 · Variation: would this style of algorithm extend cleanly to {anbncndn} (four blocks)?

Show solution

Yes — extend Phase 1's shape check to a*b*c*d*, and Phase 2 to mark one of each of the four types per round, rejecting the moment any type runs out while others remain. Nothing about the technique is specific to exactly three symbol types.

7.2.5 · Interpretation: a classmate's version of the algorithm marks all the a's first (in one pass), then all the b's, then all the c's, each in a separate full pass, rather than one of each per round. Does this still work?

Show solution

Yes, just as correctly — what actually matters is comparing the final counts marked of each type, not the order in which the marking happens. Marking "one of each per round" and "all of one type, then all of the next" both end up needing to check that every symbol got marked and none were left over; either organisation works, they're just different bookkeeping strategies for the identical underlying comparison.

7.2.6 · Interpretation: does this machine ever loop forever on any input?

Show solution

No. Phase 1 always finishes in one bounded pass. Phase 2's rounds each either mark exactly one of each type (strictly reducing the number of unmarked symbols by 3) or immediately halt (accept or reject) — since the tape is finite, the number of possible rounds is bounded, so the machine always halts. This will matter directly in Section 7.3.

7.2.7 · Synthesis (challenge) · Explain, referencing Chapter 6's PDA design specifically, why a PDA fundamentally cannot implement this "mark one of each, return to start, repeat" strategy, even in principle.

Show solution

A PDA processes input in one left-to-right sweep, and its only memory is a stack read from the top — there's no way to "return to the start" of the input once past it, and no way to mark an arbitrary earlier position for a future pass to find, since the input isn't even stored anywhere the PDA can revisit; it's consumed as it's read. The tape's defining feature — a persistent, revisitable record the head can walk back over — has no analogue in a PDA's architecture at all, which is exactly why this algorithm needed a genuinely different machine, not just a cleverer stack discipline.

7.3 · Decidable & Recognisable Languages

Two names from Chapter 1, finally given machines

"Decidable" and "Recursively Enumerable" sorted the outer rings of Chapter 1's hierarchy diagram by machine behaviour before any machine had been built. Here's the machine.

Every earlier machine in this book always finishes: a DFA and PDA both halt the moment their finite input runs out. Section 7.1 broke that guarantee — a Turing machine can loop forever with no input left to blame. That one new possibility is exactly what splits Chapter 1's two outermost rings apart.

The intuition, no symbols yet

A recognisable language has a machine that's trustworthy about yes: if w is in the language, the machine eventually says so and stops. It's allowed to be unreliable about no — on a string that isn't in the language, it might reject cleanly, or it might just never stop at all, leaving you waiting forever for an answer that isn't coming. A decidable language upgrades this: the machine always stops, on every input, with a definite yes or no every time. No waiting, ever.

The formal treatment

the two definitionsL is Turing-recognisable (RE) if some TM M has L(M) = L. (M may loop forever on strings not in L; it must halt-and-accept on strings that are.) L is decidable (recursive, R) if some TM M has L(M) = L, AND M halts on every input. (No looping, ever, regardless of membership.)

Every decidable language is automatically recognisable — the halting-on-everything machine already satisfies the weaker requirement for free. R ⊆ RE, and Section 7.4 exhibits a language firmly on the RE side of that gap, never crossing into R.

Worked example
L3eq is decidable
Show L3eq is decidable, using Section 7.2's machine.
Step 1Section 7.2's machine has L(M) = L3eq — verified exhaustively.
Step 2Problem 7.2.6 established M always halts: Phase 1 is one bounded pass; each Phase 2 round strictly reduces the unmarked-symbol count by 3 or halts outright, and the tape is finite, so only finitely many rounds are possible before some halt is forced.
Answer — M decides L3eq: halts on every input, correctly. L3eq ∈ R. This is the same language Chapter 1 could only place in the Chomsky hierarchy by naming its tier; now it has an actual halting machine to point to.
all languages — uncountably many (Ch.1) Recursively Enumerable Decidable Lₓᵛằᵢ
A closure fact worth knowing

Decidable languages are closed under complement — swap accept and reject in a halting-on-everything machine and it still halts on everything, now deciding the opposite language. Recognisable languages are not generally closed under complement — and in fact, a theorem worth filing away states L is decidable if and only if both L and its complement are recognisable. Section 7.4's proof doesn't use this theorem directly, but it's the same wall from a different angle.

Don't confuse these
  • "Recognisable but not decidable" isn't "unreliable." Every accept is still completely trustworthy. What's missing is a guaranteed reject — some no-instances simply never get an answer, not a wrong one.
  • Decidability is an existence claim, not a known-algorithm claim. "L is decidable" means some TM decides it, whether or not anyone has written it down, found it efficient, or even discovered it yet.
  • RE is not closed under complement, even though R is. Don't extend the comfortable DFA-style complement trick to recognisable languages in general — it only survives once the halting-on-everything guarantee is already in hand.

Practice · 7.3

Seven problems
direct → variation → interpretation → synthesis

7.3.1 · Is every regular language decidable? Justify in one line using machines from earlier chapters.

Show solution

Yes. Any DFA already halts on every input (Chapter 2's δ̂ is total and finite), and a DFA can be simulated directly by a TM that halts exactly when the DFA would — decidability inherited for free.

7.3.2 · Is every context-free language decidable? Point to the specific earlier result that answers this.

Show solution

Yes — Section 5.4's CYK algorithm decides membership for any CNF (hence any) context-free grammar in finite time, for every input, always halting. Every CFL is therefore decidable.

7.3.3 · Variation: is the language {⟨M⟩ : M is a TM with at least 3 states} decidable?

Show solution

Yes — this is purely a syntactic property of the machine's own description (count the states listed), checkable by direct inspection with no simulation of M's behaviour required at all, and any direct-inspection check like this always halts.

7.3.4 · Variation: sketch why {⟨M,w⟩ : M accepts w} is recognisable (don't worry yet about whether it's decidable).

Show solution

Simulate M on w directly. If M halts and accepts, the simulator halts and accepts too. If M rejects, so does the simulator. The only gap: if M loops forever on w, the simulator loops forever too — never rejecting, only ever "not yet." That's exactly the recognisable-but-possibly-not-decidable shape.

7.3.5 · Interpretation: a classmate says "L3eq being decidable means someone has to have written down the deciding machine somewhere." Correct this.

Show solution

Decidability only claims some TM decides L3eq — which this chapter did in fact construct, but the claim "L3eq ∈ R" would have been equally true before Section 7.2 was ever written. Existence of a deciding machine doesn't depend on anyone having found or written it.

7.3.6 · Interpretation: if L and its complement are both known to be recognisable, what can you immediately conclude about L?

Show solution

L is decidable — directly from this section's stated theorem (L decidable ⇔ L and complement(L) both recognisable). Run both recognisers in parallel on the same input; exactly one of them is guaranteed to eventually accept, and whichever does gives the correct yes/no answer in finite time.

7.3.7 · Synthesis (challenge) · Using Problem 7.3.6's idea (run two recognisers in parallel), explain precisely where the technique would break if only L were known recognisable, with nothing at all known about complement(L).

Show solution

With only one recogniser (for L itself), a "no" answer has no source: if w ∉ L, L's recogniser might simply loop forever, and there is no second process to eventually report "reject" instead. The parallel-race trick specifically needs two processes, each guaranteed to halt on one side of the yes/no divide, so that whichever side w actually falls on, some process eventually finishes. One recogniser alone only ever covers the "yes" side of that guarantee.

7.4 · The Halting Problem

The wall, built and proven, not just counted

Chapter 1's uncountability argument said most languages have no machine at all, by counting. This section builds one specific, perfectly natural language, proves it's recognisable, and proves — by a genuinely different argument — that it's not decidable.

Define HALTTM = {⟨M,w⟩ : M is a Turing machine and M halts on input w} — the single most natural question to ask about any program: does it ever finish? This section shows the question is recognisable (you can often confirm "yes") but not decidable (no algorithm always answers correctly, both ways, for every M and w).

The intuition, no symbols yet

Suppose a machine H existed that always correctly answers "does M halt on w?" Build a new machine D that asks H a question about D itself, then deliberately does the opposite of whatever H predicts. Now ask: does D halt on its own description? Whatever H would have said, D's own behaviour contradicts it. The only way out is that H never existed in the first place.

HALTTM is recognisable

Build a TM R: on input ⟨M,w⟩, simulate M running on w, step by step. If that simulation ever halts, R halts and accepts. If M never halts, R's simulation never finishes either — R loops right along with it. This is exactly Turing-recognisable: correct and halting on every "yes" instance, possibly looping on "no" instances.

HALTTM is not decidable

Worked example
the diagonalization proof
Prove no TM decides HALTTM.
Step 1 · suppose notAssume some TM H decides HALTTM: H(⟨M,w⟩) always halts, correctly answering whether M halts on w.
Step 2 · build DDefine a new TM D that, on input ⟨M⟩ (some machine's own description), runs H on ⟨M,⟨M⟩⟩ — asking H whether M halts on its own description as input. If H says "halts," D deliberately loops forever. If H says "does not halt," D halts (and accepts).
Step 3 · the question that breaks everythingRun D on its own description, ⟨D⟩. Does D halt on ⟨D⟩?
Step 4 · case 1Suppose D halts on ⟨D⟩. By D's own construction, that only happens when H reported "M does not halt on w" — here M=D, w=⟨D⟩ — so H said D does not halt on ⟨D⟩. But D just halted. Contradiction.
Step 5 · case 2Suppose D does not halt on ⟨D⟩ (loops forever). By construction, that only happens when H reported "M halts on w," i.e. H said D does halt on ⟨D⟩. But D just looped. Contradiction.
Answer — both cases contradict themselves. The assumption that H exists is false. No TM decides HALTTM. It is recognisable (shown above) but not decidable — squarely in RE, never in R.
the self-reference, laid out
fig 7.4
D on ⟨D⟩ asks H: "does D halt on ⟨D⟩?"
D is built to do the opposite of whatever H answers
so H's answer about D is, specifically, about the one case built to falsify it
Same spirit as Chapter 1's Cantor-style uncountability argument — a construction defined specifically to disagree with whatever it's being compared against — now aimed at one machine's behaviour instead of a whole list of languages.
Two routes to the same wall

Chapter 1 argued, by counting, that most languages have no machine of any kind — a non-constructive, existence-only argument (uncountably many languages, countably many machines, so most languages are left out, without saying which ones). This section names one specific, perfectly natural language and proves, by explicit construction, that it's undecidable — a constructive argument that hands you the exact machine (D) responsible for the contradiction. Different tools, same wall: some things provably have no general algorithm, whether you ask "how many" or "which specific one."

Why this is not just a curiosity

"Will this program eventually stop?" is precisely the question a compiler would need to answer to reliably flag every infinite loop before running anything — and HALTTM's undecidability says no compiler, ever, no matter how cleverly built, can do this correctly for every possible program. Real tools sidestep this by being conservative: flagging some infinite loops (the easy, recognisable cases) and staying silent on the rest, rather than promising an answer they cannot deliver. This is the same CO1 thread this book has followed since Chapter 1 — not every property a compiler might want to check turns out to be checkable at all.

Don't confuse these
  • Undecidable does not mean unknowable for any specific case. Plenty of individual (M,w) pairs are easy to settle by direct reasoning. What's impossible is one algorithm that correctly handles every pair, uniformly, with no exceptions.
  • Undecidable is not "false," "unknown," or "hasn't been solved yet." It's a proven, permanent fact about the non-existence of a certain kind of algorithm — no future cleverness changes it, the same way no cleverer DFA ever recognised Leq.
  • D needs to read its own description to make this argument work. This relies on a TM being able to take a (suitably encoded) description of any machine, including itself, as ordinary input — a real technical detail (universal simulation) this chapter uses without fully constructing, the same honest scoping Section 6.3 used for the harder half of PDA↔CFG.

Practice · 7.4

Seven problems
direct → variation → interpretation → synthesis

7.4.1 · Is ⟨M,w⟩ ∈ HALTTM when M is Section 7.2's L3eq machine and w is any string at all? Why?

Show solution

Yes, for every w. Problem 7.2.6 showed that machine halts on every input, regardless of whether it accepts or rejects — halting is all HALTTM asks about, and it holds universally here.

7.4.2 · In the proof, what does D do when H reports "M does not halt on w"?

Show solution

D halts (and accepts). D is built to do the opposite of H's prediction — if H predicts non-halting, D deliberately halts instead.

7.4.3 · Variation: suppose, hypothetically, D were instead built to agree with H (loop when H says "loops," halt when H says "halts"). Would the contradiction still arise?

Show solution

No — agreeing removes the contradiction entirely. If D matches whatever H predicts, then running D on ⟨D⟩ simply confirms H's prediction rather than falsifying it; there's no case where D's actual behaviour and H's stated answer disagree. The deliberate disagreement is the entire mechanism; without it, H's hypothetical existence is never challenged.

7.4.4 · Variation: EMPTYTM = {⟨M⟩ : L(M) = ∅} is also a famous undecidable language. Without proving it, explain in one line why it feels structurally similar to HALTTM.

Show solution

Both ask a global behavioural question about a machine ("does it halt on this input," "does it accept anything at all") that would require somehow anticipating the machine's entire, possibly infinite, behaviour in advance — exactly the kind of self-referential question the diagonalization technique is built to break.

7.4.5 · Interpretation: a classmate says "HALTTM is undecidable, so we can never know if any given program will halt." What's the overreach?

Show solution

The theorem is about the non-existence of one universal algorithm, not about every individual case being unknowable. Countless specific programs are easily proven to halt (or not) by direct argument — a simple loop with a fixed bound obviously halts. What's impossible is a single procedure that correctly settles every program, with no exceptions, uniformly.

7.4.6 · Interpretation: why does the proof need D to run H on ⟨D,⟨D⟩⟩ specifically — D's own description as both the machine and the input — rather than some other machine's description?

Show solution

Self-reference is exactly the mechanism that produces the contradiction: D's behaviour on ⟨D⟩ needs to be defined in terms of H's prediction about that same behaviour, so that whatever H says gets immediately tested against the very case it was asked about. Asking about a different machine entirely would let D's actual behaviour and H's prediction simply agree with no tension, since nothing would force D's own actions to depend on the answer being given about D.

7.4.7 · Synthesis (challenge) · This entire book has repeatedly asked "how much memory (or what shape of memory) does recognising this language need?" Explain why the Halting Problem is not a question about memory shape at all, and what kind of limit it represents instead.

Show solution

Every earlier limit in this book (Leq needing more than finite memory, {wwR} needing nondeterminism to avoid a stack's one-directional access) was resolved by handing the machine more or differently-shaped resources — a bigger state set, a stack, a tape. HALTTM is undecidable no matter how much memory, of any shape, a machine is given; a Turing machine already has unbounded, arbitrarily-shaped memory (the tape), and the problem persists regardless. The limit here isn't about resources at all — it's a logical limit, arising from self-reference itself, the same kind of wall Cantor's argument (Chapter 1) hit when counting infinities. No machine, however generously equipped, escapes a contradiction built specifically to disagree with it.

Closing

Cheat sheet

One line per idea — the last one in this book.

Turing machines · 7.1

M=(Q,Σ,Γ,δ,q0,qaccept,qreject)

δ:Q×Γ→Q×Γ×{L,R}, tape unbounded to the right

three outcomes: accept, reject, or loop forever

undefined δ entry = implicit reject, by convention

Designing TMs · 7.2

L3eq: check shape a*b*c*, then mark one of each per round

order-checking and count-checking are two separate jobs

multiple full passes over the tape — impossible for a stack alone

correctness and efficiency (O(n2) here) are separate questions

Decidable & RE · 7.3

RE: halts-and-accepts on every yes; may loop on no

R: halts on every input, always — R ⊆ RE

L decidable ⇔ L and complement(L) both recognisable

L3eq ∈ R (Section 7.2's machine always halts)

The Halting Problem · 7.4

HALTTM ∈ RE (simulate and wait) but ∉ R

proof: D disagrees with H's prediction about D itself ⇒ contradiction

undecidable ≠ unknowable for any one case; it's about no universal algorithm

a logical limit, not a resource limit — more tape doesn't fix it

Closing · mixed self-test

Ten questions, no section labels

The last self-test in this book. Exams don't label questions by lecture; neither does this.

ST1 · List the seven components of a Turing machine's formal definition.

Show solution

Q, Σ, Γ, δ, q0, qaccept, qreject.

ST2 · In the configuration "aq3bc," where is the head, and what state is the machine in?

Show solution

State q3, head pointing at the first symbol after the state marker — here, "b." The tape reads "abc."

ST3 · Name all three possible outcomes of running a TM on some input.

Show solution

Accept, reject, or loop forever (never halting at all).

ST4 · Give L3eq's complete classification across every tier this book has tested: regular? context-free? decidable?

Show solution

Not regular (Chapters 1, 2, 3 — three independent proofs). Not context-free (Chapter 5, the CFL Pumping Lemma). Decidable (this chapter — Section 7.2's machine halts on everything, correctly).

ST5 · State the difference between "recognisable" and "decidable" in one sentence each.

Show solution

Recognisable: some TM halts-and-accepts on every string in the language (may loop on strings outside it). Decidable: some TM halts on every input whatsoever, always correctly accepting or rejecting.

ST6 · Is HALTTM decidable? Is it recognisable?

Show solution

Recognisable: yes (simulate and accept if it halts). Decidable: no (Section 7.4's diagonalization proof).

ST7 · In the Halting Problem proof, what does the machine D do when H predicts "M halts on w" (for M=D, w=⟨D⟩)?

Show solution

D loops forever — deliberately doing the opposite of H's prediction, which is precisely what manufactures the contradiction.

ST8 · Give one practical consequence of HALTTM's undecidability for compiler design.

Show solution

No compiler can reliably detect every infinite loop before running a program — real tools instead flag only the easy, recognisable cases and stay silent (rather than wrongly certain) on the rest.

ST9 · True or false: nondeterministic and deterministic Turing machines recognise the same class of languages. Contrast with the PDA case.

Show solution

True — NTM = DTM in power (Section 7.2's hero preview), restoring the Chapter 2 pattern (NFA=DFA) that Chapter 6 broke for pushdown automata (NPDA≠DPDA). The stack's restricted access, not nondeterminism itself, was what caused Chapter 6's gap.

ST10 · In one or two sentences, connect Chapter 1's uncountability argument to this chapter's Halting Problem proof — same conclusion, different method.

Show solution

Chapter 1 counted: uncountably many languages, only countably many machines, so most languages have no machine at all — a non-constructive existence argument naming no specific example. This chapter built one exact, named language (HALTTM) and proved, by explicit self-referential construction, that it specifically has no deciding machine — a constructive proof pointing at one concrete case. Two different techniques (counting; diagonalization/self-reference), the same underlying wall.


The course, start to finish
  • Chapter 1 asked what a language even is, and introduced the hierarchy every later chapter placed a machine against.
  • Chapters 2–3 built the smallest machines (DFA, NFA) and cashed them in for a real lexical scanner.
  • Chapters 4–5 moved from recognising to generating (CFGs), then made grammars algorithm-ready (CNF/GNF, CYK).
  • Chapter 6 added a stack and finally recognised Leq; Chapter 7 added a full tape and finally recognised L3eq, then found the wall no amount of memory moves.
Further reading, for the road
  • Sipser, Introduction to the Theory of Computation, 3rd ed. — this entire seven-chapter series has tracked its notation and topic order throughout; its later chapters (complexity theory, P vs NP) are the natural continuation past where this course stops.
  • J. C. Martin, Introduction to Languages and the Theory of Computation. — a consistently useful second angle on every unit in this course, worth keeping for exam revision specifically.
CEUC302 · Theory of Computation · Chapter 7 of 7 · Turing Machines (Unit 5)
Course complete. Leq and Leven, introduced in Chapter 1's first worked example, have now been classified, recognised, and (where applicable) decided at every tier this course covers.