Computability and Complexity
You can build a computer out of a strip of paper, a pencil and a short list of rules. Not a toy version. A machine that can work out anything your laptop can work out, given enough paper and enough patience. That is the good news, and it arrives first. The bad news arrives in Step 5, when the same strip of paper is used to prove that some perfectly sensible questions have no answer any machine can ever produce.
There is a working machine here: a tape, a head that reads and writes one square at a time, a state, and a rule table you type into. Every machine in the course runs on it, including the ones that never stop. Later on, when a method is described as slow, the method is run and its work counted as it goes, so the numbers on screen were produced by running something rather than copied out of a book.
Introduction to Algorithms, or at least the habit of measuring a method by counting the steps it takes rather than by timing it on one particular computer. Nothing else. No programming. No electronics. The only piece of arithmetic that turns up beyond multiplying is doubling over and over, and there is a note on it at the point where it first matters.
The steps
A machine made of tape and rules
Put chips and screens out of your mind for a while. Here is a computer you could cut out with scissors. A long strip of paper, ruled into squares, running off to the right and the left as far as you ever need. Each square holds exactly one symbol, or nothing at all. Sitting over the strip is a head: a small reader that can look at one square, and only one.
The head repeats three actions for as long as it runs. It reads the symbol in the square beneath it. It writes a symbol into that square, rubbing out whatever was there. Then it shuffles one square to the left or to the right. That is the entire body of the machine. There is nothing else in it.
What counts as a symbol
A symbol is one mark you are allowed to write in one square. Which marks are allowed is up to
whoever designs the machine, and the list is fixed before it starts. In this course the marks are the
digits 0 and 1, a few letters such as X and Y, a
plus sign and one more: an empty square.
An empty square needs a name, because rules have to be able to mention it. It is called the
blank, and it is written as an underscore, _. On screen an empty square is drawn
with a dashed edge so you can tell it apart from a square holding a real mark.
Write 1, then
Move right ▶, then Write 0. The pink arrow above the strip is the head, and
it slides one square each time you move it. The line at the bottom says what you just did. Your target
is printed above the strip: get the strip to match it.So the machine needs two more parts. The first is a state: one word, which you can picture on a sticky note attached to the head. That word is the machine's entire memory of what it is in the middle of doing. The second is a rule table, which is the machine's program.
A single word is the whole memory. How can that be enough
Because the tape is doing the rest of the remembering. The state only has to hold what the machine cannot write down: which part of the job it has reached. Something like "I am searching for a plus sign", or "I have seen an odd number of 1s so far". A handful of words covers that.
The number of different words allowed is fixed and finite, and that matters later. A machine cannot have a state for every number it might meet, because there are infinitely many numbers and only so many words. Anything the machine wants to count has to be counted on the tape.
A rule has five parts, written on one line. The first two are the situation, and the last three are what to do about it.
seek 0 -> 1 R seek
Read it as a sentence: when the state is seek and the square under the head holds
0, write 1 into that square, move Right, and make the new state
seek. The move is R for right, L for left, or S to stay
still. The machine stops when it reaches a state called halt, and it also stops if no rule in
the table covers the situation it is in, which is a bug rather than a plan.
What if two rules cover the same situation
They are not allowed to. Each pair of state and symbol may appear at most once in the table. If two
rules both started with seek 0 the machine would have a choice, and then nobody could say
what it does. A machine with no choices is called deterministic and every machine in this
course is one.
This is not a small technical detail. It is what makes the machine trustworthy: run it twice on the same tape and you get the same answer both times, every time, because at every step exactly one rule applies. The editor below will tell you if you write the same situation twice.
Step five times,
slowly. Each press carries out exactly one rule. The rule that matched lights up in the table, the
head slides one square, and the line at the bottom reads out what happened in words. Then press
Run to the end and watch the rest go by.Run to the end again. The machine walks to the
first blank square, finds no rule for that situation, and stops where it stands. It has not crashed, and
nothing is on fire. It simply has nothing to do.seek reading 0, and one for
seek reading 1, and nothing else. The tape holds 0 1 1 and the
machine starts in state seek on the first square. What happens?halt is one way to stop, and
running out of rules is the other. Neither is an error the machine can report, because the machine has
nobody to report to. Later on, that second kind of stopping turns out to be handy: a machine that gets
stuck has still stopped, and Step 5 only ever asks whether a machine stops, not how politely.It can add, and that is already surprising
Flipping 0s into 1s is not obviously computing. So make the strip of paper do arithmetic, which is what the word computer used to mean when it was still a job title.
First, numbers need a shape the machine can handle. Write three as 111 and two as
11: one mark per unit, the way a prisoner scratches days on a wall. Put a plus between them and
the tape reads 111+11. The machine's job is to leave 11111 behind.
Why tally marks instead of ordinary numbers
Because it keeps the first adding machine short enough to read in one go. A machine that adds ordinary written numbers, with carrying, is perfectly possible and takes about twenty rules; a machine that adds tallies takes five. Nothing about what a machine can do depends on the choice. It only changes how many squares a number takes up and how many steps the work costs.
That difference is real, though, and Step 7 comes back to it. Written as tallies, the number one million needs a million squares. Written in the ordinary way it needs seven. When people measure how slow a method is, the size of the written-down input is what they measure against, so the choice of writing changes the measurement.
What an algorithm is
An algorithm is a method written out in enough detail that something with no judgement at all can follow it and get the right answer every time. No steps left to common sense, no "and then sort it out somehow". Long division is an algorithm. A recipe that says "season to taste" is not.
A rule table is an unusually honest way of writing one down, because the machine that follows it really does have no judgement. If a rule table works, there is no argument about whether the method was described properly: you can watch every step of it happen.
Run to the end. Five
1s are left on the strip, which is 3 plus 2. Then press Start over and use
Step to go through it slowly: the plus sign turns into a 1 early on, and one 1 is rubbed
out at the far end near the finish. Change the numbers in the two boxes and run it again.Say the adding trick another way
Three tallies, a plus, two tallies. If you rubbed the plus out entirely you would have five tallies touching, which is the answer, but the machine cannot rub something out and close the gap: a square cannot be removed from the strip, only overwritten. So it writes a 1 in the plus sign's square instead. Now the strip reads six 1s in a row, one too many, and the fix is to delete any single one of them.
The machine deletes the last one, because getting to the end is easy: walk right until you meet a blank, then step back one. Walking left to the front would work just as well and cost the same.
Check my machine before
changing anything. It runs your rules on five sums you cannot see, including two with a zero in
them, and names the first one that came out wrong along with what was left on the strip. Then change one
symbol in the last rule and check again.Anything a computer does, this can do
Every programming language ever made offers the same three things underneath the syntax. Somewhere to keep values. A way to choose between two paths. A way to repeat something. The strip of paper has all three, and they are worth meeting one at a time, because after this step the machine gets used rather than explained.
Values live in two places: on the tape, which is roomy and slow to reach, and in the state, which holds one word and is instant. Choosing happens on every single step, because the pair of state and symbol is what picks the rule. Repeating is a rule whose next state is the state it came from, which sends the machine round the same rule again.
Which part of a rule table is the loop
Look for a rule whose first word and last word are the same. walk 1 -> 1 R walk reads
the symbol, leaves it alone, moves right, and comes back to walk. If the next square also
holds a 1, the same rule fires again. That is a loop, and it keeps going for exactly as long as the
condition holds, which here means until the head meets something that is not a 1.
The way out of the loop is another rule starting with the same state and a different symbol. In a familiar language you would write "while the square holds a 1, move right". Here the while and the condition and the body are all folded into two lines.
remember, then
Run to the end. The machine rubs out the first symbol, walks to the far end, and writes
that same symbol there, without ever being able to see both ends at once. Then press choose
and repeat and run each of those.carry0 and carry1 behave
identically all the way along the strip and only differ at the very last rule, which is what carrying a
value in a state looks like. One word of memory, used well, and it survived a walk of any length.Some machines are asked to work something out, and some are asked a yes-or-no question. For the second
kind we need a way to give an answer, and the tidiest way is to use the state the machine stops in. Two
more special state names join halt: a machine that stops in state yes is
answering yes and one that stops in no is answering no.
Why the answer is a state name rather than a mark on the tape
It could be either. Writing Y or N in a square would work perfectly well,
and some books do it that way. Using the stopping state is slightly tidier because the machine does not
have to tidy the tape first, and because the thing we care about from Step 5 onwards is what a machine
does rather than what it leaves lying around.
A machine that answers a yes-or-no question and always stops is said to decide that question. Hold on to that word. Almost everything in the second half of this course is about which questions can be decided and which cannot.
Check my machine
straight away. It runs your table on seven strips you cannot see, including an empty one, and tells
you which one it got stuck on and why. The table is missing two rules. Add them and check again.Now the claim this whole course rests on. Anything your laptop can work out, one of these strips of paper can work out too. Not quickly, and not comfortably, but it gets there. Nobody has proved that, because "anything a computer can do" is not a precise enough idea to prove things about, but every attempt to invent a more powerful machine since the 1930s has turned out to be exactly as powerful as this one. The claim has a name: the Church-Turing thesis.
How can people be so sure, if it has never been proved
Because of how many separate attempts landed in the same place. Alonzo Church built a system out of nothing but functions being applied to other functions. Alan Turing built the tape machine. Kurt Gödel and Jacques Herbrand built one out of equations about whole numbers. Emil Post built one out of a queue. All of these were done at roughly the same time, by people working differently, and each system turned out to be able to imitate every other one exactly.
Every computer built since fits the same pattern, which is the part that matters for the rest of this course. A limit proved about the strip of paper is a limit on every machine anybody has ever managed to build, including the ones that do not exist yet. That is why Step 5 is allowed to say "no computer" and mean it.
A program is data
Look at a rule table again, and this time do not read it as instructions. Read it as a row of symbols. Words, digits, arrows, spaces. There is nothing about it that stops you writing it out along a tape, in the same squares you would use for a number.
Turning something into a row of symbols by a fixed set of conventions is called encoding it, and the row you end up with is called a string. Encoding a rule table is not clever. Pick a separator between the five parts of a rule, pick another between one rule and the next, and write everything out in order.
What a string is, and why the word is used
A string is a row of symbols one after another, in a definite order, with a definite length.
hello is a string of five symbols. So is 111+11, and so is the whole contents
of a tape between the first and last mark. The name is old and comes from the picture of beads strung on
a thread.
The word gets used constantly in computing because so many different things turn out to be one: text, a program's source, a picture file, a message crossing a network. All of them are rows of symbols that some agreed convention says how to read.
seek to
go everywhere it appears in the table. The encoded string underneath gets shorter as
you type, and the count of squares next to it drops. Then press the adder to load a bigger
machine and watch the string grow.Now put a description of a machine on a tape, put an input next to it, and build a second machine whose job is to read the description and do whatever it says. That second machine is called a universal machine, and it is the single most consequential idea in this course.
You have been using one of these all day
The reason a laptop is not sold as a chess machine, or a word machine, or a spreadsheet machine, is that it is a universal machine. The programs on it are not part of it. They are strings sitting in storage, and the machine reads one and behaves like whatever that string describes. Change the string and the same hardware becomes a different machine.
Before this idea, a machine that did a job was built to do that job. Turing's paper of 1936 described the universal machine years before anyone had built an electronic computer at all, and every general-purpose computer since has been one.
Run to the end. The
long strip at the top is one single tape: a machine description, then a #, then that
machine's input. Underneath, the panel shows the machine being described as it runs, with its own strip,
its own state, and its own step count. Then press the parity machine to put a completely
different program on the same tape.R to an L, and press Run
again: the behaviour underneath changes, because the behaviour is coming off the tape. That is the whole
trick, and it is why the next step is possible at all. Once programs are data, a program can be handed
to a program, including itself.Is that one machine, or is the page cheating
A real universal tape machine does the reading and obeying with nothing but its own rule table, and it is a slog: a few hundred rules and a great deal of shuffling back and forth between the description and the working area to look up each step. Every serious textbook builds one and nobody enjoys it. In the lab above, that shuffling happens at full speed instead of one square at a time, so the idea is watchable.
The part that would be cheating is not happening. The rules being obeyed are read from the top strip, symbol by symbol, and if you write nonsense there the panel below reports that it could not make sense of the description, exactly as the real machine would grind to a halt on it.
The question with no answer
Some machines stop. Some run for ever. Both are easy to write, and once you have a few dozen rules it is no longer obvious from looking which kind you have. Every programmer has shipped a program that hangs, and every programmer has wished the computer would say so in advance.
So here is the question, stated carefully, because the care is where the whole argument lives. Given a description of a machine, and an input for it, will that machine eventually stop? This is called the halting problem.
Why not just run it and see
Run it, and one of two things happens. It stops. You have your answer. Or it is still going. You have learned nothing, because "still going after a million steps" and "going for ever" look identical from the outside and always will. There is no moment at which waiting turns into knowing.
You might try setting a limit: run it for a million steps, and if it has not stopped call it a non-stopper. That method always gives an answer, and it is wrong about every machine that stops at step one million and one. The lab below has a machine that runs for over a thousand steps and then stops. It is not doing anything odd.
stops or never stops to commit, then press Run it. The
machine runs with a budget of 4000 steps and reports what actually happened. Your running score is kept
at the bottom. Press Next machine ▶ for the next one.Running it is not a method, then. What we want is a machine that reads a description and an input and answers correctly without running anything, or at least without running it forever. The argument below shows that no such machine can exist. It is not a hard argument, but it has to be walked through in order, so it is laid out as cards you turn over one at a time.
What "suppose it exists" is doing in an argument
It is a way of proving something is impossible without having to check every possibility. You pretend the thing exists, follow the consequences honestly, and arrive somewhere that cannot be true. Since the reasoning was honest, the fault has to be the pretence, so the thing does not exist. This is called proof by contradiction.
Small example. Suppose there is a largest whole number, and call it L. Then L plus 1 is a whole number, and it is bigger than L. So L was not the largest after all and the supposition has eaten itself. Nobody had to look at every number. The argument on the cards has exactly this shape, with a machine in place of a number.
Go on ▶.
Some cards ask you to choose before they turn over, and a wrong choice explains itself and lets you try
again. At card 4 the argument splits in two and you have to walk both halves; the row of dots at the top
shows which cards you have turned and which are still face down.The whole thing in one breath
Suppose a perfect stopping-detector exists. Build a machine that asks the detector what it will do, and then does the opposite. Ask that machine about itself. Whatever it does, it does the opposite of what it does, so the detector was never perfect. That is the entire argument and every extra sentence in the cards is there to keep it honest rather than to add anything.
The same shape of trick shows up elsewhere."This sentence is false" has no truth value for the same reason. What Turing added was the observation that a machine can be handed its own description, which turns a word game into a fact about every computer that will ever be built.
What undecidable actually means, and what it does not
The word for what Step 5 found is undecidable. A yes-or-no question is undecidable when no single machine answers it correctly for every input while always stopping. The halting problem is the first question ever shown to be undecidable, and it is the one most others are traced back to.
The word gets misread constantly, and usually in the direction of despair, so here is what it does not mean. It does not mean nobody can tell whether any particular program stops. It does not mean the question is merely difficult. It does not mean a faster computer would help, or that a cleverer person might crack it next year. It means there is no method that always works.
Undecidable is a claim about all inputs at once
Pick any single machine and any single input. Either it stops or it does not, and that fact is already settled, whether or not anyone knows it. For most machines you meet, working out which is easy: the adder from Step 2 obviously stops and a rule that sends the head right forever on blank tape obviously does not.
Undecidability is about the whole collection. There is no one machine that gets every case right. There are always cases left over, and no amount of adding special-case tests to your checker will finish the job, because the argument in Step 5 can be run against your improved checker just as well as against the original.
Then why does my compiler warn me about infinite loops sometimes
A compiler is a program that turns the code a person writes into the instructions a machine runs, and on the way it inspects the code and points out things that look wrong. Those warnings are honest because of how they are phrased. A compiler says "this loop cannot exit", not "this program halts". It only speaks when it is certain, and stays quiet otherwise.
That is allowed, and it is useful. It is not a solution to the halting problem. A checker with three possible answers, yes, no, and I cannot tell, is easy to build and never wrong. A checker with two possible answers that is never wrong is what cannot exist. The lab below is exactly such a three-answer checker. You are invited to defeat it.
true or
false on the first claim. The reason appears underneath it straight away, right or
wrong, and your score updates at the bottom. Work down the list; press Clear my answers to
go round again.Ask the checker without
changing anything. It answers stops, and says how it knows. Your job is to change the
rules or the starting strip so the checker must return cannot tell. Press
Check my machine to have that marked.stops
only after watching a machine stop. It says never stops only when it has caught the machine
in exactly the same situation twice, same state, same square, same tape, which guarantees it will go
round again forever. Everything else gets cannot tell, and no amount of extra cleverness
would ever empty that third box.Is halting the only undecidable thing about programs
Far from it. A result called Rice's theorem says that essentially every interesting question about what a program computes is undecidable. Does this program ever print the number 7. Do these two programs always agree. Does this program ever touch that file. All undecidable, and each one is proved by showing that a machine answering it could be turned into a machine answering the halting problem, which Step 10 shows you how to do.
Questions about how a program is written stay perfectly answerable: how many lines it has, whether a particular word appears, whether every bracket is closed. The line runs between the text of a program and its behaviour. Anything about the text is fair game; almost anything about the behaviour is not.
never stops only when it sees a machine
return to a situation it has been in before, and reports cannot tell the rest of the time.
A colleague says this violates the Step 5 result. Who is right?Answerable, and hopeless anyway
Undecidable is one way to be stuck, and it is the dramatic one. The other way costs far more sleep in practice, because it looks like success right up until the moment you use it on a real amount of data.
Take this question. You have a list of numbers and a target. Is there some group of the numbers that adds up to exactly the target? There is an obvious method: try every possible group and see. That method always finishes, so the question is decidable. It is also unusable, and the lab shows how quickly.
Why the number of groups is 2 multiplied by itself
Go along the list and make one decision per number: in the group, or out of it. Two choices for the first number. For each of those, two choices for the second, so four so far. Then eight, then sixteen. With n numbers you get 2 multiplied by itself n times, which is written 2n and said as "two to the n".
Small numbers hide how fast this moves. Ten numbers give 1024 groups, which is nothing. Twenty give just over a million. Forty give over a million million. Each single extra number doubles the entire pile, which is why the counter in the lab below goes from comfortable to hopeless in about ten presses.
Add one more number ▶
about eight times, pausing to read the counts. Both methods are really run each time and their work
really counted: the top lane scans the list once, the bottom lane tries every group. The right-hand
column shows how many times the count grew when the list got one longer.Counting steps rather than timing seconds
Seconds are a property of the machine you happened to use, the other programs running that day, and how warm the room is. Steps are a property of the method. Run the same method twice on the same input and the seconds differ while the step count is identical, which makes steps the honest thing to compare.
To turn steps into a feel for time you pick a speed and multiply. A modern processor manages something in the region of a billion simple steps a second, and that figure is what the next lab uses. It is a rough figure, deliberately generous, and being generous does not save the exponential method.
Show me the answer. The exact length is worked
out from the speed you picked, and both your guess and the true answer are shown as times. Then change
the speed to a trillion steps a second and press it again.P: the problems that finish in reasonable time
We need a line between methods you can use and methods you cannot, and the line has to be drawn without mentioning any particular computer, because computers keep changing and the line should not.
The line everyone settled on is this. Count the steps as a formula in n, the size of the input. If the formula is n multiplied by itself some fixed number of times, the method is called polynomial and counts as usable. So n, n2, n3 and n5 are all in. If n appears in the exponent instead, as in 2n, it is out.
What n2 and n3 are counting
n2 means n times n. It is the number of ways of picking an ordered pair out of n things, which is why any method that compares everything with everything else lands on it. n3 is n times n times n, the number of ordered triples, and it shows up when a method has three nested walks through the data.
The difference from 2n is which part grows. In n3 the base grows and the exponent is stuck at 3. In 2n the base is stuck at 2 and the exponent grows. That swap is the entire distinction, and the second lab in this step shows how brutal it is.
What people mean by a class of problems
A class is a bag with problems in it, and a rule for what gets in. The bag called P holds every yes-or-no question for which somebody has found a polynomial method. Is this number in this sorted list. Is there a route from this town to that one. Does this list contain a repeat. All in P.
Membership is about the problem, not about your particular attempt at it. A problem is in P the moment any polynomial method exists, even if the method you personally wrote is exponential, and even if nobody has yet noticed the fast method. That last part matters: problems move into P when someone finds a better method, and several famous ones have.
all pairs, then press
Double n ▶ three or four times. Each press really runs the method on a list twice as
long and counts every comparison. Watch the ratio column: it settles near 4, and the widget names the
shape underneath. Then try the other three methods.An n to the hundred method is not reasonable either, so why draw the line there
Because the line has two properties nothing better has managed. It does not change if you swap the kind of machine: a method that is polynomial on a tape machine is polynomial on a laptop, with a different exponent. And polynomials survive being combined, so a polynomial method that calls another polynomial method a polynomial number of times is still polynomial. A line drawn at, say,"under a million steps" has neither property.
The practical defence is that the line turns out to bite. Problems with polynomial methods almost always end up with small exponents, usually 3 or less, once people have worked on them for a while. Problems without one usually have nothing at all. The middle ground the objection worries about is oddly empty.
Find the crossover. The page searches upward from n equals 2 for the
first length where 2n beats n raised to your exponent, and shows both values there.
Then drag the exponent up to 10 and to 20 and find them again.NP: when checking is the easy half
Here is a shape of problem that turns up everywhere once you notice it. Finding an answer looks hopeless. Checking an answer somebody hands you is quick and dull. Timetables, seating plans, delivery routes, packing a van: all the same shape.
The example for this step is colouring. You are given a set of dots with lines drawn between some pairs of them, and three colours. Colour every dot so that no line ever joins two dots of the same colour. Checking a finished colouring means looking at each line once. Producing one from a blank picture is another matter.
Dots and lines: what a graph is
A graph in this sense has nothing to do with charts. It is a set of dots, called nodes, and a set of connections between pairs of them, called edges. That is all. The picture on screen is only one way of drawing it; sliding a dot around changes nothing, because a graph is the pattern of connections and not the positions.
Graphs are used for anything made of things and relations between them: towns and roads, people and friendships, tasks and which must come first. Colouring with the rule that joined dots differ is how timetabling works. Dots are exams, an edge means some student sits both, and a colour is a time slot.
Check it. The edges
are examined one at a time, each lighting up as it is looked at, and the counter shows how many looks it
took. Then press Nudge one dot to recolour a single dot, and press Check it
again to watch the check fail and name the offending line.Let the machine try every colouring, which grinds through the possibilities in order and
keeps a running count of how many it has tried.The bag of problems where a proposed answer can always be checked in polynomial time is called NP. Colouring is in it. So is every problem in P, because if you can find an answer quickly you can certainly check one quickly by finding it yourself and comparing. Whether NP holds anything that P does not is the open question this course is heading towards.
NP does not stand for "not polynomial"
It stands for nondeterministic polynomial time, which is a mouthful from an older way of describing the same bag. Imagine a machine allowed to make guesses, which magically always guesses correctly when a correct guess exists. Such a machine solves colouring in polynomial time by guessing the colours and then checking. Nobody can build one, but it defines the same collection of problems as the checking definition, and the checking definition is the one to keep in your head.
The misreading matters because "not polynomial" would mean NP and P have nothing in common, and the truth is the opposite: every problem in P is also in NP. P sits inside NP. The open question is whether it fills it.
Turning one problem into another
Here is the move that organises the whole field. Suppose you have a problem A you cannot solve, and a problem B someone else can solve. If you can quickly rewrite any question about A as a question about B, in such a way that B's answer gives you A's answer, then B's solver solves A too. That rewriting is called a reduction.
It is worth being slow about the direction, because it is the thing everyone gets backwards. Writing A as B means B is at least as hard as A, never the other way round. A solver for B does A's work as well, so B is carrying more.
An everyday version of the same move
You cannot measure the height of a tall building, but a friend has an accurate way of measuring shadows and angles. You turn your problem into theirs: measure the shadow, measure the angle of the sun, hand those over, get a height back. You have reduced building-measuring to shadow-measuring, and shadow-measuring is now at least as useful as building-measuring.
Notice the shape. The translation has to be something you can actually do, the answer has to come back meaning what you wanted, and none of it says a word about how your friend does the measuring. That indifference is the strength of the method: you can use a solver you know nothing about.
The problem everything gets reduced to in practice is a puzzle made of switches. You have a row of switches, each either on or off, and a list of requirements. Each requirement names a few switches and says "at least one of these is the way I want it". Satisfy every requirement at once, or show that no setting does. This is called satisfiability, or SAT.
Reading a switch puzzle written down
Each switch gets a name. A requirement is written as a short list of switch names inside brackets,
joined by "or". A plain name means that switch must be on to satisfy the requirement; a name with
not in front means it must be off. So (a or not b or c) is satisfied if a is
on, or b is off, or c is on. Each such requirement is called a clause.
You must satisfy every clause at the same time, using one setting of the switches. A single clause is trivial. Hundreds of overlapping clauses, where turning a switch on to rescue one clause breaks three others, is not. Every setting of 20 switches means a million possibilities, and the counting from Step 7 applies exactly.
Translate to a switch
puzzle. One switch appears for every dot-and-colour pair, and the clauses build up in the
panel below, with the count of each kind. Then press Solve the switch puzzle and watch the
answer come back and land on the dots as colours.Add the awkward edge, which joins the hub to the two remaining dots of the
ring so that it touches all five, and watch the solver prove that no setting works at all.Why the translation itself has to be quick
If translating took exponential time, the reduction would prove nothing. You could always "reduce" anything to anything by solving the first problem during the translation and then producing a trivial question with the right answer, which is cheating dressed as a proof.
So the rule is that the translation must be polynomial. In the lab above it is better than that: one clause per dot, three per dot to stop two colours being on at once, and three per edge. That is a fixed amount of work per piece of the picture, and you can watch the clause counter to confirm it grows in step with the number of dots and edges rather than exploding.
follows and does not follow buttons. Each one tells you
whether it was right and why. Then press Point the arrow the other way ⇄ and do all four
again: two of them swap answers.The hardest problems in NP, and what a proof would mean
In 1971 Stephen Cook proved something that sounds too strong to be true, and Leonid Levin proved it independently in the Soviet Union at about the same time. Every single problem in NP can be quickly rewritten as a switch puzzle. Not the ones we have thought of. All of them, including the ones nobody has invented yet.
The sketch is closer to this course than you might expect. A problem is in NP when a checking machine can verify a candidate answer within a polynomial number of steps. That machine is a tape machine, and its whole run over that many steps can be written out as a grid of squares: which symbol is in which square at which moment, where the head is, what the state is. Then you make one switch for each of those facts, and clauses saying the grid describes a legal run that ends in yes. A setting of the switches is a run that accepts, which is a valid answer to the original problem.
How can anyone reduce a problem they have never seen
By reducing the definition rather than the problem. Being in NP already tells you everything the proof needs: there is a checking machine, and it stops within some polynomial number of steps. You never have to know what the problem is about. You only need its checker and the construction turns any checker whatsoever into clauses.
This is the same style of argument as Step 4, where the universal machine ran a program it had never seen by reading its description. Once a machine is a description, general statements about all machines become possible, and Cook's proof is the most powerful thing anybody has done with that.
A problem that is in NP, and that every other NP problem reduces to, is called NP-complete. Cook and Levin showed SAT is one. Richard Karp then showed 21 more within two years by reducing SAT to them, each new one becoming a stepping stone for the next and the list now runs to thousands.
In NP, NP-hard, NP-complete: three different things
In NP means answers can be checked quickly. That is a ceiling on difficulty, and easy problems qualify: adding two numbers is in NP. NP-hard means everything in NP reduces to it, so it is at least as hard as all of them. That is a floor, and it does not require the problem to be in NP at all; the halting problem is NP-hard and is not in NP.
NP-complete means both at once: in NP, and NP-hard. Those are the problems sitting exactly at the top of NP. They are the interesting ones, because a fast method for any single one of them would be a fast method for every problem in NP.
Vertex cover, then press
Suppose this one gets a fast method. The page follows the reduction arrows backwards
from it and lights every problem that would become fast as a result, and says how many and by what
route. Then try it on Two-colouring and on Switch puzzle (SAT).So the question, worth a million dollars from the Clay Mathematics Institute since 2000 and unanswered since 1971, is whether P and NP are the same bag. Nobody has found a fast method for any NP-complete problem, and nobody has proved that none exists. Almost everyone who works on it expects P and NP to be different, which would mean the gap you felt in Lab 18 is real and permanent.
What would actually break if the two turned out to be equal
Most of the locks. Public-key cryptography, which is what makes online payment possible, rests on certain problems being easy to check and hard to solve, which is exactly the NP shape. A fast method for SAT would very likely undo a large part of it. On the other hand, protein folding, chip layout, timetabling and thousands of scheduling problems would fall out at once, which would be a considerable compensation.
Two cautions. A proof might be non-constructive, showing a fast method exists without saying what it is. And a method taking n100 steps would settle the question while changing nothing whatever in practice. Even the dramatic answer might arrive quietly.
a machine that never
stops, then Ask the checker. Nothing here is marked. Load any machine from the
course, take it apart, break it, and see what the checker makes of the wreckage.R to an L: about a third of the time you get an
immediate loop, and the rest of the time it stops early with the job half done. The checker in Step 6
proves almost every one of those loops, which is a small demonstration of why loop bugs are so common and
how much a repeated situation gives away.Decide, recognise and enumerate are different promises
A decider stops on every input and answers yes or no correctly. A recogniser has a weaker contract: it must eventually say yes when the answer is yes, but on a no-instance it may say no or keep running. Watching forever is not a way to confirm no.
The strings accepted by a recogniser form a recognisable language. If both a language and its complement have recognisers, run the two machines a step at a time. One must eventually accept, so together they make a decider. Halting is recognisable: simulate the named program and accept if it stops. Its complement cannot be recognisable, or this two-machine method would decide halting.
Language
A set of finite strings. A decision problem asks whether an input string belongs to it.
Complement
All valid input strings that are not in the language.
Enumerator
A machine that eventually prints every string in a language.
Why enumeration and recognition match
Given an enumerator, wait until the target string appears. Given a recogniser, dovetail it over every possible string and print a string when its run accepts. This is an exact equivalence.
Program text is inspectable; general program behaviour is not
Some properties are about syntax: “does this rule table contain an R?” can be answered by
reading its finite description. Other properties ask what the program computes: “does it accept any
string?” or “does it compute the same function as that program?” Those quantify over behaviour.
Rice’s theorem says every nontrivial semantic property of the partial function computed by a general program is undecidable. Nontrivial means some programs have it and some do not. Useful analysers remain possible by restricting the language, requiring annotations, proving only some cases, or returning unknown.
Unknown can be the correct result
A sound analyser says safe only with a proof. For many behaviours, no analyser can be both sound and complete over all programs. Tests add evidence from selected runs; they do not cover every input.
Complexity counts the input that is actually written down
Running time is measured against encoded input length. One million needs one million marks in unary but only 20 bits in binary. A loop that runs once per numeric value is linear in a unary input and exponential in the length of a binary input.
An algorithm can be pseudo-polynomial: polynomial in a numeric value such as capacity, but exponential in the bits used to write that value. State the encoding, parameters and arithmetic cost model beside a complexity claim.
Arithmetic operations also have a cost
A unit-cost model treats addition or multiplication as one step. For very large integers, their bit lengths matter and arithmetic itself takes more work. State which model is being used before comparing algorithms.
Time, memory and which side has a short proof are separate questions
Time counts steps; space counts simultaneously used memory. Depth-first search can recompute work to save memory. A breadth-first frontier may use much more memory while finding a shallow answer sooner. Real limits include both resources.
NP gives short, quickly checked certificates for yes-instances. coNP contains problems whose no-instances have short certificates, equivalently complements of NP languages. Failing to find an answer is not itself a no-certificate.
Where PSPACE enters
PSPACE allows polynomial memory even when time is much larger. Games and quantified formulas alternate choices. The Complexity Classes course develops this map.
Hardness tells you which promise to change
NP-hard does not mean give up. Engineering can restrict the input, accept an approximation with a proved ratio, isolate a small parameter, spend exponential time on modest instances, or use a heuristic and measure it without calling the answer optimal.
A parameterised method may take f(k)nc time: expensive in a small parameter k but polynomial in total size. Randomised methods need a failure probability. Approximation needs a bound. Heuristics need diverse benchmarks and feasibility checks.
Special cases can be the right specification
Interval graphs, planar graphs, bounded treewidth and metric distances can change what is solvable or approximable. Restricting inputs is legitimate when the real system guarantees that structure and validates it at the boundary.
Modern solvers search better, but checkers still settle the claim
SAT, SMT, constraint-programming and mixed-integer solvers combine propagation, conflict learning, cuts, symmetry handling, restarts and parallel search. They solve many industrial instances without changing the worst-case class.
Learned models can rank branches, propose cuts, generate candidates or predict settings. Treat them as search guides. A deterministic checker should validate the assignment, proof log, schedule, code or bound. Include inference cost and a fallback.
Continue into the advanced map
Continue with Complexity Classes, Algorithm Design and Quantum Algorithms. Quantum computation does not decide halting.
What you can do now
- Write a rule table that computes something, and step it to find out why it does not.
- Explain why a program can be data, and why that makes general-purpose computers possible.
- Walk the halting argument from memory, and spot the two places people usually mangle it.
- Say precisely what undecidable means, and correct the four usual misreadings.
- Tell a polynomial method from an exponential one by doubling the input and watching the ratio.
- State what P, NP and NP-complete are, and get the direction of a reduction right.
- Distinguish deciders, recognisers and enumerators, and explain dovetailing.
- Apply Rice’s theorem without confusing syntax with behaviour.
- Audit encodings, time, space, certificates and practical solver claims.
Where this goes
- Algorithm Design. Exact search, approximation, parameters, heuristics and certificates when the deadline is real.
- Complexity Classes. Space, randomness, counting, interactive proofs and the wider class map.
- Language Engineering. How computability limits shape the promises a compiler and analyser can make.