Library hydras.Ackermann.cPair

Cantor's pairing function (Originally Russel O'Connors goedel contrib

From Coq Require Import Arith Lists.List Lia.
From hydras Require Import extEqualNat primRec.
From hydras Require Export Compat815 ssrnat_extracts.
Import PRNotations.
Import Nat.

Bijection from nat × nat to nat

Preliminary definitions

Sum of all natural numbers upto n

Fixpoint sumToN (n : nat): nat :=
  match n with
    0 ⇒ 0
  | S pS p + sumToN p
  end.

Lemma sumToN1 n : n sumToN n.

Lemma sumToN2 b a : a b sumToN a sumToN b.

#[export] Instance sumToNIsPR : isPR 1 sumToN.

Definition and properties of cPair

The cPair function defined below is slightly different from the "usual" Cantor pairing function shown in a big part of the litterature (and Coq's standard library). Since both versions are equivalent upto a swap of the arguments a and b, we still use Russel O'Connors notations

Definition cPair (a b : nat) := a + sumToN (a + b).


Usual definition (e.g. wikipedia)

 Definition xPair a b := b + sumToN ( b + a).

 Lemma xPairDef a b : xPair a b = cPair b a.

#[export] Instance cPairIsPR : isPR 2 cPair.

Section CPair_Injectivity.

  Remark cPairInjHelp :
     a b c d : nat, cPair a b = cPair c d a + b = c + d.

  Lemma cPairInj1 a b c d: cPair a b = cPair c d a = c.

  Lemma cPairInj2 a b c d : cPair a b = cPair c d b = d.

End CPair_Injectivity.

Section CPair_projections.


  Let searchXY (a : nat) :=
        boundedSearch (fun a y : natltBool a (sumToN y.+1)) a.

  Definition cPairPi1 (a : nat) := a - sumToN (searchXY a).
  Definition cPairPi2 (a : nat) := searchXY a - cPairPi1 a.

Lemma cPairProjectionsHelp (a b: nat):
  b < sumToN a.+1 sumToN a b searchXY b = a.

Lemma cPairProjections a: cPair (cPairPi1 a) (cPairPi2 a) = a.

#[local] Instance searchXYIsPR : isPR 1 searchXY.

#[export] Instance cPairPi1IsPR : isPR 1 cPairPi1.

Lemma cPairProjections1 (a b : nat): cPairPi1 (cPair a b) = a.

Lemma cPairProjections2 (a b : nat): cPairPi2 (cPair a b) = b.

#[export] Instance cPairPi2IsPR : isPR 1 cPairPi2.

End CPair_projections.

Section CPair_Order.

  Lemma cPairLe1 (a b : nat) : a cPair a b.

  Lemma cPairLe1A (a : nat) : cPairPi1 a a.

  Lemma cPairLe2 (a b : nat) : b cPair a b.

  Lemma cPairLe2A (a: nat): cPairPi2 a a.

  Lemma cPairLe3 (a b c d : nat): a b c d cPair a c cPair b d.

  Lemma cPairLt1 (a b : nat): a < cPair a (S b).

  Lemma cPairLt2 (a b : nat): b < cPair (S a) b.

End CPair_Order.

Require Import Extraction.
Section code_nat_list.

Fixpoint codeList (l : list nat) : nat :=
  match l with
  | nil ⇒ 0
  | n :: l'S (cPair n (codeList l'))
  end.

Lemma codeListInj (l m : list nat): codeList l = codeList m l = m.

Definition codeNth (n m:nat) : nat :=
  let X := nat_rec (fun _ : natnat)
             m
             (fun _ Hrecn : natcPairPi2 (pred Hrecn)) n
  in cPairPi1 (pred X).

drops n first elements from l
Let drop (n : nat) : (l : list nat), list nat.

Lemma codeNthCorrect :
   (n : nat) (l : list nat), codeNth n (codeList l) = nth n l 0.

#[export] Instance codeNthIsPR : isPR 2 codeNth.

End code_nat_list.

Extraction codeNth.
Print codeNth.

Section Strong_Recursion.
Definition evalStrongRecHelp (n : nat) (f : naryFunc n.+2) :
  naryFunc n.+1 :=
  evalPrimRecFunc n (evalComposeFunc n 0 (Vector.nil _) (codeList nil))
    (evalComposeFunc n.+2 2
       (Vector.cons _ f _
          (Vector.cons _ (evalProjFunc n.+2 n
                            (Nat.lt_lt_succ_r _ _
                               (Nat.lt_succ_diag_r _))) _
             (Vector.nil _)))
       (fun a b : natS (cPair a b))).

