What are the limits (if any) of computers?
To answer this question, we need to clarify the notions of computer and computation
A good theory should be as simple as possible, but not simpler.
—Albert Einstein
A computation is any process that can be described by a set of unambiguous instructions.
Alan Turing invented the idea of a Turing Machine in 1935-36 to describe computations.
State | Symbol | New State | New Symbol | Move |
1 | 0 | 1 | 1 | R |
1 | 1 | 1 | 0 | R |
1 | b | 2 | b | R |
Start State: 1
Halt State: 2
This Turing machine can be viewed as a function that takes an input sequence and returns the corresponding inverted sequence (all 1's replaced by 0's and vice versa).
1100 --> 0011
01
--> 10
Turing machine description:
(1, 0, 1,
1, R)
(1, 1, 1, 0,
R)
(1, b, 2, b, R)
Turing Machine Simulator from The Analytical Engine
Turing Machine Simulator from Buena Vista UniversityIs this really enough to compute everything?
Consider:
Church-Turing
Thesis Anything that can be computed can be computed by a Turing machine |
Choice of programming language doesn't really matter — all are "Turing equivalent"
When we talk about Turing machines, we're really talking about computer programs in general.
Corollary If the human mind is really a kind of computer, it must be equivalent in power to a Turing machine |
Is there anything a Turing machine cannot do, even in principle? YES!
Example: Looper TM eventually halts on input 0000bbb... but loops forever on input 0000111bbb...
No Turing machine can infallibly tell if another Turing machine will get stuck in an infinite loop on some given input.
In other words, no computer program can infallibly tell if another computer program will ever halt on some given input.
Put another way, no computer program can infallibly tell if another program is completely free of bugs.
How did Turing prove that such a program is in principle impossible?
We'll use JavaScript instead of Turing machines to illustrate the argument, but the argument is valid no matter what language we use to describe computations (JavaScript, BASIC, Turing machines, Excel, etc.)
Turing's approach was to assume that a loop-detector program could be written.
He then showed that this leads directly to a logical contradiction!
So, following in Turing's steps, let's just assume that it's possible to write a JavaScript program that correctly tells whether other JavaScript programs will eventually halt when given particular inputs. Let's call our hypothetical program WillHalt.
function WillHalt(program, data) {
.
.
.
... lots of complicated code ...
.
.
.
if ( ...more code... ) {
return true;
} else {
return false;
}
}
For example, let's write a couple of simple JavaScript programs to test
WillHalt:
function Halter(input) {
alert('done');
}
function Looper(input) {
while (input == 1) {
input = 1;
}
}
Halter always halts, no matter what input we feed it:
WillHalt("function Halter(input){alert('done');}", 1) returns true
WillHalt("function Halter(input){alert('done');}", 2) returns true
Looper loops forever if we happen to feed
it the value 1. Any other value will cause it to halt:
WillHalt("function Looper(input){while(input==1){input=1;}}", 1) returns false
WillHalt("function Looper(input){while(input==1){input=1;}}", 2) returns true
So far, we have every reason to believe that WillHalt could exist, at least in principle, even though it might be a rather hard program to write.
At this point, Turing says "OH YEAH? If WillHalt
exists, then I can define the following program called Turing,
which accepts any JavaScript program as its input..."
function Turing(program)
{
var n;
if (WillHalt(program,
program) == true) {
while
(2 + 2 == 4) {
n = 0;
}
} else {
alert('done');
}
}
"Yes," we say, "so what?"
Turing laughs and says "Well what happens when I feed the Turing program to itself?"
What happens indeed? Let's analyze the situation:
Thus our original assumption about the existence of WillHalt must have been invalid, since as we've seen, it's easy to define the logically-impossible Turing program if WillHalt is available to us.
Q.E.D.
Conclusion The task of deciding if an arbitrary computation will ever terminate cannot be described computationally. |
Turing discovered another amazing fact about Turing machines:
A single Turing machine, properly programmed, can simulate any other Turing machine.
Such a machine is called a Universal Turing Machine (UTM)
How can we "encode" a Turing machine? Here's one way:
Example: Looper TM
States: 1, 2 --> 0, 00
Symbols: 0, 1, b -->
0, 00, 000
Moves: L,
R --> 0, 00
Rule 1: (1, 0, 1, 0, R) -->
0101010100
Rule 2: (1, 1, 1, 1, L)
--> 01001010010
Rule 3: (1,
b, 2, b, R) -->
010001001000100
1110101010100110100101001011010001001000100111
We could run our hypothetical Loop-detector Turing machine on the above encoding with the input 0000111:
Eventually the machine would halt with a single 1 as output, meaning an infinite loop was detected:
But, alas, we know that such a loop-detecting Turing machine is impossible, as Turing showed.