1.1 The Entscheidungsproblem
Algorithms have been used since antiquity — Euclid’s algorithm for the greatest common divisor, the sieve of Eratosthenes, Gaussian elimination — without any need for a definition of the word. As long as one only wishes to show that a problem can be solved mechanically, it suffices to exhibit a procedure that everybody accepts as mechanical.
The situation changed with the foundational program of Hilbert. In 1928, Hilbert and Ackermann formulated the Entscheidungsproblem: find a procedure which, given a formula of first-order logic, decides in finitely many steps whether this formula is universally valid. Gödel’s incompleteness theorems (1931) made a positive answer increasingly implausible. But a negative answer requires proving that no algorithm solves the problem, and a statement about all algorithms can only be proved once the class of algorithms has been defined mathematically.
Several definitions were proposed between 1931 and 1936:
- the general recursive functions of Herbrand and Gödel (1934), studied systematically by Kleene;
- the λ-definable functions of Church and Kleene (1933–1936);
- the Turing machines (1936), together with the closely related machines of Post (1936).
Church (1936) and Turing (1936) independently gave a negative solution to the Entscheidungsproblem. The three classes of functions were quickly proved to coincide. Turing’s analysis of what a human computer can do was decisive in convincing the community — including Gödel — that the definition was the right one.
Note that the first electronic computers were built a decade later. The notion being formalized is that of a function computable by a human following a finite set of instructions mechanically, with unlimited paper and time.
1.2 Features of an algorithm
Any proposed definition should respect the following features of the informal notion.
- Finite description. An algorithm is described by a finite text, fixed in advance, independent of the input.
- Discrete and deterministic steps. The computation proceeds in steps. At each step, the next action is completely determined by the current situation, and each action is elementary — it requires no insight.
- Unbounded resources. No bound is fixed in advance on the number of steps or on the amount of memory. A computation which terminates has however only performed finitely many steps, and therefore used only finitely much memory.
- Possible non-termination. Nothing guarantees that a computation terminates. An algorithm therefore defines a partial function, undefined on the inputs on which the computation does not terminate.
Points 3 and 4 distinguish computability theory from complexity theory: we study what can be computed in principle, not what can be computed within given resources. Point 4 is not a defect of the definitions. We will see in the course on fundamentals that it cannot be avoided: there is no programming language with a computable interpreter whose programs compute exactly the total computable functions.
1.3 Partial functions
Throughout the course, , and abbreviates a tuple whose length is clear from the context.
A partial function is a function from a subset , its domain, to . We write (” converges on ”) if , and (” diverges on ”) otherwise. We write when and . A partial function is total if .
Total functions are particular partial functions. The image of is . The empty function, with empty domain, is denoted when no confusion is possible.
When partial functions are composed, an expression may be undefined. We adopt the following convention: an expression built from partial functions is defined only if all its subexpressions are defined. For instance, requires and to converge on the value . In particular, is undefined when : we never evaluate an expression “lazily”.
For two expressions built from partial functions, we write (Kleene equality) to mean that either both are undefined, or both are defined and have the same value.
For instance, two partial functions are equal if and only if for all . Some authors simply write for ; we will do so in later courses, when no ambiguity can arise.
1.4 Coding finite objects by integers
Algorithms manipulate finite objects: integers, but also tuples, finite sequences, strings, formulas, graphs, and programs. We will mostly study functions on . This is no restriction, because all these objects can be coded by integers in such a way that the usual operations on them become computable operations on the codes. The basic tool is a bijection between and .
Cantor’s pairing function is the function defined by
The pairs are enumerated diagonal by diagonal: , , , , , , and so on. Write for the -th triangular number.
The function is a bijection from to .
Fix . Since is strictly increasing with , there is a unique such that . Let , so that , and let . Then and , so the function is surjective.
For injectivity, suppose , and let , . Since , we have , and similarly for . By uniqueness of above, ; then and .
The inverse functions with and are computed by the procedure of the proof: find with by trying , then set and . Only a bounded search is needed, since . This remark will become important when we study primitive recursive functions.
Iterating the pairing function codes tuples of any fixed length: , and in general . For each this gives a bijection . Finite sequences of arbitrary length require a little more care, since the length must be recoverable from the code; this is done in the lesson Coding finite sequences.
Strings over a finite alphabet are coded by reading them as numerals in base with digits (bijective numeration): the string is coded by , which defines a bijection between strings and , the empty string being coded by . Programs, being strings, are coded the same way. With these codings, a function on finite objects is called computable if the corresponding function on codes is.
1.5 Exercises
Show that the function , is a bijection. Compare it with Cantor’s pairing function: which one is more economical, in the sense of the size of as a function of ?
Solution
Every integer is uniquely of the form with odd, that is . So is a bijection from onto , and subtracting gives a bijection onto . On the diagonal, grows exponentially, whereas is quadratic. Cantor’s pairing is a polynomial bijection; by a theorem of Fueter and Pólya, it is, up to exchanging the coordinates, the only quadratic polynomial bijection from to .
Show that and for all , with equality only when , or for the first inequality.
Solution
. Since , we get , and . Since , equality forces , and then , i.e. . Equality forces , i.e. .
1.6 Notes and references
The Entscheidungsproblem is formulated in Hilbert and Ackermann’s textbook Grundzüge der theoretischen Logik (Springer, 1928). Its negative solution was obtained independently by Church and by Turing in 1936. The quadratic polynomial bijections were determined by Fueter and Pólya (1923): up to the exchange of coordinates, Cantor’s pairing function is the only one.
- A. Church, An unsolvable problem of elementary number theory, American Journal of Mathematics 58 (1936), 345–363.
- A. M. Turing, On computable numbers, with an application to the Entscheidungsproblem, Proceedings of the London Mathematical Society (2) 42 (1936), 230–265.
- R. Soare, Turing Computability: Theory and Applications, Springer, 2016, chapter 1, for a historical account.