Definition evalStrongRec (n : nat) (f : naryFunc n.+2):
  naryFunc n.+1 :=
  evalComposeFunc n.+1 1
    (Vector.cons _
       (fun z : natevalStrongRecHelp n f z.+1) _ (Vector.nil _))
    (fun z : natcPairPi1 z.-1).

#[export] Instance
 evalStrongRecIsPR (n : nat) (f : naryFunc n.+2):
  isPR _ f isPR _ (evalStrongRec n f).

Lemma computeEvalStrongRecHelp :
   (n : nat) (f : naryFunc n.+2) (c : nat),
    evalStrongRecHelp n f c.+1 =
      compose2 n (evalStrongRecHelp n f c)
        (fun a0 : nat
           evalComposeFunc n 2
             (Vector.cons (naryFunc n) (f c a0) 1
                (Vector.cons (naryFunc n) (evalConstFunc n a0) 0
                   (Vector.nil (naryFunc n))))
             (fun a1 b0 : natS (cPair a1 b0))).

Fixpoint listValues (f : naryFunc 2) (n : nat) : list nat :=
  match n with
    0 ⇒ nil
  | S mevalStrongRec _ f m :: listValues f m
  end.

Lemma evalStrongRecHelp1 :
  (f : naryFunc 2) (n m : nat),
   m < n
   codeNth (n - m.+1) (evalStrongRecHelp _ f n) = evalStrongRec _ f m.

Lemma evalStrongRecHelpParam :
   (a n c : nat) (f : naryFunc a.+3),
    extEqual a (evalStrongRecHelp (S a) f n c)
      (evalStrongRecHelp a (fun x y : natf x y c) n).

Lemma evalStrongRecHelp2 :
   (a : nat) (f : naryFunc a.+2) (n m : nat),
    m < n
    extEqual _
      (evalComposeFunc _ 1
         (Vector.cons _ (evalStrongRecHelp _ f n) 0 (Vector.nil _))
         (fun b : natcodeNth (n - m.+1) b)) (evalStrongRec _ f m).

#[export] Instance callIsPR (g : nat nat) (H : isPR 1 g) :
   isPR 2 (fun a recs : natcodeNth (a - S (g a)) recs).

End Strong_Recursion.

#[export] Instance div2IsPR : isPR 1 div2.

Lemma cPairLemma1 :
   a b : nat, (a + b) × S (a + b) + 2 × a = 2 × cPair a b.

abbreviations a la Lisp (to improve)

Module LispAbbreviations.
  #[global] Notation car := cPairPi1.
  #[global] Notation cdr := cPairPi2.
  #[global] Notation caar n := (cPairPi1 (cPairPi1 n)).
  #[global] Notation cadr n := (cPairPi1 (cPairPi2 n)).
  #[global] Notation caddr n := (cPairPi1 (cPairPi2 (cPairPi2 n))).

  #[global] Notation cddr n := (cPairPi2 (cPairPi2 n)).
  #[global] Notation cdddr n := (cPairPi2 (cPairPi2 (cPairPi2 n))).
  #[global] Notation cddddr n :=
    (cPairPi2 (cPairPi2 (cPairPi2 (cPairPi2 n)))).

End LispAbbreviations.

Triples

(moved from codeSubFormula.v)

Definition cTriple (a b c : nat) : nat := cPair a (cPair b c).

Definition cTriplePi1 (n : nat) : nat := cPairPi1 n.

Definition cTriplePi2 (n : nat) : nat := cPairPi1 (cPairPi2 n).

Definition cTriplePi3 (n : nat) : nat := cPairPi2 (cPairPi2 n).

#[export] Instance cTripleIsPR : isPR 3 cTriple.

#[export] Instance cTriplePi1IsPR : isPR 1 cTriplePi1.

#[export] Instance cTriplePi2IsPR : isPR 1 cTriplePi2.

#[export] Instance cTriplePi3IsPR : isPR 1 cTriplePi3.

Lemma cTripleProj1 (a b c : nat) : cTriplePi1 (cTriple a b c) = a.

Lemma cTripleProj2 (a b c : nat) : cTriplePi2 (cTriple a b c) = b.

Lemma cTripleProj3 (a b c : nat) : cTriplePi3 (cTriple a b c) = c.

Lemma cTripleProj (a: nat) :
 cTriple (cTriplePi1 a) (cTriplePi2 a) (cTriplePi3 a) = a.