Cite

This course has no released version yet: the text at this address may change. Cite a released version when one exists.

/courses/models-of-computation/primitive-recursion
@misc{models-of-computation-primitive-recursion,
  title = {{Primitive recursive functions}},
  howpublished = {Lesson 5 of \emph{Models of computation}, Computability Theory course notes},
  url = {/courses/models-of-computation/primitive-recursion},
  note = {Unreleased working version}
}

To cite a single statement, use the # link that appears next to its heading.

Lesson 5 of 13

Primitive recursive functions

Definition of the primitive recursive functions and predicates, and their closure under definition by cases, bounded sums and products, bounded quantification and bounded minimization.

45 min6 questions
Models of computation · lesson 5 of 13
  1. Algorithms and partial functions
  2. Turing machines
  3. Programming Turing machines
  4. Register machines
  5. Primitive recursive functions
  6. Coding finite sequences
  7. The Ackermann function
  8. Minimization and partial recursive functions
  9. LOOP and WHILE programs
  10. The λ-calculus
  11. Computing with λ-terms
  12. Equivalence of the models
  13. The Church–Turing thesis

Machines describe computations step by step. A different approach, due to Dedekind, Skolem, Gödel, Herbrand and Kleene, describes computable functions by the way they are defined: one starts from a few functions whose computability is evident, and closes them under operations which evidently preserve computability. In this lesson we study the functions obtained using composition and recursion on one argument. They form a large class of total computable functions, and the tools developed here are used throughout the course.

5.1 Definition

Definition 5.1.#

The basic functions are:

  • the zero function Z:N→NZ : \nat \to \nat, Z(x)=0Z(x) = 0;
  • the successor function S:N→NS : \nat \to \nat, S(x)=x+1S(x) = x + 1;
  • the projections pik:Nk→Np^k_i : \nat^k \to \nat, pik(x1,…,xk)=xip^k_i(x_1, \dots, x_k) = x_i, for 1≤i≤k1 \leq i \leq k.
Definition 5.2.#
  1. Composition. Given h:Nm→Nh : \nat^m \to \nat and g1,…,gm:Nk→Ng_1, \dots, g_m : \nat^k \to \nat, the function f=h∘(g1,…,gm):Nk→Nf = h \circ (g_1, \dots, g_m) : \nat^k \to \nat is defined by
f(x⃗)=h(g1(x⃗),…,gm(x⃗)).f(\vec x) = h(g_1(\vec x), \dots, g_m(\vec x)).
  1. Primitive recursion. Given g:Nk→Ng : \nat^k \to \nat and h:Nk+2→Nh : \nat^{k+2} \to \nat, the function f:Nk+1→Nf : \nat^{k+1} \to \nat is defined by
f(x⃗,0)=g(x⃗),f(x⃗,y+1)=h(x⃗,y,f(x⃗,y)).f(\vec x, 0) = g(\vec x), \qquad f(\vec x, y + 1) = h(\vec x, y, f(\vec x, y)).

For k=0k = 0, the scheme reads f(0)=af(0) = a and f(y+1)=h(y,f(y))f(y + 1) = h(y, f(y)), for a constant a∈Na \in \nat.

By induction on yy, the equations of the recursion scheme define a unique total function ff.

Definition 5.3.#

The class of primitive recursive functions is the smallest class of functions Nk→N\nat^k \to \nat (k≥1k \geq 1) containing the basic functions and closed under composition and primitive recursion.

Equivalently, a function is primitive recursive if it has a derivation: a finite sequence of functions f1,…,fnf_1, \dots, f_n, each of which is a basic function or is obtained from earlier functions of the sequence by composition or primitive recursion, the last one being the function in question.

Proposition 5.4.#

Every primitive recursive function is total and computable.

Proof of Proposition 5.4.

By induction on derivations. Basic functions are total and computable. If g1,…,gmg_1, \dots, g_m and hh are, so is their composition: compute the values gi(x⃗)g_i(\vec x), then hh on them. If gg and hh are, then f(x⃗,y)f(\vec x, y) is computed by the loop: v←g(x⃗)v \leftarrow g(\vec x); for z=0,…,y−1z = 0, \dots, y - 1, v←h(x⃗,z,v)v \leftarrow h(\vec x, z, v); return vv. This loop is executed exactly yy times, so it terminates.

