Exercise session 2 — Part 2
🏠 Go back to the course homepage.
Set Default Goal Selector "!".From Stdlib Require Import Nat List. Import ListNotations.
EXERCISE
As you can guess, x^n is a notation for x to the power of n. You can use Locate "^". to see what the notation unfold to (here pow) and then Print pow. to see the definition.
n, x: natx ^ n = iter (mul x) n 1n, x: natx ^ n = iter (mul x) n 1x: natx ^ 0 = iter (mul x) 0 1n, x: nat
ih: x ^ n = iter (mul x) n 1x ^ S n = iter (mul x) (S n) 1x: natx ^ 0 = iter (mul x) 0 1reflexivity.x: nat1 = 1n, x: nat
ih: x ^ n = iter (mul x) n 1x ^ S n = iter (mul x) (S n) 1n, x: nat
ih: x ^ n = iter (mul x) n 1x * x ^ n = x * iter (mul x) n 1reflexivity.n, x: nat
ih: x ^ n = iter (mul x) n 1x * iter (mul x) n 1 = x * iter (mul x) n 1
EXERCISE
Hint: The rewrite tactic can be used to rewrite an equality in the opposite direction using rewrite <- e. When e : u = v, it will replace v in the goal by u.
A: Type
f: A -> A
n: nat
x: Aiter f (S n) x = iter f n (f x)A: Type
f: A -> A
n: nat
x: Aiter f (S n) x = iter f n (f x)A: Type
f: A -> A
x: Aiter f 1 x = iter f 0 (f x)A: Type
f: A -> A
n: nat
x: A
ih: iter f (S n) x = iter f n (f x)iter f (S (S n)) x = iter f (S n) (f x)reflexivity.A: Type
f: A -> A
x: Aiter f 1 x = iter f 0 (f x)A: Type
f: A -> A
n: nat
x: A
ih: iter f (S n) x = iter f n (f x)iter f (S (S n)) x = iter f (S n) (f x)A: Type
f: A -> A
n: nat
x: A
ih: iter f (S n) x = iter f n (f x)f (f (iter f n x)) = f (iter f n (f x))reflexivity.A: Type
f: A -> A
n: nat
x: A
ih: iter f (S n) x = iter f n (f x)f (f (iter f n x)) = f (iter f (S n) x)
EXERCISE
Spell out the induction principle of le' without checking it. Notice that it's not the same definition as in the live coding.
EXERCISE
Prove the following and lemmas that you need by induction. Do not use the standard library or lia!
forall n : nat, 0 <= nforall n : nat, 0 <= nn: nat0 <= n0 <= 0n: nat
ih: 0 <= n0 <= S nconstructor.0 <= 0n: nat
ih: 0 <= n0 <= S nassumption.n: nat
ih: 0 <= n0 <= nforall n m : nat, n <= m -> S n <= S mforall n m : nat, n <= m -> S n <= S mn, m: nat
h: n <= mS n <= S mn: natS n <= S nn, m: nat
h: n <= m
IHh: S n <= S mS n <= S (S m)constructor.n: natS n <= S nn, m: nat
h: n <= m
IHh: S n <= S mS n <= S (S m)assumption.n, m: nat
h: n <= m
IHh: S n <= S mS n <= S mforall n : nat, le' n nforall n : nat, le' n nn: natle' n nle' 0 0n: nat
ih: le' n nle' (S n) (S n)constructor.le' 0 0n: nat
ih: le' n nle' (S n) (S n)assumption.n: nat
ih: le' n nle' n nforall n m : nat, le' n m -> le' n (S m)forall n m : nat, le' n m -> le' n (S m)n, m: nat
h: le' n mle' n (S m)n: natle' 0 (S n)n, m: nat
h: le' n m
IHh: le' n (S m)le' (S n) (S (S m))constructor.n: natle' 0 (S n)n, m: nat
h: le' n m
IHh: le' n (S m)le' (S n) (S (S m))assumption.n, m: nat
h: le' n m
IHh: le' n (S m)le' n (S m)n, m: natle' n m <-> n <= mn, m: natle' n m <-> n <= mn, m: natle' n m -> n <= mn, m: natn <= m -> le' n mn, m: natle' n m -> n <= mn, m: nat
h: le' n mn <= mn: nat0 <= nn, m: nat
h: le' n m
IHh: n <= mS n <= S mapply le_0_n.n: nat0 <= nn, m: nat
h: le' n m
IHh: n <= mS n <= S massumption.n, m: nat
h: le' n m
IHh: n <= mn <= mn, m: natn <= m -> le' n mn, m: nat
h: n <= mle' n mn: natle' n nn, m: nat
h: n <= m
IHh: le' n mle' n (S m)apply le'_refl.n: natle' n nn, m: nat
h: n <= m
IHh: le' n mle' n (S m)assumption.n, m: nat
h: n <= m
IHh: le' n mle' n m
EXERCISE
EXERCISE
n, m: natleb n m = true <-> n <= mn, m: natleb n m = true <-> n <= mn, m: natleb n m = true -> n <= mn, m: natn <= m -> leb n m = truen, m: natleb n m = true -> n <= mn, m: nat
h: leb n m = truen <= mm: nat
h: leb 0 m = true0 <= mn, m: nat
h: leb (S n) m = true
ih:= forall m: nat, leb n m = true -> n <= mS n <= mapply le_0_n.m: nat
h: leb 0 m = true0 <= mn, m: nat
h: leb (S n) m = true
ih:= forall m: nat, leb n m = true -> n <= mS n <= mn, m: nat
h: match m with | 0 => false | S m' => leb n m' end = true
ih:= forall m: nat, leb n m = true -> n <= mS n <= mn: nat
h: false = true
ih:= forall m: nat, leb n m = true -> n <= mS n <= 0n, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= mS n <= S mn, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= mS n <= S mn, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= mn <= massumption.n, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= mleb n m = truen, m: natn <= m -> leb n m = truen, m: nat
h: n <= mleb n m = truen, m: nat
h: le' n mleb n m = truen: natleb 0 n = truen, m: nat
h: le' n m
IHh: leb n m = trueleb (S n) (S m) = truereflexivity.n: natleb 0 n = truen, m: nat
h: le' n m
IHh: leb n m = trueleb (S n) (S m) = trueassumption.n, m: nat
h: le' n m
IHh: leb n m = trueleb n m = true
EXERCISE
Define an even predicate similar to how you would define a Boolean predicate but using propositions instead.
EXERCISE
Spell out the induction principle of even4 without checking it.
We now allow you to use lia.
Require Import Lia.
EXERCISE
forall P : nat -> Prop, (forall n : nat, (forall m : nat, m < n -> P m) -> P n) -> forall n : nat, P nforall P : nat -> Prop, (forall n : nat, (forall m : nat, m < n -> P m) -> P n) -> forall n : nat, P nP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: natP nP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: natforall m : nat, m <= n -> P mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
hn:= forall m: nat, m <= n -> P mP nP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: natforall m : nat, m <= n -> P mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P nforall m : nat, m <= 0 -> P mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
ih:= forall m: nat, m <= n -> P mforall m : nat, m <= S n -> P mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P nforall m : nat, m <= 0 -> P mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
m: nat
hm: m <= 0P mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
m: nat
hm: m <= 0
H: m = 0P 0P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
m: nat
hm: m <= 0
H: m = 0forall m0 : nat, m0 < 0 -> P m0lia.P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
m: nat
hm: m <= 0
H: m = 0
k: nat
hk: k < 0P kP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
ih:= forall m: nat, m <= n -> P mforall m : nat, m <= S n -> P mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
ih:= forall m: nat, m <= n -> P m
m: nat
hm: m <= S nP mP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
ih:= forall m: nat, m <= n -> P m
m: nat
hm: m <= S nforall m0 : nat, m0 < m -> P m0P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
ih:= forall m: nat, m <= n -> P m
m: nat
hm: m <= S n
k: nat
hk: k < mP klia.P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
ih:= forall m: nat, m <= n -> P m
m: nat
hm: m <= S n
k: nat
hk: k < mk <= nP: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
hn:= forall m: nat, m <= n -> P mP nlia.P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat
hn:= forall m: nat, m <= n -> P mn <= n
EXERCISE
Hint: If you want to assert an equality (e : a = b) and then use rewrite e, then you can also make use of the replace tactic. replace a with b will replace a with b in the goal and ask you to prove the equality between the two.
n: nateven1 n -> even2 n = truen: nateven1 n -> even2 n = true
Short for intros n h. destruct h as [m e]. subst e.:
m: nateven2 (2 * m) = true
In fact the -> means rewriting e from left to right.
even2 (2 * 0) = truem: nat
ih: even2 (2 * m) = trueeven2 (2 * S m) = trueeven2 (2 * 0) = truereflexivity.true = truem: nat
ih: even2 (2 * m) = trueeven2 (2 * S m) = truem: nat
ih: even2 (2 * m) = trueeven2 (S (S (2 * m))) = true
replace a with b allows us to rewrite with an equality we have yet to prove between a and b. by lia tells Rocq that lia will prove said equality.
assumption.m: nat
ih: even2 (2 * m) = trueeven2 (m + (m + 0)) = true
EXERCISE
n: nateven2 n = true <-> even3 nn: nateven2 n = true <-> even3 nn: nat
ih:= forall m: nat, m < n -> even2 m = true <-> even3 meven2 n = true <-> even3 nih:= forall m: nat, m < 0 -> even2 m = true <-> even3 meven2 0 = true <-> even3 0ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 meven2 1 = true <-> even3 1n: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 meven2 (S (S n)) = true <-> even3 (S (S n))ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 meven2 0 = true <-> even3 0ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 mtrue = true <-> Trueih:= forall m: nat, m < 0 -> even2 m = true <-> even3 mtrue = true -> Trueih:= forall m: nat, m < 0 -> even2 m = true <-> even3 mTrue -> true = trueih:= forall m: nat, m < 0 -> even2 m = true <-> even3 mtrue = true -> Trueconstructor.ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m
H: true = trueTruereflexivity.ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 mTrue -> true = trueih:= forall m: nat, m < 1 -> even2 m = true <-> even3 meven2 1 = true <-> even3 1ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 mfalse = true <-> Falseih:= forall m: nat, m < 1 -> even2 m = true <-> even3 mfalse = true -> Falseih:= forall m: nat, m < 1 -> even2 m = true <-> even3 mFalse -> false = truediscriminate.ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 mfalse = true -> Falsecontradiction.ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 mFalse -> false = truen: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 meven2 (S (S n)) = true <-> even3 (S (S n))n: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 meven2 n = true <-> even3 nlia.n: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 mn < S (S n)
EXERCISE
Hint: The tactic contradiction is useful if you have an obviously false hypothesis.
n: nateven3 n -> even4 nn: nateven3 n -> even4 nn: nat
h: even3 neven4 nn: nat
ih:= forall m: nat, m < n -> even3 m -> even4 m
h: even3 neven4 nih:= forall m: nat, m < 0 -> even3 m -> even4 m
h: even3 0even4 0ih:= forall m: nat, m < 1 -> even3 m -> even4 m
h: even3 1even4 1n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))even4 (S (S n))constructor.ih:= forall m: nat, m < 0 -> even3 m -> even4 m
h: even3 0even4 0ih:= forall m: nat, m < 1 -> even3 m -> even4 m
h: even3 1even4 1contradiction.ih:= forall m: nat, m < 1 -> even3 m -> even4 m
h: Falseeven4 1n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))even4 (S (S n))n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))even4 nn: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))n < S (S n)n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))even3 nlia.n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))n < S (S n)assumption.n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))even3 n
EXERCISE
n: nateven4 n -> even1 nn: nateven4 n -> even1 nn: nat
h: even4 neven1 nn: nat
h: even4 nexists m : nat, n = 2 * mexists m : nat, 0 = 2 * mn: nat
h: even4 n
ih:= exists m: nat, n = 2 * mexists m : nat, S (S n) = 2 * mexists m : nat, 0 = 2 * mreflexivity.0 = 2 * 0n: nat
h: even4 n
ih:= exists m: nat, n = 2 * mexists m : nat, S (S n) = 2 * mm: nat
h: even4 (2 * m)exists m0 : nat, S (S (2 * m)) = 2 * m0lia.m: nat
h: even4 (2 * m)S (S (2 * m)) = 2 * S m
Membership in a list
EXERCISE
Propose an inductive definition of membership (add the missing constructor(s)).
EXERCISE
A: Type
x: A
l: list AIn x l <-> In_i x lA: Type
x: A
l: list AIn x l <-> In_i x lA: Type
x: A
l: list AIn x l -> In_i x lA: Type
x: A
l: list AIn_i x l -> In x lA: Type
x: A
l: list AIn x l -> In_i x lA: Type
x: A
l: list A
h: In x lIn_i x lA: Type
x: A
h: In x []In_i x []A: Type
x, a: A
l: list A
h:= In x (a :: l)
ih: In x l -> In_i x lIn_i x (a :: l)A: Type
x: A
h: In x []In_i x []contradiction.A: Type
x: A
h: FalseIn_i x []A: Type
x, a: A
l: list A
h:= In x (a :: l)
ih: In x l -> In_i x lIn_i x (a :: l)A: Type
x, a: A
l: list A
h: a = x \/ In x l
ih: In x l -> In_i x lIn_i x (a :: l)A: Type
x: A
l: list A
ih: In x l -> In_i x lIn_i x (x :: l)A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x lIn_i x (a :: l)constructor.A: Type
x: A
l: list A
ih: In x l -> In_i x lIn_i x (x :: l)A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x lIn_i x (a :: l)A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x lIn_i x lassumption.A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x lIn x lA: Type
x: A
l: list AIn_i x l -> In x lA: Type
x: A
l: list A
h: In_i x lIn x lA: Type
x: A
l: list AIn x (x :: l)A: Type
x, y: A
l: list A
h: In_i x l
IHh: In x lIn x (y :: l)A: Type
x: A
l: list AIn x (x :: l)A: Type
x: A
l: list Ax = x \/ In x lreflexivity.A: Type
x: A
l: list Ax = xA: Type
x, y: A
l: list A
h: In_i x l
IHh: In x lIn x (y :: l)A: Type
x, y: A
l: list A
h: In_i x l
IHh: In x ly = x \/ In x lassumption.A: Type
x, y: A
l: list A
h: In_i x l
IHh: In x lIn x l
ADVANCED EXERCISES
Make sure you manage to do the previous exercices before. Do not hesitate to ask for help.
EXERCISE
Define the factorial function in two ways:
once using Fixpoint
and once using iter
Prove that both yield the same value for all arguments.
forall n : nat, fact_fix n = fact_iter nforall n : nat, fact_fix n = fact_iter nn: natfact_fix n = fact_iter nn: natfact_fix n = snd (iter fact_iter_f n (0, 1))n: nat(n, fact_fix n) = iter fact_iter_f n (0, 1)n: nat
h: (n, fact_fix n) = iter fact_iter_f n (0, 1)fact_fix n = snd (iter fact_iter_f n (0, 1))n: nat(n, fact_fix n) = iter fact_iter_f n (0, 1)(0, fact_fix 0) = iter fact_iter_f 0 (0, 1)n: nat
ih: (n, fact_fix n) = iter fact_iter_f n (0, 1)(S n, fact_fix (S n)) = iter fact_iter_f (S n) (0, 1)(0, fact_fix 0) = iter fact_iter_f 0 (0, 1)reflexivity.(0, 1) = (0, 1)n: nat
ih: (n, fact_fix n) = iter fact_iter_f n (0, 1)(S n, fact_fix (S n)) = iter fact_iter_f (S n) (0, 1)n: nat
ih: (n, fact_fix n) = iter fact_iter_f n (0, 1)(S n, fact_fix n + n * fact_fix n) = fact_iter_f (iter fact_iter_f n (0, 1))n: nat
ih: (n, fact_fix n) = iter fact_iter_f n (0, 1)(S n, fact_fix n + n * fact_fix n) = fact_iter_f (n, fact_fix n)reflexivity.n: nat
ih: (n, fact_fix n) = iter fact_iter_f n (0, 1)(S n, fact_fix n + n * fact_fix n) = (S n, fact_fix n + n * fact_fix n)n: nat
h: (n, fact_fix n) = iter fact_iter_f n (0, 1)fact_fix n = snd (iter fact_iter_f n (0, 1))assumption.n: nat
h: snd (n, fact_fix n) = snd (iter fact_iter_f n (0, 1))fact_fix n = snd (iter fact_iter_f n (0, 1))
EXERCISE
Define the Fibonnaci function, using only iter (no recursive definition). As a reminder fib 0 = 0, fib 1 = 1 and fib (n+2) = fib (n+1) + fib n.
EXERCISE
fib 0 = 0reflexivity.fib 0 = 0
EXERCISE
fib 1 = 1reflexivity.fib 1 = 1
EXERCISE
Note. It's proven by reflexivity directly!
forall n : nat, fib (S (S n)) = fib n + fib (S n)reflexivity.forall n : nat, fib (S (S n)) = fib n + fib (S n)
EXERCISE
Hint: You can use apply f with u to provide u as argument to f when Rocq can't guess it on its own.
forall (A : Type) (R : A -> A -> Prop) (x y z : A), rtclos' R x y -> rtclos' R y z -> rtclos' R x zforall (A : Type) (R : A -> A -> Prop) (x y z : A), rtclos' R x y -> rtclos' R y z -> rtclos' R x zA: Type
R: A -> A -> Prop
x, y, z: A
hxy: rtclos' R x y
hyz: rtclos' R y zrtclos' R x zA: Type
R: A -> A -> Prop
z, x: A
hyz: rtclos' R x zrtclos' R x zA: Type
R: A -> A -> Prop
z, x, y, w: A
h1: R x y
h2: rtclos' R y w
hyz: rtclos' R w z
ih: rtclos' R w z -> rtclos' R y zrtclos' R x zassumption.A: Type
R: A -> A -> Prop
z, x: A
hyz: rtclos' R x zrtclos' R x z
The with keyword is to give the argument it can't guess.
A: Type
R: A -> A -> Prop
z, x, y, w: A
h1: R x y
h2: rtclos' R y w
hyz: rtclos' R w z
ih: rtclos' R w z -> rtclos' R y zrtclos' R x zA: Type
R: A -> A -> Prop
z, x, y, w: A
h1: R x y
h2: rtclos' R y w
hyz: rtclos' R w z
ih: rtclos' R w z -> rtclos' R y zR x yA: Type
R: A -> A -> Prop
z, x, y, w: A
h1: R x y
h2: rtclos' R y w
hyz: rtclos' R w z
ih: rtclos' R w z -> rtclos' R y zrtclos' R y zassumption.A: Type
R: A -> A -> Prop
z, x, y, w: A
h1: R x y
h2: rtclos' R y w
hyz: rtclos' R w z
ih: rtclos' R w z -> rtclos' R y zR x yA: Type
R: A -> A -> Prop
z, x, y, w: A
h1: R x y
h2: rtclos' R y w
hyz: rtclos' R w z
ih: rtclos' R w z -> rtclos' R y zrtclos' R y zassumption.A: Type
R: A -> A -> Prop
z, x, y, w: A
h1: R x y
h2: rtclos' R y w
hyz: rtclos' R w z
ih: rtclos' R w z -> rtclos' R y zrtclos' R w z
EXERCISE
forall (A : Type) (R : A -> A -> Prop) (x y : A), rtclos R x y <-> rtclos' R x yforall (A : Type) (R : A -> A -> Prop) (x y : A), rtclos R x y <-> rtclos' R x yA: Type
R: A -> A -> Prop
x, y: Artclos R x y <-> rtclos' R x yA: Type
R: A -> A -> Prop
x, y: Artclos R x y -> rtclos' R x yA: Type
R: A -> A -> Prop
x, y: Artclos' R x y -> rtclos R x yA: Type
R: A -> A -> Prop
x, y: Artclos R x y -> rtclos' R x yA: Type
R: A -> A -> Prop
x, y: A
h: rtclos R x yrtclos' R x yA: Type
R: A -> A -> Prop
x: Artclos' R x xA: Type
R: A -> A -> Prop
x, y: A
H: R x yrtclos' R x yA: Type
R: A -> A -> Prop
x, y, z: A
h1: rtclos R x y
h2: rtclos R y z
IHh1: rtclos' R x y
IHh2: rtclos' R y zrtclos' R x zconstructor.A: Type
R: A -> A -> Prop
x: Artclos' R x xA: Type
R: A -> A -> Prop
x, y: A
H: R x yrtclos' R x yA: Type
R: A -> A -> Prop
x, y: A
H: R x yR x yA: Type
R: A -> A -> Prop
x, y: A
H: R x yrtclos' R y yassumption.A: Type
R: A -> A -> Prop
x, y: A
H: R x yR x yconstructor.A: Type
R: A -> A -> Prop
x, y: A
H: R x yrtclos' R y yA: Type
R: A -> A -> Prop
x, y, z: A
h1: rtclos R x y
h2: rtclos R y z
IHh1: rtclos' R x y
IHh2: rtclos' R y zrtclos' R x zall: assumption.A: Type
R: A -> A -> Prop
x, y, z: A
h1: rtclos R x y
h2: rtclos R y z
IHh1: rtclos' R x y
IHh2: rtclos' R y zrtclos' R x yA: Type
R: A -> A -> Prop
x, y, z: A
h1: rtclos R x y
h2: rtclos R y z
IHh1: rtclos' R x y
IHh2: rtclos' R y zrtclos' R y zA: Type
R: A -> A -> Prop
x, y: Artclos' R x y -> rtclos R x yA: Type
R: A -> A -> Prop
x: Artclos R x xA: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y zrtclos R x zconstructor.A: Type
R: A -> A -> Prop
x: Artclos R x xA: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y zrtclos R x zA: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y zrtclos R x yA: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y zrtclos R y zA: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y zrtclos R x yassumption.A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y zR x yassumption.A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y zrtclos R y z
Implementation of the Cantor pairing and its inverse function
We build a bijection between nat * nat and nat.
Require Import PeanoNat.
Cantor pairing to_nat
Note the following notation '(x,y) is performing pattern matching implicitly.
Cantor pairing inverse of_nat
EXERCISE
Show that of_nat is a left inverse of to_nat.
forall p : nat * nat, of_nat (to_nat p) = pforall p : nat * nat, of_nat (to_nat p) = pforall (n : nat) (p : nat * nat), to_nat p = n -> of_nat n = pH:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = pforall p : nat * nat, of_nat (to_nat p) = pforall (n : nat) (p : nat * nat), to_nat p = n -> of_nat n = pn: nat
p: nat * nat
h: to_nat p = nof_nat n = pp: nat * nat
h: to_nat p = 0of_nat 0 = pn: nat
p: nat * nat
h: to_nat p = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = pp: nat * nat
h: to_nat p = 0of_nat 0 = pp: nat * nat
h: to_nat p = 0(0, 0) = px, y: nat
h: to_nat (x, y) = 0(0, 0) = (x, y)x, y: nat
h: y + to_nat' (y + x) = 0(0, 0) = (x, y)x: nat
h: 0 + to_nat' (0 + x) = 0(0, 0) = (x, 0)x, y: nat
h: S y + to_nat' (S y + x) = 0(0, 0) = (x, S y)x: nat
h: 0 + to_nat' (0 + x) = 0(0, 0) = (x, 0)x: nat
h: to_nat' x = 0(0, 0) = (x, 0)h: to_nat' 0 = 0(0, 0) = (0, 0)x: nat
h: to_nat' (S x) = 0(0, 0) = (S x, 0)reflexivity.h: to_nat' 0 = 0(0, 0) = (0, 0)n: nat
p: nat * nat
h: to_nat p = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = pn, x, y: nat
h: to_nat (x, y) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (x, y)n, x, y: nat
h: y + to_nat' (y + x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (x, y)n, x: nat
h: 0 + to_nat' (0 + x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (x, 0)n, x, y: nat
h: S y + to_nat' (S y + x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (x, S y)n, x: nat
h: 0 + to_nat' (0 + x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (x, 0)n, x: nat
h: to_nat' x = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (x, 0)n: nat
h: to_nat' 0 = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (0, 0)n, x: nat
h: to_nat' (S x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (S x, 0)n, x: nat
h: to_nat' (S x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (S x, 0)n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pmatch of_nat n with | (0, y) => (S y, 0) | (S x1, y) => (x1, S y) end = (S x, 0)n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p(S x, 0) = (S x, 0)n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pto_nat (0, x) = nreflexivity.n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p(S x, 0) = (S x, 0)n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pto_nat (0, x) = nn, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = px + to_nat' (x + 0) = nlia.n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = px + to_nat' x = nn, x, y: nat
h: S y + to_nat' (S y + x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pof_nat (S n) = (x, S y)n, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pmatch of_nat n with | (0, y0) => (S y0, 0) | (S x1, y0) => (x1, S y0) end = (x, S y)n, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p(x, S y) = (x, S y)n, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pto_nat (S x, y) = nreflexivity.n, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p(x, S y) = (x, S y)n, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = pto_nat (S x, y) = nn, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = py + to_nat' (y + S x) = nn, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = py + to_nat' (S y + x) = nlia.n, x, y: nat
h: S (y + S (y + x + to_nat' (y + x))) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = py + S (y + x + to_nat' (y + x)) = nH:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = pforall p : nat * nat, of_nat (to_nat p) = pH:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = p
p: nat * natof_nat (to_nat p) = preflexivity.H:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = p
p: nat * natto_nat p = to_nat p
EXERCISE
Show to_nat is injective.
forall p q : nat * nat, to_nat p = to_nat q -> p = qforall p q : nat * nat, to_nat p = to_nat q -> p = qp, q: nat * nat
e: to_nat p = to_nat qp = qp, q: nat * nat
e: of_nat (to_nat p) = of_nat (to_nat q)p = q
[2!] means do the rewrite twice.
assumption.p, q: nat * nat
e: p = qp = q
EXERCISE
Show to_nat is a left inverse to of_nat.
forall n : nat, to_nat (of_nat n) = nforall n : nat, to_nat (of_nat n) = nn: natto_nat (of_nat n) = nto_nat (of_nat 0) = 0n: nat
ih: to_nat (of_nat n) = nto_nat (of_nat (S n)) = S nreflexivity.to_nat (of_nat 0) = 0n: nat
ih: to_nat (of_nat n) = nto_nat (of_nat (S n)) = S nn: nat
ih: to_nat (of_nat n) = nto_nat match of_nat n with | (0, y) => (S y, 0) | (S x0, y) => (x0, S y) end = S nn, x, y: nat
ih: to_nat (x, y) = nto_nat match x with | 0 => (S y, 0) | S x0 => (x0, S y) end = S nn, y: nat
ih: to_nat (0, y) = nto_nat (S y, 0) = S nn, x, y: nat
ih: to_nat (S x, y) = nto_nat (x, S y) = S nn, y: nat
ih: to_nat (0, y) = nto_nat (S y, 0) = S nn, y: nat
ih: y + to_nat' (y + 0) = nS (y + to_nat' y) = S nlia.n, y: nat
ih: y + to_nat' y = nS (y + to_nat' y) = S nn, x, y: nat
ih: to_nat (S x, y) = nto_nat (x, S y) = S nn, x, y: nat
ih: y + to_nat' (y + S x) = nS (y + S (y + x + to_nat' (y + x))) = S nn, x, y: nat
ih: y + to_nat' (S y + x) = nS (y + S (y + x + to_nat' (y + x))) = S nlia.n, x, y: nat
ih: y + S (y + x + to_nat' (y + x)) = nS (y + S (y + x + to_nat' (y + x))) = S n
EXERCISE
Show of_nat is injective.
forall n m : nat, of_nat n = of_nat m -> n = mforall n m : nat, of_nat n = of_nat m -> n = m
The following notation applies f_equal to_nat to e.
n, m: nat
e: to_nat (of_nat n) = to_nat (of_nat m)n = massumption.n, m: nat
e: n = mn = m
Church encodings
It is possible to encode natural numbers (and other data types) using so-called Church encodings that you might have seen in a λ-calculus class. Below, num is the definition of Church numerals.
EXERCISE
forall n m : nat, add (from_nat n) (from_nat m) = from_nat (n + m)forall n m : nat, add (from_nat n) (from_nat m) = from_nat (n + m)n, m: natadd (from_nat n) (from_nat m) = from_nat (n + m)m: natadd (from_nat 0) (from_nat m) = from_nat (0 + m)n, m: nat
ih: add (from_nat n) (from_nat m) = from_nat (n + m)add (from_nat (S n)) (from_nat m) = from_nat (S n + m)reflexivity.m: natadd (from_nat 0) (from_nat m) = from_nat (0 + m)n, m: nat
ih: add (from_nat n) (from_nat m) = from_nat (n + m)add (from_nat (S n)) (from_nat m) = from_nat (S n + m)n, m: nat
ih: add (from_nat n) (from_nat m) = from_nat (n + m)add (succ (from_nat n)) (from_nat m) = succ (from_nat (n + m))reflexivity.n, m: nat
ih: add (from_nat n) (from_nat m) = from_nat (n + m)add (succ (from_nat n)) (from_nat m) = succ (add (from_nat n) (from_nat m))
EXERCISE
EXERCISE
forall n m : nat, mul (from_nat n) (from_nat m) = from_nat (n * m)forall n m : nat, mul (from_nat n) (from_nat m) = from_nat (n * m)n, m: natmul (from_nat n) (from_nat m) = from_nat (n * m)m: natmul (from_nat 0) (from_nat m) = from_nat (0 * m)n, m: nat
ih: mul (from_nat n) (from_nat m) = from_nat (n * m)mul (from_nat (S n)) (from_nat m) = from_nat (S n * m)m: natmul (from_nat 0) (from_nat m) = from_nat (0 * m)reflexivity.m: natmul zero (from_nat m) = zeron, m: nat
ih: mul (from_nat n) (from_nat m) = from_nat (n * m)mul (from_nat (S n)) (from_nat m) = from_nat (S n * m)n, m: nat
ih: mul (from_nat n) (from_nat m) = from_nat (n * m)mul (succ (from_nat n)) (from_nat m) = from_nat (m + n * m)n, m: nat
ih: mul (from_nat n) (from_nat m) = from_nat (n * m)mul (succ (from_nat n)) (from_nat m) = add (from_nat m) (from_nat (n * m))reflexivity.n, m: nat
ih: mul (from_nat n) (from_nat m) = from_nat (n * m)mul (succ (from_nat n)) (from_nat m) = add (from_nat m) (mul (from_nat n) (from_nat m))
EXERCISE
Define the power function (check out the next exercise to make sure you see what it should give).
EXERCISE
n, m: natexp (from_nat n) (from_nat m) = from_nat (n ^ m)n, m: natexp (from_nat n) (from_nat m) = from_nat (n ^ m)n: natexp (from_nat n) (from_nat 0) = from_nat (n ^ 0)n, m: nat
ih: exp (from_nat n) (from_nat m) = from_nat (n ^ m)exp (from_nat n) (from_nat (S m)) = from_nat (n ^ S m)reflexivity.n: natexp (from_nat n) (from_nat 0) = from_nat (n ^ 0)n, m: nat
ih: exp (from_nat n) (from_nat m) = from_nat (n ^ m)exp (from_nat n) (from_nat (S m)) = from_nat (n ^ S m)n, m: nat
ih: exp (from_nat n) (from_nat m) = from_nat (n ^ m)exp (from_nat n) (succ (from_nat m)) = from_nat (n * n ^ m)n, m: nat
ih: exp (from_nat n) (from_nat m) = from_nat (n ^ m)exp (from_nat n) (succ (from_nat m)) = mul (from_nat n) (from_nat (n ^ m))reflexivity.n, m: nat
ih: exp (from_nat n) (from_nat m) = from_nat (n ^ m)exp (from_nat n) (succ (from_nat m)) = mul (from_nat n) (exp (from_nat n) (from_nat m))
EXERCISE
Define a predecessor function.
For the solution we also encode pairs.
EXERCISE
n: natpred' (from_nat n) = pair (from_nat (Nat.pred n)) (from_nat n)n: natpred' (from_nat n) = pair (from_nat (Nat.pred n)) (from_nat n)pred' (from_nat 0) = pair (from_nat (Nat.pred 0)) (from_nat 0)n: nat
ih: pred' (from_nat n) = pair (from_nat (Nat.pred n)) (from_nat n)pred' (from_nat (S n)) = pair (from_nat (Nat.pred (S n))) (from_nat (S n))reflexivity.pred' (from_nat 0) = pair (from_nat (Nat.pred 0)) (from_nat 0)n: nat
ih: pred' (from_nat n) = pair (from_nat (Nat.pred n)) (from_nat n)pred' (from_nat (S n)) = pair (from_nat (Nat.pred (S n))) (from_nat (S n))n: nat
ih: pred' (from_nat n) = pair (from_nat (Nat.pred n)) (from_nat n)pred' (succ (from_nat n)) = pair (from_nat n) (succ (from_nat n))n: nat
ih:= from_nat n (prod num num) (fun p: prod num num => pair (snd p) (succ (snd p))) (pair zero zero) = pair (from_nat (Nat.pred n)) (from_nat n)succ (from_nat n) (prod num num) (fun p : prod num num => pair (snd p) (succ (snd p))) (pair zero zero) = pair (from_nat n) (succ (from_nat n))n: nat
ih:= from_nat n (prod num num) (fun p: prod num num => pair (snd p) (succ (snd p))) (pair zero zero) = pair (from_nat (Nat.pred n)) (from_nat n)pair (snd (from_nat n (prod num num) (fun p : prod num num => pair (snd p) (succ (snd p))) (pair zero zero))) (succ (snd (from_nat n (prod num num) (fun p : prod num num => pair (snd p) (succ (snd p))) (pair zero zero)))) = pair (from_nat n) (succ (from_nat n))reflexivity.n: nat
ih:= from_nat n (prod num num) (fun p: prod num num => pair (snd p) (succ (snd p))) (pair zero zero) = pair (from_nat (Nat.pred n)) (from_nat n)pair (snd (pair (from_nat (Nat.pred n)) (from_nat n))) (succ (snd (pair (from_nat (Nat.pred n)) (from_nat n)))) = pair (from_nat n) (succ (from_nat n))n: natpred (from_nat n) = from_nat (Nat.pred n)n: natpred (from_nat n) = from_nat (Nat.pred n)n: natfst (pred' (from_nat n)) = from_nat (Nat.pred n)reflexivity.n: natfst (pair (from_nat (Nat.pred n)) (from_nat n)) = from_nat (Nat.pred n)