Theory of computation · A level · AQA 7517 4.4.4.6 · about 20 min
Non-computable problems, the Halting problem and why it cannot be solved, and what step limits can and cannot tell you.
[1 mark]What is the Halting problem?
[1 mark]What is the significance of the Halting problem?
[1 mark]Which statements are true?
Tick every answer that is true.
[1 mark]Put the steps of the Halting problem proof by contradiction in order.
Number the lines 1 to 5 to put them in the right order.
Write contrary(p): if halts(p, p) is True, loop forever; otherwise stopWhatever halts answers about contrary(contrary), contrary does the oppositeSuppose a function halts(p, d) always correctly says whether p halts on dRun contrary with its own code as inputSo halts cannot existSuppose a function halts(p, d) always correctly says whether p halts on d Write contrary(p): if halts(p, p) is True, loop forever; otherwise stop Run contrary with its own code as input Whatever halts answers about contrary(contrary), contrary does the opposite So halts cannot exist
Assume the checker exists, build a program that does the opposite of its prediction, and feed it itself.
[1 mark]What does this program print?
def watch(x, limit):
for steps in range(limit):
if x == 0:
return "halted after " + str(steps)
x = x - 3
return "no answer"
print(watch(12, 100))
print(watch(10, 100))halted after 4 no answer
From 12, x reaches 0 after 4 steps. From 10, x goes 7, 4, 1, -2, ... and never equals 0, so the limit runs out.
Write a watchdog that runs simple programs with a step limit and reports honestly on each.
- Each program in programs is a tuple (name, x, step, done): name is a string, x is the starting whole number, step(x) returns the next value of x, and done(x) returns True when the program has halted.
- Write watch(name, x, step, done, limit). Before each step, check done(x). If it is True, print <name>: halted after <n> steps, where n is the number of steps taken so far, and stop watching. Otherwise take a step. If limit steps have been taken and done(x) is still not True, print <name>: no answer after <limit> steps.
- Call watch for each program in order, with limit set to 1000.
Three lines in all, such as p1: halted after 3 steps. Work the counts out by running the programs, not by hand.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
programs = [
("p1", 10, lambda x: x - 3, lambda x: x == 1),
("p2", 10, lambda x: x - 4, lambda x: x == 0),
("p3", 27, lambda x: x // 2 if x % 2 == 0 else 3 * x + 1, lambda x: x == 1),
]
def watch(name, x, step, done, limit):
passThe hint students can ask for: Keep a count of steps taken. Loop while the count is below the limit: if the program is done, report the count and return straight away; otherwise take a step and add one. If the loop ends without returning, the limit was reached. Remember to check done once more after the last step.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
programs = [
("p1", 10, lambda x: x - 3, lambda x: x == 1),
("p2", 10, lambda x: x - 4, lambda x: x == 0),
("p3", 27, lambda x: x // 2 if x % 2 == 0 else 3 * x + 1, lambda x: x == 1),
]
def watch(name, x, step, done, limit):
steps = 0
while steps <= limit:
if done(x):
print(f"{name}: halted after {steps} steps")
return
if steps == limit:
break
x = step(x)
steps = steps + 1
print(f"{name}: no answer after {limit} steps")
for name, x, step, done in programs:
watch(name, x, step, done, 1000)
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.