Derivations are finite objects, so there are countably many primitive recursive functions, and their derivations can be effectively listed. This remark is the starting point of the proof, in the lesson The Ackermann function, that not every total computable function is primitive recursive.

5.2 First closure properties

Lemma 5.5.#

The primitive recursive functions are closed under explicit transformations: if f:Nm→Nf : \nat^m \to \nat is primitive recursive and i1,…,im∈{1,…,k}i_1, \dots, i_m \in \{1, \dots, k\}, then g(x1,…,xk)=f(xi1,…,xim)g(x_1, \dots, x_k) = f(x_{i_1}, \dots, x_{i_m}) is primitive recursive. In particular one may permute variables, identify them, and add dummy variables. The constant functions cak(x⃗)=ac^k_a(\vec x) = a are primitive recursive.

Proof of Lemma 5.5.

g=f∘(pi1k,…,pimk)g = f \circ (p^k_{i_1}, \dots, p^k_{i_m}). For constants, ca1=S∘⋯∘S∘Zc^1_a = S \circ \cdots \circ S \circ Z with aa applications of SS, and cak=ca1∘p1kc^k_a = c^1_a \circ p^k_1.

From now on we write definitions informally, as systems of equations, and leave the explicit use of projections and constants to the reader.

Arithmetic. The following functions are primitive recursive:

  • addition: x+0=xx + 0 = x, x+(y+1)=S(x+y)x + (y + 1) = S(x + y). Formally, g=p11g = p^1_1 and h=S∘p33h = S \circ p^3_3.
  • multiplication: x⋅0=0x \cdot 0 = 0, x⋅(y+1)=x⋅y+xx \cdot (y + 1) = x \cdot y + x.
  • exponentiation: x0=1x^0 = 1, xy+1=xy⋅xx^{y+1} = x^y \cdot x (so that 00=10^0 = 1).
  • factorial: 0!=10! = 1, (y+1)!=y!⋅(y+1)(y + 1)! = y! \cdot (y + 1).
  • predecessor: pred(0)=0\mathrm{pred}(0) = 0, pred(y+1)=y\mathrm{pred}(y + 1) = y.
  • truncated subtraction: x−˙0=xx \dotminus 0 = x, x−˙(y+1)=pred(x−˙y)x \dotminus (y + 1) = \mathrm{pred}(x \dotminus y). Thus x−˙y=x−yx \dotminus y = x - y if x≥yx \geq y and 00 otherwise.
  • sign functions: sg(x)=1−˙(1−˙x)\mathrm{sg}(x) = 1 \dotminus (1 \dotminus x), equal to 00 if x=0x = 0 and 11 otherwise, and sg‾(x)=1−˙x\overline{\mathrm{sg}}(x) = 1 \dotminus x.
  • distance: ∣x−y∣=(x−˙y)+(y−˙x)|x - y| = (x \dotminus y) + (y \dotminus x); also min⁡(x,y)=x−˙(x−˙y)\min(x, y) = x \dotminus (x \dotminus y) and max⁡(x,y)=x+(y−˙x)\max(x, y) = x + (y \dotminus x).

5.3 Predicates

Definition 5.6.#

A predicate (or relation) P⊆NkP \subseteq \nat^k is primitive recursive if its characteristic function χP\chi_P, equal to 11 on PP and to 00 outside PP, is primitive recursive.

We write P(x⃗)P(\vec x) for x⃗∈P\vec x \in P.

Proposition 5.7.#

The relations x=yx = y, x≠yx \neq y, x<yx < y, x≤yx \leq y are primitive recursive. Primitive recursive predicates are closed under ¬\neg, ∧\wedge, ∨\vee, →\rightarrow.

Proof of Proposition 5.7.

