Chapter 10 Computable Functions 1 Copyright © 2011 The McGraw-Hill Companies, Inc. Permission required for reproduction or display. Primitive Recursive Functions • We have defined a function to be computable if there is a Turing machine that computes it. Most functions are not computable (the set of functions from ℕ to ℕ is uncountable, and the set of Turing machines is countable). It would be desirable to have a clearer idea of what sorts of functions can be computed • In this chapter we present an approach due to Kleene. We start with a set of initial functions and develop some operations on functions that preserve computability. We will eventually describe operations that produce all computable functions Introduction to Computation 2 Primitive Recursive Functions (cont’d.) • Definition 10.1: The initial functions are the following: – Constant functions: For each k 1 and each a 0, the constant function Cak : ℕk ℕ is defined by the formula Cak(X) = a for every X ℕk – The successor function s : ℕ ℕ is defined by the formula s(x) = x + 1 – Projection functions: For each k 1 and each i with 1 i k, the projection function pik : ℕk ℕ is defined by the formula pik(x1, … , xi, …, xk) = xi Introduction to Computation 3 Primitive Recursive Functions (cont’d.) • Definition 10.2: – Suppose f is a partial function from ℕk to ℕ, and for each i with 1 i k, gi is a partial function from ℕm to ℕ. The partial function obtained from f and g1, … , gk by composition is the partial function h from ℕm to ℕ defined by the formula h(X) = f (g1(X),…, gk(X)) for every X ℕm Introduction to Computation 4 Primitive Recursive Functions (cont’d.) • Definition 10.2 (cont’d.) – Suppose n 0, and g and h are functions of n and n+2 variables, respectively – The function obtained from g and h by the operation of primitive recursion is the function f : ℕn+1 ℕ defined by the formula f (X, 0) = g(x); f(X, k+1) = h(X, k, f (X, k)) for every X ℕn and every k 0 Introduction to Computation 5 Primitive Recursive Functions (cont’d.) • A function obtained by either of these operations from total functions is a total function • If f is obtained from g and h by primitive recursion, and g(X) is undefined for some X, then f (X,i) is undefined for all X, i • Similarly if f (X, k) is undefined for some k, say k = k0, then f (X, k) is undefined for k k0 Introduction to Computation 6 Primitive Recursive Functions (cont’d.) • Definition 10.3: The set PR of primitive recursive functions is defined as follows: – All initial functions are elements of PR – For every k 0 and m 0, if f : ℕk ℕ and g1, …, gk : ℕm ℕ are elements of PR, then the function f (g1, …, gk) obtained from f and g1, …, gk by composition is an element of PR – For every n 0, every function g : ℕn ℕ in PR, and every function h : ℕn+2 ℕ in PR, the function f : ℕn+1 ℕ obtained from g and h by primitive recursion is in PR Introduction to Computation 7 Primitive Recursive Functions (cont’d.) • In other words, the set PR is the smallest set of functions that: – Contains all the initial functions – Is closed under the operations of composition and primitive recursion • The initial functions are computable • The set of computable functions is also closed under the operations of composition and primitive recursion. (We can describe TMs to compute the functions obtained by these operations) Introduction to Computation 8 Primitive Recursive Functions (cont’d.) • Theorem 10.4: Every primitive recursive function is total and computable – Proof: This follows from the Church-Turing thesis and the previous observations • We can define the arithmetic operations Add(x, y) and Mult(x, y), and they are both primitive recursive. So is Sub(x, y), which is defined in terms of a predecessor function Pred(x ). We must be slightly careful, because ordinary subtraction doesn’t always produce natural numbers. On the slides we continue to use the minus sign (-) for “proper subtraction” Introduction to Computation 9 Primitive Recursive Functions (cont’d.) • An n-place predicate P is a function or partial function from ℕn to the set {true, false} – The corresponding numeric function is the characteristic function P defined by P(X) = 1 if P(X) is true, 0 if P(X) is false • By definition, the predicate P is primitive recursive, or computable, if the characteristic function P is Introduction to Computation 10 Primitive Recursive Functions (cont’d.) • Theorem 10.6: – The two-place predicates LT, EQ, GT, LE, GE, and NE are primitive recursive (LT corresponds to <, EQ to =, etc.) – If P and Q are any primitive recursive n-place predicates then P Q, P Q, and P are primitive recursive • Proof: the second half follows from the equations – P1 P2 = P1 * P2 – P 1 P 2 = P 1 + P 2 - P 1 P 2 – P = 1 - P1 Introduction to Computation 11 Primitive Recursive Functions (cont’d.) • To prove the first part, we introduce the function Sg: ℕ ℕ defined by Sg(0)=0, Sg(k+1) = 1. This is clearly primitive recursive • Now: – LT(x, y) = Sg(y - x) – EQ(x, y) = Sub(1, (Sg(x - y) + Sg(y - x)) – EQ(x, y) = Sub(1, (Sg(x - y) + Sg(y - x)) – LE = LT EQ – GT = LE – GE = LT – NE = EQ Introduction to Computation 12 Primitive Recursive Functions (cont’d.) • Theorem 10.7: – Suppose f1, … , fk are primitive recursive functions from ℕm to ℕ; P1, … , Pk are primitive recursive n-place predicates; and for every X ℕn, exactly one of the conditions P1(X), … , Pk(X) is true – Then the function f (X), which for each i is defined to be fi (X) if Pi(X) is true, is primitive recursive • Proof: f = f1 * P1 + … + f1 * P because of the definition of f and the assumption on the Pi’s Introduction to Computation 13 Primitive Recursive Functions (cont’d.) • The Div and Mod functions are primitive recursive if we take as part of the definition that for any x, Div(x, 0) = 0 and Mod(x, 0) = x • This will be useful later Introduction to Computation 14 Quantification, Minimalization, and -Recursive Functions • The operations that can be applied to predicates to produce new ones include not only the logical operations, but also universal and existential quantification • Here’s an example. If Sq(x, y) = (x = y2) the existential quantification of Sq would be the predicate PerfectSquare: PerfectSquare(x) = (there exists y such that Sq(x, y)) • Sq is a primitive recursive predicate; in this example, the existential and universal quantifications are also. This is not always the case Introduction to Computation 15 Quantification, Minimalization, and -Recursive Functions (cont’d.) • Suppose that for x ≥ 0, sx denotes the xth string in {0,1}* in canonical order, and suppose Tu is a universal TM. Let H(x,y) be the predicate H(x,y) = (Tu halts after y moves on input sx) The existential quantification of H is the predicate Halts(x) = (there exists y such that H(x,y)) • H(x,y) is computable and even primitive recursive. However, Halts cannot be computable, because the halting problem is undecidable Introduction to Computation 16 Quantification, Minimalization, and Recursive Functions (cont’d.) • We infer that quantification does not preserve computability nor primitive recursiveness • Definition 10.9: Let P be an (n+1)-place predicate – The bounded existential quantification of P is the (n+1)-place predicate EP defined by EP(X, k) = (there exists y with 0 y k such that P(X, y) is true) – The bounded universal quantification of P is the (n+1)-place predicate AP defined by AP(X, k) = (for every y with 0 y k, P(X, y) is true) Introduction to Computation 17 Quantification, Minimalization, and Recursive Functions (cont’d.) • Theorem 10.10: – If P is a primitive recursive (n+1)-place predicate, both the predicates EP and AP are also primitive recursive • Proof sketch: – The characteristic function of AP(X,k) can be expressed as a “bounded product” of the functions P(X, i) for 0 i k, and as a result it is primitive recursive. – The result for the existential quantification follows from the formula EP(X,k) = A P(X,k) Introduction to Computation 18 Quantification, Minimalization, and Recursive Functions (cont’d.) • The bounded quantifications in this section preserve primitive recursiveness and computability – The unbounded versions do not • In order to separate the computable functions from the primitive recursive ones, we need at least one operation that preserves computability but not primitive recursiveness – The operation of minimalization turns out to have this feature – Minimalization also has a bounded and an unbounded version Introduction to Computation 19 Quantification, Minimalization, and Recursive Functions (cont’d.) • Definition 10.11: For an (n+1)-place predicate P, the bounded minimalization of P is the function mP : ℕn+1 ℕ defined by mP(X, k) = min {y | 0 y k and P(X, y)} if this set is empty, and k+1 otherwise – The symbol is often used for the minimalization operator, and we sometimes write mP(X, k) = k y[ P(X, y) ] – In the special case in which P(X, y) is (f (X, y) = 0), mP is written mf and we refer to it as the bounded minimalization of f Introduction to Computation 20 Quantification, Minimalization, and Recursive Functions (cont’d.) • Theorem 10.12: – If P is a primitive recursive (n+1)-place predicate, its bounded minimalization mP is a primitive recursive function • Proof: by construction using primitive recursive constructs – See book for details. • PrNo(n), the nth prime number, is primitive recursive – For details, see book Introduction to Computation 21 Quantification, Minimalization, and Recursive Functions (cont’d.) • Definition 10.14: If P is an (n+1)-place predicate, the unbounded minimalization of P is the partial function MP : ℕn ℕ defined by MP(X) = min{y | P(X,y) is true} – MP(X) is undefined at any X ℕn for which there is no y satisfying P(X, y) – The notation y[P(X,y)] is also used for MP(X) – In the special case where P(X,y) = (f (X, y) = 0), we write MP = Mf and refer to this function as the unbounded minimalization of f Introduction to Computation 22 Quantification, Minimalization, and Recursive Functions (cont’d.) • Definition 10.15: The set M of -recursive, or simply recursive, partial functions is defined as follows: – Every initial function is an element of M – Every function obtained from elements of M by composition or primitive recursion is an element of M – For every n 0 and every total function f : ℕn+1 ℕ in M, the function Mf : ℕn ℕ defined by Mf (X) = y[f (X, y)=0] is an element of M Introduction to Computation 23 Quantification, Minimalization, and Recursive Functions (cont’d.) • Theorem 10.16: All -recursive partial functions are computable. • Proof: For a proof using structural induction, it is sufficient to show that if f : ℕn+1 ℕ is a computable total function, then its unbounded minimalization Mf is a computable partial function • If Tf is a Turing machine computing f, a TM T computing Mf operates on an input X by computing f (X, 0), f (X, 1),… until it discovers an i for which f (X, i) = 0, and halting in ha with i as its output Introduction to Computation 24 Gödel Numbering • In 1930’s, Kurt Gödel developed a method of “arithmetizing” a formal axiomatic system by assigning numbers to statements and formulas – This allowed him to describe relationships between objects in the system using relationships between the corresponding numbers • This led to Gödel’s Incompleteness Theorem: – Any formal system comprehensive enough to include the laws of arithmetic must, if it is consistent, contain true statements that cannot be proved within the system • Gödel numbering will be useful in this chapter also Introduction to Computation 25 Gödel Numbering (cont’d.) • Definition 10.17: For every n 1 and every finite sequence x0, x1, … , xn-1 of n natural numbers, the Gödel number of the sequence is the number gn(x0, x1, … , xn-1)=2x03x1…(PrNo(n -1))xn-1 where PrNo(i) is the ith prime – Every sequence of length n is uniquely determined by its Gödel number – If two sequences of different length have the same Gödel number, then they must agree except for the number of trailing 0’s Introduction to Computation 26 Gödel Numbering (cont’d.) • Every positive integer is the Gödel number of some sequence of integers • For every n, the Gödel numbering determines a function from ℕn to ℕ – We will be imprecise and use the name gn for any of these functions – All of them are primitive recursive – The function Exponent: ℕ2 ℕ, defined by Exponent(i, x) = the exponent of PrNo(i) in x’s prime factorization or 0 if i is 0, is primitive recursive • See book for details Introduction to Computation 27 Gödel Numbering (cont’d.) • For many functions that are defined recursively, the definition does not make it obvious that the function is obtained by primitive recursion – For example, the right side of the formula f (n+1) = f (n) + f (n -1) is not of the form h(n, f (n)) – In general f (n+1) might depend on several, or even all, of the terms f (0), f (1), … , f (n) – This type of recursion is known as course-of-values recursion • It is related to primitive recursion as strong induction is related to ordinary mathematical induction Introduction to Computation 28 Gödel Numbering (cont’d.) • Gödel numbering gives us a way to formulate definitions of this type. Suppose f (n+1) depends on f (0), f (1), … , f (n), and also directly on n. We’d like another function f1 so that f1(n+1) depends only on n and f1(n), and knowing f1 allows us to calculate f. – If we could allow f1(n) to be the entire sequence (f (0), f (1), … , f (n)), instead of a number, we’d have what we want. – Instead we can use the Gödel number of the sequence, because gn(f (0), … , f (n)) has enough information to determine each f (i) – This allows us to use course-of-values recursion Introduction to Computation 29 Gödel Numbering (cont’d.) • Theorem 10.19: Suppose that g : ℕn ℕ and h : ℕn+2 ℕ are primitive recursive functions, and f : ℕn+1 ℕ is obtained from g and h by course-ofvalues recursion; that is, f (X, 0) = g(X); f (X, k+1) = h(X, k, gn(f (X,0),…f (X,k))), then f is primitive recursive. • Now we can apply Gödel numbering techniques to Turing machines Introduction to Computation 30 Gödel Numbering (cont’d.) • A TM move can be interpreted as a transformation of one TM configuration to another • To arithmetize this, we need a way of characterizing a TM configuration by a number – Assign a number to each state • ha gets 0, hr gets 1, and 2 represents the initial state – The tape head position is simply the number of the current tape square – Tape symbols get numbers too, with = 0 – The current tape number tn of the TM is the Gödel number of the sequence of symbols on the tape Introduction to Computation 31 Gödel Numbering (cont’d.) • The configuration of the TM is determined by the state, tape head position and current contents of the tape, and we define the configuration number to be gn(q, P, tn), where q is the number of the current state, P is the current tape head position, and tn is the tape number • From the configuration number, we can reconstruct all of the details of the TM’s configuration Introduction to Computation 32 All Computable Functions are Recursive • Suppose that f : ℕn ℕ is a partial function computed by the TM T • To compute f (X), T does these things: – It starts in the standard initial configuration corresponding to X – It carries out a sequence of moves – It ends up in an accepting configuration, if X is in the domain of f, with a string representing f (X) on the tape Introduction to Computation 33 All Computable Functions are Recursive • Each move of the computation transforms one configuration number to another • Thus, f (X) = ResultT(fT(InitConfig(n)(X))) – Here InitConfig(n)(X) is the configuration number of the initial configuration corresponding to input X – fT is the function that transforms the initial configuration number to the final one, corresponding to the computation of T – ResultT (j) is the value y if j is the number of a configuration in which the output is y Introduction to Computation 34 All Computable Functions are Recursive (cont’d.) • In order to show that f is -recursive, it will be sufficient to show that each of the three functions on the right side of the formula is • The two outer ones, ResultT and InitConfig(n) are actually primitive recursive • fT is not generally primitive recursive – It is defined in a way that involves unbounded minimalization and is defined only at configuration numbers corresponding to n-tuples in the domain of f Introduction to Computation 35 All Computable Functions are Recursive (cont’d.) • InitConfig(n) : ℕn ℕ – It is easy to see that this is primitive recursive • IsConfigT is the one-place predicate defined by IsConfigT(n) = (n is a configuration number for T) – It is primitive recursive because it can be computed using bounded universal quantification • IsAcceptingT(m) = 0 if IsConfigT(m)∧Exponent(0,m)=0, 1 otherwise – It is primitive recursive because IsConfigT and Exponent are primitive recursive Introduction to Computation 36 All Computable Functions are Recursive (cont’d.) • ResultT(n) = HighestPrime(Exponent(2,n)) if IsConfigT(n), and 0 otherwise – It is primitive recursive because HighestPrime is • Some helper functions that are all primitive recursive – – – – State(m) = Exponent(0,m) Posn(m) = Exponent(1,m) TapeNumber(m) = Exponent(2,m) Symbol(m) = Exponent(Posn(m), TapeNumber(m)) Introduction to Computation 37 All Computable Functions are Recursive (cont’d.) • A single move may result in new values for any or all of those four quantities – We have corresponding functions: – NewState, NewPosn, NewTapeNumber, and NewSymbol – All of these are primitive recursive • The function MoveT : ℕ ℕ is defined by MoveT(m) = gn(NewState(m),NewPosn(m), NewTapeNum(m)) if IsConfigT(m), and 0 otherwise – This is primitive recursive Introduction to Computation 38 All Computable Functions are Recursive (cont’d.) • MovesT(m,0) = m if IsConfigT(m), and 0 otherwise • MovesT(m,k+1) = MoveT(Moves(m,k)) if IsConfigT(m), and 0 otherwise • MovesT is obtained by primitive recursion from two primitive recursive functions – Is itself primitive recursive • Define NumberOfMovesToAcceptT : ℕ ℕ by the formula NumberOfMovesToAcceptT(m) = k[AcceptingT(MovesT(m,k))=0] – This is -recursive, because it uses unbounded minimalization Introduction to Computation 39 All Computable Functions are Recursive (cont’d.) • Theorem 10.20: Every Turing-compatible partial function from ℕn to ℕ is -recursive • Proof: use previous definitions Introduction to Computation 40 Other Approaches to Computability • Unrestricted grammars provide a way of generating languages, and they can also be used to compute functions • If G=(V, , S, P) is a grammar, and f is a partial function from * to *, G is said to compute f if there are variables A, B, C, and D in the set V such that for every x and y in *, f (x) = y if and only if AxB G* CyD • It can be shown that the functions computable this way are the same as the ones computable by TMs Introduction to Computation 41 Other Approaches to Computability (cont’d.) • Computer programs can be viewed as computing functions from strings to strings • The Church-Turing thesis asserts that every function computable by a high-level programming language is Turing-computable • On the other hand, we can simulate a TM in any modern programming language • Therefore, high-level languages and TMs have equivalent power Introduction to Computation 42