Gödel Numbering for Partial Recursive Functions. #
THIS FILE IS SYNCHRONIZED WITH MATHLIB4. Any changes to this file require a corresponding PR to mathlib4.
This file defines nat.partrec.code
, an inductive datatype describing code for partial
recursive functions on ℕ. It defines an encoding for these codes, and proves that the constructors
are primitive recursive with respect to the encoding.
It also defines the evalution of these codes as partial functions using pfun
, and proves that a
function is partially recursive (as defined by nat.partrec
) if and only if it is the evaluation
of some code.
Main Definitions #
nat.partrec.code
: Inductive datatype for partial recursive codes.nat.partrec.code.encode_code
: A (computable) encoding of codes as natural numbers.nat.partrec.code.of_nat_code
: The inverse of this encoding.nat.partrec.code.eval
: The interpretation of anat.partrec.code
as a partial function.
Main Results #
nat.partrec.code.rec_prim
: Recursion onnat.partrec.code
is primitive recursive.nat.partrec.code.rec_computable
: Recursion onnat.partrec.code
is computable.nat.partrec.code.smn
: The $S_n^m$ theorem.nat.partrec.code.exists_code
: Partial recursiveness is equivalent to being the eval of a code.nat.partrec.code.evaln_prim
:evaln
is primitive recursive.nat.partrec.code.fixed_point
: Roger's fixed point theorem.
References #
- zero : nat.partrec.code
- succ : nat.partrec.code
- left : nat.partrec.code
- right : nat.partrec.code
- pair : nat.partrec.code → nat.partrec.code → nat.partrec.code
- comp : nat.partrec.code → nat.partrec.code → nat.partrec.code
- prec : nat.partrec.code → nat.partrec.code → nat.partrec.code
- rfind' : nat.partrec.code → nat.partrec.code
Code for partial recursive functions from ℕ to ℕ.
See nat.partrec.code.eval
for the interpretation of these constructors.
Instances for nat.partrec.code
- nat.partrec.code.has_sizeof_inst
- nat.partrec.code.inhabited
- nat.partrec.code.denumerable
- nat.partrec.code.has_mem
Equations
Returns a code for the constant function outputting a particular natural.
Equations
A code for the identity function.
Given a code c
taking a pair as input, returns a code using n
as the first argument to c
.
Equations
- c.curry n = c.comp ((nat.partrec.code.const n).pair nat.partrec.code.id)
An encoding of a nat.partrec.code
as a ℕ.
Equations
- cf.rfind'.encode_code = bit1 (bit1 cf.encode_code) + 4
- (cf.prec cg).encode_code = bit1 (bit0 (nat.mkpair cf.encode_code cg.encode_code)) + 4
- (cf.comp cg).encode_code = bit0 (bit1 (nat.mkpair cf.encode_code cg.encode_code)) + 4
- (cf.pair cg).encode_code = bit0 (bit0 (nat.mkpair cf.encode_code cg.encode_code)) + 4
- nat.partrec.code.right.encode_code = 3
- nat.partrec.code.left.encode_code = 2
- nat.partrec.code.succ.encode_code = 1
- nat.partrec.code.zero.encode_code = 0
A decoder for nat.partrec.code.encode_code
, taking any ℕ to the nat.partrec.code
it represents.
Equations
- nat.partrec.code.of_nat_code (n + 4) = let m : ℕ := n.div2.div2 in have hm : m < n + 4, from _, nat.partrec.code.of_nat_code._match_1 (nat.partrec.code.of_nat_code (nat.unpair n.div2.div2).fst) (nat.partrec.code.of_nat_code (nat.unpair n.div2.div2).snd) (nat.partrec.code.of_nat_code (nat.unpair n.div2.div2).fst) (nat.partrec.code.of_nat_code (nat.unpair n.div2.div2).snd) (nat.partrec.code.of_nat_code (nat.unpair n.div2.div2).fst) (nat.partrec.code.of_nat_code (nat.unpair n.div2.div2).snd) (nat.partrec.code.of_nat_code n.div2.div2) n.bodd n.div2.bodd
- nat.partrec.code.of_nat_code 3 = nat.partrec.code.right
- nat.partrec.code.of_nat_code 2 = nat.partrec.code.left
- nat.partrec.code.of_nat_code 1 = nat.partrec.code.succ
- nat.partrec.code.of_nat_code 0 = nat.partrec.code.zero
- nat.partrec.code.of_nat_code._match_1 _f_1 _f_2 _f_3 _f_4 _f_5 _f_6 _f_7 bool.tt bool.tt = _f_7.rfind'
- nat.partrec.code.of_nat_code._match_1 _f_1 _f_2 _f_3 _f_4 _f_5 _f_6 _f_7 bool.tt bool.ff = _f_5.prec _f_6
- nat.partrec.code.of_nat_code._match_1 _f_1 _f_2 _f_3 _f_4 _f_5 _f_6 _f_7 bool.ff bool.tt = _f_3.comp _f_4
- nat.partrec.code.of_nat_code._match_1 _f_1 _f_2 _f_3 _f_4 _f_5 _f_6 _f_7 bool.ff bool.ff = _f_1.pair _f_2
Equations
- nat.partrec.code.denumerable = denumerable.mk' {to_fun := nat.partrec.code.encode_code, inv_fun := nat.partrec.code.of_nat_code, left_inv := nat.partrec.code.denumerable._proof_1, right_inv := encode_of_nat_code}
Recursion on nat.partrec.code
is primitive recursive.
Recursion on nat.partrec.code
is computable.
The interpretation of a nat.partrec.code
as a partial function.
nat.partrec.code.zero
: The constant zero function.nat.partrec.code.succ
: The successor function.nat.partrec.code.left
: Left unpairing of a pair of ℕ (encoded bynat.mkpair
)nat.partrec.code.right
: Right unpairing of a pair of ℕ (encoded bynat.mkpair
)nat.partrec.code.pair
: Pairs the outputs of argument codes usingnat.mkpair
.nat.partrec.code.comp
: Composition of two argument codes.nat.partrec.code.prec
: Primitive recursion. Given an argument of the formnat.mkpair a n
:- If
n = 0
, returnseval cf a
. - If
n = succ k
, returnseval cg (mkpair a (mkpair k (eval (prec cf cg) (mkpair a k))))
- If
nat.partrec.code.rfind'
: Minimization. Forf
an argument of the formnat.mkpair a m
,rfind' f m
returns the leasta
such thatf a m = 0
, if one exists andf b m
terminates forb < a
Equations
- cf.rfind'.eval = nat.unpaired (λ (a m : ℕ), part.map (λ (_x : ℕ), _x + m) (nat.rfind (λ (n : ℕ), (λ (m : ℕ), decidable.to_bool (m = 0)) <$> cf.eval (nat.mkpair a (n + m)))))
- (cf.prec cg).eval = nat.unpaired (λ (a n : ℕ), nat.elim (cf.eval a) (λ (y : ℕ) (IH : part ℕ), IH >>= λ (i : ℕ), cg.eval (nat.mkpair a (nat.mkpair y i))) n)
- (cf.comp cg).eval = λ (n : ℕ), cg.eval n >>= cf.eval
- (cf.pair cg).eval = λ (n : ℕ), nat.mkpair <$> cf.eval n <*> cg.eval n
- nat.partrec.code.right.eval = ↑(λ (n : ℕ), (nat.unpair n).snd)
- nat.partrec.code.left.eval = ↑(λ (n : ℕ), (nat.unpair n).fst)
- nat.partrec.code.succ.eval = ↑nat.succ
- nat.partrec.code.zero.eval = has_pure.pure 0
Helper lemma for the evaluation of prec
in the base case.
Helper lemma for the evaluation of prec
in the recursive case.
Equations
- nat.partrec.code.has_mem = {mem := λ (f : ℕ →. ℕ) (c : nat.partrec.code), c.eval = f}
The $S_n^m$ theorem: There is a computable function, namely nat.partrec.code.curry
, that takes a
program and a ℕ n
, and returns a new program using n
as the first argument.
A function is partial recursive if and only if there is a code implementing it.
A modified evaluation for the code which returns an option ℕ
instead of a part ℕ
. To avoid
undecidability, evaln
takes a parameter k
and fails if it encounters a number ≥ k in the course
of its execution. Other than this, the semantics are the same as in nat.partrec.code.eval
.
Equations
- nat.partrec.code.evaln (k + 1) cf.rfind' = λ (n : ℕ), guard (n ≤ k) >> nat.unpaired (λ (a m : ℕ), nat.partrec.code.evaln (k + 1) cf (nat.mkpair a m) >>= λ (x : ℕ), ite (x = 0) (has_pure.pure m) (nat.partrec.code.evaln k cf.rfind' (nat.mkpair a (m + 1)))) n
- nat.partrec.code.evaln (k + 1) (cf.prec cg) = λ (n : ℕ), guard (n ≤ k) >> nat.unpaired (λ (a n : ℕ), nat.cases (nat.partrec.code.evaln (k + 1) cf a) (λ (y : ℕ), nat.partrec.code.evaln k (cf.prec cg) (nat.mkpair a y) >>= λ (i : ℕ), nat.partrec.code.evaln (k + 1) cg (nat.mkpair a (nat.mkpair y i))) n) n
- nat.partrec.code.evaln (k + 1) (cf.comp cg) = λ (n : ℕ), guard (n ≤ k) >> (nat.partrec.code.evaln (k + 1) cg n >>= λ (x : ℕ), nat.partrec.code.evaln (k + 1) cf x)
- nat.partrec.code.evaln (k + 1) (cf.pair cg) = λ (n : ℕ), guard (n ≤ k) >> nat.mkpair <$> nat.partrec.code.evaln (k + 1) cf n <*> nat.partrec.code.evaln (k + 1) cg n
- nat.partrec.code.evaln (k + 1) nat.partrec.code.right = λ (n : ℕ), guard (n ≤ k) >> has_pure.pure (nat.unpair n).snd
- nat.partrec.code.evaln (k + 1) nat.partrec.code.left = λ (n : ℕ), guard (n ≤ k) >> has_pure.pure (nat.unpair n).fst
- nat.partrec.code.evaln (k + 1) nat.partrec.code.succ = λ (n : ℕ), guard (n ≤ k) >> has_pure.pure n.succ
- nat.partrec.code.evaln (k + 1) nat.partrec.code.zero = λ (n : ℕ), guard (n ≤ k) >> has_pure.pure 0
- nat.partrec.code.evaln 0 _x = λ (m : ℕ), option.none
The nat.partrec.code.evaln
function is primitive recursive.
Roger's fixed-point theorem: Any total, computable f
has a fixed point: That is, under the
interpretation given by nat.partrec.code.eval
, there is a code c
such that c
and f c
have
the same evaluation.