χ<(x,y)=sg(y−˙x)\chi_{<}(x, y) = \mathrm{sg}(y \dotminus x), χ≤(x,y)=χ<(x,y+1)\chi_{\leq}(x, y) = \chi_<(x, y + 1), χ=(x,y)=sg‾(∣x−y∣)\chi_=(x, y) = \overline{\mathrm{sg}}(|x - y|), and χ≠=1−˙χ=\chi_{\neq} = 1 \dotminus \chi_=. For the connectives, χ¬P=1−˙χP\chi_{\neg P} = 1 \dotminus \chi_P, χP∧Q=χP⋅χQ\chi_{P \wedge Q} = \chi_P \cdot \chi_Q, χP∨Q=sg(χP+χQ)\chi_{P \vee Q} = \mathrm{sg}(\chi_P + \chi_Q), and P→QP \rightarrow Q is ¬P∨Q\neg P \vee Q.

Proposition 5.8 (Definition by cases).#

Let P1,…,Pn⊆NkP_1, \dots, P_n \subseteq \nat^k be primitive recursive predicates such that every x⃗\vec x satisfies exactly one of them, and let g1,…,gn:Nk→Ng_1, \dots, g_n : \nat^k \to \nat be primitive recursive. Then the function ff defined by f(x⃗)=gi(x⃗)f(\vec x) = g_i(\vec x) if Pi(x⃗)P_i(\vec x) is primitive recursive.

Proof of Proposition 5.8.

f(x⃗)=g1(x⃗)⋅χP1(x⃗)+⋯+gn(x⃗)⋅χPn(x⃗)f(\vec x) = g_1(\vec x) \cdot \chi_{P_1}(\vec x) + \cdots + g_n(\vec x) \cdot \chi_{P_n}(\vec x).

5.4 Bounded sums, products and quantifiers

Proposition 5.9.#

If f:Nk+1→Nf : \nat^{k+1} \to \nat is primitive recursive, so are

s(x⃗,y)=∑z<yf(x⃗,z)andp(x⃗,y)=∏z<yf(x⃗,z),s(\vec x, y) = \sum_{z < y} f(\vec x, z) \qquad\text{and}\qquad p(\vec x, y) = \prod_{z < y} f(\vec x, z),

with the conventions that the empty sum is 00 and the empty product is 11.

Proof of Proposition 5.9.

s(x⃗,0)=0s(\vec x, 0) = 0 and s(x⃗,y+1)=s(x⃗,y)+f(x⃗,y)s(\vec x, y + 1) = s(\vec x, y) + f(\vec x, y); similarly p(x⃗,0)=1p(\vec x, 0) = 1 and p(x⃗,y+1)=p(x⃗,y)⋅f(x⃗,y)p(\vec x, y + 1) = p(\vec x, y) \cdot f(\vec x, y).

Corollary 5.10.#

If P⊆Nk+1P \subseteq \nat^{k+1} is primitive recursive, so are the predicates

∃z<y P(x⃗,z)and∀z<y P(x⃗,z),\exists z < y\ P(\vec x, z) \qquad\text{and}\qquad \forall z < y\ P(\vec x, z),

and likewise with z≤yz \leq y.

Proof of Corollary 5.10.

The characteristic functions are sg(∑z<yχP(x⃗,z))\mathrm{sg}\big(\sum_{z < y} \chi_P(\vec x, z)\big) and ∏z<yχP(x⃗,z)\prod_{z < y} \chi_P(\vec x, z). For z≤yz \leq y, replace yy by y+1y + 1.

More generally, the bound may be any primitive recursive function of the parameters: ∃z<b(x⃗) P(x⃗,z)\exists z < b(\vec x)\ P(\vec x, z) is obtained by composing with bb.

5.5 Bounded minimization

Definition 5.11.#

For a predicate P⊆Nk+1P \subseteq \nat^{k+1}, the bounded minimization

μz<y P(x⃗,z)\mu z < y\ P(\vec x, z)

denotes the least z<yz < y such that P(x⃗,z)P(\vec x, z), if there is one, and yy otherwise.

Proposition 5.12.#

If PP is primitive recursive, then f(x⃗,y)=μz<y P(x⃗,z)f(\vec x, y) = \mu z < y\ P(\vec x, z) is primitive recursive.

For v<yv < y, the product ∏u≤vsg‾(χP(x⃗,u))\prod_{u \leq v} \overline{\mathrm{sg}}(\chi_P(\vec x, u)) equals 11 if no u≤vu \leq v satisfies P(x⃗,u)P(\vec x, u), and 00 otherwise. Hence

f(x⃗,y)=∑v<y ∏u≤vsg‾(χP(x⃗,u))f(\vec x, y) = \sum_{v < y}\ \prod_{u \leq v} \overline{\mathrm{sg}}(\chi_P(\vec x, u))

counts the v<yv < y that are smaller than every witness. If the least witness z0<yz_0 < y exists, these are exactly the v<z0v < z_0, so the sum is z0z_0; otherwise all v<yv < y are counted and the sum is yy. By Proposition 5.9, ff is primitive recursive.

5.6 Arithmetic functions and primes

With bounded minimization at hand, most functions of elementary number theory are seen to be primitive recursive.

  • Quotient and remainder. ⌊x/y⌋=μq<x+1 ((q+1)⋅y>x)\lfloor x / y \rfloor = \mu q < x + 1\ \big( (q + 1) \cdot y > x \big) for y≥1y \geq 1 (and 00 for y=0y = 0, by cases), and x mod y=x−˙y⋅⌊x/y⌋x \bmod y = x \dotminus y \cdot \lfloor x / y \rfloor.
  • Divisibility. y∣x  ⟺  ∃q≤x (q⋅y=x)y \mid x \iff \exists q \leq x\ (q \cdot y = x).
  • Primality. Prime(x)  ⟺  x≥2∧∀y<x (y∣x→y≤1)\mathrm{Prime}(x) \iff x \geq 2 \wedge \forall y < x\ (y \mid x \rightarrow y \leq 1).
  • Integer square root. ⌊x⌋=μr<x+1 ((r+1)2>x)\lfloor \sqrt x \rfloor = \mu r < x + 1\ \big((r+1)^2 > x\big).
  • Cantor pairing. ⟨x,y⟩=⌊(x+y)(x+y+1)/2⌋+y\langle x, y \rangle = \lfloor (x + y)(x + y + 1) / 2 \rfloor + y, and its inverses π0(z)=μx<z+1 ∃y≤z ⟨x,y⟩=z\pi_0(z) = \mu x < z + 1\ \exists y \leq z\ \langle x, y \rangle = z and similarly for π1\pi_1.
Proposition 5.13.#

The function n↦pnn \mapsto p_n, where p0=2,p1=3,p2=5,…p_0 = 2, p_1 = 3, p_2 = 5, \dots is the increasing enumeration of the primes, is primitive recursive.

Euclid’s argument shows that pn!+1p_n! + 1 has a prime factor larger than pnp_n, so pn+1≤pn!+1p_{n+1} \leq p_n! + 1. Hence

p0=2,pn+1=μz<pn!+2 (z>pn∧Prime(z)).p_0 = 2, \qquad p_{n+1} = \mu z < p_n! + 2\ \big(z > p_n \wedge \mathrm{Prime}(z)\big).

This is a primitive recursion with h(n,v)=μz<v!+2 (z>v∧Prime(z))h(n, v) = \mu z < v! + 2\ (z > v \wedge \mathrm{Prime}(z)), which is primitive recursive by Proposition 5.12.

Finally, every x≥1x \geq 1 is uniquely a product ∏ipiei\prod_i p_i^{e_i}. The exponent of pip_i in xx is

(x)i=μe<x ¬(pie+1∣x)for x≥1,(0)i=0,(x)_i = \mu e < x\ \neg\big(p_i^{e+1} \mid x\big) \quad \text{for } x \geq 1, \qquad (0)_i = 0,

which is primitive recursive. These exponents are the basis of the coding of finite sequences in the next lesson.

5.7 Exercises

Exercise 5.14 ★.

Show that gcd⁡(x,y)\gcd(x, y) and lcm(x,y)\mathrm{lcm}(x, y) are primitive recursive.

Solution

gcd⁡(x,y)=μd<x+y+1 (d∣x∧d∣y∧∀e≤x+y (e∣x∧e∣y→e≤d))\gcd(x, y) = \mu d < x + y + 1\ \big(d \mid x \wedge d \mid y \wedge \forall e \leq x + y\ (e \mid x \wedge e \mid y \rightarrow e \leq d)\big), which is correct for (x,y)≠(0,0)(x, y) \neq (0, 0); set gcd⁡(0,0)=0\gcd(0, 0) = 0 by cases. For x,y≥1x, y \geq 1, lcm(x,y)=⌊xy/gcd⁡(x,y)⌋\mathrm{lcm}(x, y) = \lfloor xy / \gcd(x, y) \rfloor, and lcm(x,y)=0\mathrm{lcm}(x, y) = 0 if x=0x = 0 or y=0y = 0.

Exercise 5.15 ★.

Show that the primitive recursive functions are closed under simultaneous recursion: if g1,g2,h1,h2g_1, g_2, h_1, h_2 are primitive recursive, so are the functions f1,f2f_1, f_2 defined by fi(x⃗,0)=gi(x⃗)f_i(\vec x, 0) = g_i(\vec x) and fi(x⃗,y+1)=hi(x⃗,y,f1(x⃗,y),f2(x⃗,y))f_i(\vec x, y + 1) = h_i(\vec x, y, f_1(\vec x, y), f_2(\vec x, y)). Deduce that the Fibonacci sequence is primitive recursive.

Solution

Let F(x⃗,y)=⟨f1(x⃗,y),f2(x⃗,y)⟩F(\vec x, y) = \langle f_1(\vec x, y), f_2(\vec x, y) \rangle. Then F(x⃗,0)=⟨g1(x⃗),g2(x⃗)⟩F(\vec x, 0) = \langle g_1(\vec x), g_2(\vec x) \rangle and F(x⃗,y+1)=⟨h1(x⃗,y,π0(F),π1(F)),h2(x⃗,y,π0(F),π1(F))⟩F(\vec x, y + 1) = \langle h_1(\vec x, y, \pi_0(F), \pi_1(F)), h_2(\vec x, y, \pi_0(F), \pi_1(F)) \rangle where FF stands for F(x⃗,y)F(\vec x, y). This is a primitive recursion, and fi=πi−1∘Ff_i = \pi_{i-1} \circ F. For Fibonacci, take f1(y)=fib(y)f_1(y) = \mathrm{fib}(y), f2(y)=fib(y+1)f_2(y) = \mathrm{fib}(y + 1), with f1(y+1)=f2(y)f_1(y + 1) = f_2(y) and f2(y+1)=f1(y)+f2(y)f_2(y + 1) = f_1(y) + f_2(y).

Exercise 5.16 ★★.

Show that if f:N→Nf : \nat \to \nat is primitive recursive and strictly increasing, then its range is a primitive recursive set. Is it true for every primitive recursive ff?

Solution

If ff is strictly increasing, then f(z)≥zf(z) \geq z, so y∈im⁡f  ⟺  ∃z≤y f(z)=yy \in \operatorname{im} f \iff \exists z \leq y\ f(z) = y, a bounded quantification. Without monotonicity this fails in general: there are primitive recursive functions whose range is not even computable. Fix a coding of Turing machines by integers in which every integer codes a machine, and a code aa of a machine which halts on input aa. Let f(⟨e,t⟩)=ef(\langle e, t \rangle) = e if the machine of code ee halts on input ee within tt steps, and f(⟨e,t⟩)=af(\langle e, t \rangle) = a otherwise. Step-bounded simulation is primitive recursive (see the lesson Equivalence of the models), so ff is primitive recursive, and its range is the halting set {e:the machine of code e halts on input e}\{e : \text{the machine of code } e \text{ halts on input } e\}, which is not computable (see the lesson The halting problem).

5.8 Notes and references

Definitions by recursion go back to Dedekind (1888) and Skolem (1923). Gödel used the primitive recursive functions — he called them recursive — to arithmetize syntax in his incompleteness theorem; the modern name is due to Kleene. Rózsa Péter’s monograph is the classical reference on the subject.

  • K. Gödel, Über formal unentscheidbare Sätze der Principia Mathematica und verwandter Systeme I, Monatshefte für Mathematik und Physik 38 (1931), 173–198.
  • R. Péter, Rekursive Funktionen, Akadémiai Kiadó, 1951.
  • P. Odifreddi, Classical Recursion Theory, North-Holland, 1989, chapter I.