Exercise session 2 — Part 2

🏠 Go back to the course homepage.

Set Default Goal Selector "!".

REPLACE_ME is declared
From Stdlib Require Import Nat List. Import ListNotations.
iter is defined
iter is recursively defined (guarded on 3rd argument)

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: nat

x ^ n = iter (mul x) n 1
n, x: nat

x ^ n = iter (mul x) n 1
x: nat

x ^ 0 = iter (mul x) 0 1
n, x: nat
ih: x ^ n = iter (mul x) n 1
x ^ S n = iter (mul x) (S n) 1
x: nat

x ^ 0 = iter (mul x) 0 1
x: nat

1 = 1
reflexivity.
n, x: nat
ih: x ^ n = iter (mul x) n 1

x ^ S n = iter (mul x) (S n) 1
n, x: nat
ih: x ^ n = iter (mul x) n 1

x * x ^ n = x * iter (mul x) n 1
n, x: nat
ih: x ^ n = iter (mul x) n 1

x * iter (mul x) n 1 = x * iter (mul x) n 1
reflexivity.
iter_pow is defined

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: A

iter f (S n) x = iter f n (f x)
A: Type
f: A -> A
n: nat
x: A

iter f (S n) x = iter f n (f x)
A: Type
f: A -> A
x: A

iter 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
x: A

iter f 1 x = iter f 0 (f x)
reflexivity.
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))
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)
reflexivity.
iter_shift is defined
le' is defined
le'_ind is defined
le'_sind is defined

EXERCISE

Spell out the induction principle of le' without checking it. Notice that it's not the same definition as in the live coding.

le'_ind : forall P : nat -> nat -> Prop, (forall n : nat, P 0 n) -> (forall n m : nat, le' n m -> P n m -> P (S n) (S m)) -> forall n m : nat, le' n m -> P n m : forall P : nat -> nat -> Prop, (forall n : nat, P 0 n) -> (forall n m : nat, le' n m -> P n m -> P (S n) (S m)) -> forall n m : nat, le' n m -> P n m

EXERCISE

Prove the following and lemmas that you need by induction. Do not use the standard library or lia!


forall n : nat, 0 <= n

forall n : nat, 0 <= n
n: nat

0 <= n

0 <= 0
n: nat
ih: 0 <= n
0 <= S n

0 <= 0
constructor.
n: nat
ih: 0 <= n

0 <= S n
n: nat
ih: 0 <= n

0 <= n
assumption.
le_0_n is defined

forall n m : nat, n <= m -> S n <= S m

forall n m : nat, n <= m -> S n <= S m
n, m: nat
h: n <= m

S n <= S m
n: nat

S n <= S n
n, m: nat
h: n <= m
IHh: S n <= S m
S n <= S (S m)
n: nat

S n <= S n
constructor.
n, m: nat
h: n <= m
IHh: S n <= S m

S n <= S (S m)
n, m: nat
h: n <= m
IHh: S n <= S m

S n <= S m
assumption.
le_n_S is defined

forall n : nat, le' n n

forall n : nat, le' n n
n: nat

le' n n

le' 0 0
n: nat
ih: le' n n
le' (S n) (S n)

le' 0 0
constructor.
n: nat
ih: le' n n

le' (S n) (S n)
n: nat
ih: le' n n

le' n n
assumption.
le'_refl is defined

forall 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 m

le' n (S m)
n: nat

le' 0 (S n)
n, m: nat
h: le' n m
IHh: le' n (S m)
le' (S n) (S (S m))
n: nat

le' 0 (S n)
constructor.
n, m: nat
h: le' n m
IHh: le' n (S m)

le' (S n) (S (S m))
n, m: nat
h: le' n m
IHh: le' n (S m)

le' n (S m)
assumption.
le'_n_S is defined
n, m: nat

le' n m <-> n <= m
n, m: nat

le' n m <-> n <= m
n, m: nat

le' n m -> n <= m
n, m: nat
n <= m -> le' n m
n, m: nat

le' n m -> n <= m
n, m: nat
h: le' n m

n <= m
n: nat

0 <= n
n, m: nat
h: le' n m
IHh: n <= m
S n <= S m
n: nat

0 <= n
apply le_0_n.
n, m: nat
h: le' n m
IHh: n <= m

S n <= S m
n, m: nat
h: le' n m
IHh: n <= m

n <= m
assumption.
n, m: nat

n <= m -> le' n m
n, m: nat
h: n <= m

le' n m
n: nat

le' n n
n, m: nat
h: n <= m
IHh: le' n m
le' n (S m)
n: nat

le' n n
apply le'_refl.
n, m: nat
h: n <= m
IHh: le' n m

le' n (S m)
n, m: nat
h: n <= m
IHh: le' n m

le' n m
assumption.
le_equiv is defined

EXERCISE

leb is defined
leb is recursively defined (guarded on 1st argument)

EXERCISE

n, m: nat

leb n m = true <-> n <= m
n, m: nat

leb n m = true <-> n <= m
n, m: nat

leb n m = true -> n <= m
n, m: nat
n <= m -> leb n m = true
n, m: nat

leb n m = true -> n <= m
n, m: nat
h: leb n m = true

n <= m
m: nat
h: leb 0 m = true

0 <= m
n, m: nat
h: leb (S n) m = true
ih:= forall m: nat, leb n m = true -> n <= m
S n <= m
m: nat
h: leb 0 m = true

0 <= m
apply le_0_n.
n, m: nat
h: leb (S n) m = true
ih:= forall m: nat, leb n m = true -> n <= m

S n <= m
n, m: nat
h: match m with | 0 => false | S m' => leb n m' end = true
ih:= forall m: nat, leb n m = true -> n <= m

S n <= m
n: nat
h: false = true
ih:= forall m: nat, leb n m = true -> n <= m

S n <= 0
n, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= m
S n <= S m
n, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= m

S n <= S m
n, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= m

n <= m
n, m: nat
h: leb n m = true
ih:= forall m: nat, leb n m = true -> n <= m

leb n m = true
assumption.
n, m: nat

n <= m -> leb n m = true
n, m: nat
h: n <= m

leb n m = true
n, m: nat
h: le' n m

leb n m = true
n: nat

leb 0 n = true
n, m: nat
h: le' n m
IHh: leb n m = true
leb (S n) (S m) = true
n: nat

leb 0 n = true
reflexivity.
n, m: nat
h: le' n m
IHh: leb n m = true

leb (S n) (S m) = true
n, m: nat
h: le' n m
IHh: leb n m = true

leb n m = true
assumption.
leb_spec is defined
even1 is defined
even2 is defined
even2 is recursively defined (guarded on 1st argument)

EXERCISE

Define an even predicate similar to how you would define a Boolean predicate but using propositions instead.

even3 is defined
even3 is recursively defined (guarded on 1st argument)
even4 is defined
even4_ind is defined
even4_sind is defined

EXERCISE

Spell out the induction principle of even4 without checking it.

even4_ind : forall P : nat -> Prop, P 0 -> (forall n : nat, even4 n -> P n -> P (S (S n))) -> forall n : nat, even4 n -> P n : forall P : nat -> Prop, P 0 -> (forall n : nat, even4 n -> P n -> P (S (S n))) -> forall n : nat, even4 n -> P n

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 n

forall P : nat -> Prop, (forall n : nat, (forall m : nat, m < n -> P m) -> P n) -> forall n : nat, P n
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat

P n
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat

forall m : nat, m <= n -> P m
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 m
P n
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
n: nat

forall m : nat, m <= n -> P m
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n

forall m : nat, m <= 0 -> P m
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
forall m : nat, m <= S n -> P m
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n

forall m : nat, m <= 0 -> P m
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
m: nat
hm: m <= 0

P m
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
m: nat
hm: m <= 0
H: m = 0

P 0
P: nat -> Prop
h:= forall n : nat, (forall m: nat, m < n -> P m) -> P n
m: nat
hm: m <= 0
H: m = 0

forall m0 : nat, m0 < 0 -> P m0
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 < 0

P k
lia.
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

forall m : nat, m <= S n -> P m
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

P m
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

forall m0 : nat, m0 < m -> P m0
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 < m

P k
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 < m

k <= n
lia.
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 m

P n
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 m

n <= n
lia.
strong_nat_ind is defined

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: nat

even1 n -> even2 n = true
n: nat

even1 n -> even2 n = true

Short for intros n h. destruct h as [m e]. subst e.:

  
m: nat

even2 (2 * m) = true

In fact the -> means rewriting e from left to right.

  

even2 (2 * 0) = true
m: nat
ih: even2 (2 * m) = true
even2 (2 * S m) = true

even2 (2 * 0) = true

true = true
reflexivity.
m: nat
ih: even2 (2 * m) = true

even2 (2 * S m) = true
m: nat
ih: even2 (2 * m) = true

even2 (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.

    
m: nat
ih: even2 (2 * m) = true

even2 (m + (m + 0)) = true
assumption.
even1_to_even2 is defined

EXERCISE

n: nat

even2 n = true <-> even3 n
n: nat

even2 n = true <-> even3 n
n: nat
ih:= forall m: nat, m < n -> even2 m = true <-> even3 m

even2 n = true <-> even3 n
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m

even2 0 = true <-> even3 0
ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 m
even2 1 = true <-> even3 1
n: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 m
even2 (S (S n)) = true <-> even3 (S (S n))
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m

even2 0 = true <-> even3 0
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m

true = true <-> True
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m

true = true -> True
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m
True -> true = true
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m

true = true -> True
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m
H: true = true

True
constructor.
ih:= forall m: nat, m < 0 -> even2 m = true <-> even3 m

True -> true = true
reflexivity.
ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 m

even2 1 = true <-> even3 1
ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 m

false = true <-> False
ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 m

false = true -> False
ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 m
False -> false = true
ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 m

false = true -> False
discriminate.
ih:= forall m: nat, m < 1 -> even2 m = true <-> even3 m

False -> false = true
contradiction.
n: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 m

even2 (S (S n)) = true <-> even3 (S (S n))
n: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 m

even2 n = true <-> even3 n
n: nat
ih:= forall m: nat, m < S (S n) -> even2 m = true <-> even3 m

n < S (S n)
lia.
even2_iff_even3 is defined

EXERCISE

Hint: The tactic contradiction is useful if you have an obviously false hypothesis.

n: nat

even3 n -> even4 n
n: nat

even3 n -> even4 n
n: nat
h: even3 n

even4 n
n: nat
ih:= forall m: nat, m < n -> even3 m -> even4 m
h: even3 n

even4 n
ih:= forall m: nat, m < 0 -> even3 m -> even4 m
h: even3 0

even4 0
ih:= forall m: nat, m < 1 -> even3 m -> even4 m
h: even3 1
even4 1
n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))
even4 (S (S n))
ih:= forall m: nat, m < 0 -> even3 m -> even4 m
h: even3 0

even4 0
constructor.
ih:= forall m: nat, m < 1 -> even3 m -> even4 m
h: even3 1

even4 1
ih:= forall m: nat, m < 1 -> even3 m -> even4 m
h: False

even4 1
contradiction.
n: 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 n
n: 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 n
n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))

n < S (S n)
lia.
n: nat
ih:= forall m: nat, m < S (S n) -> even3 m -> even4 m
h: even3 (S (S n))

even3 n
assumption.
even3_to_even4 is defined

EXERCISE

n: nat

even4 n -> even1 n
n: nat

even4 n -> even1 n
n: nat
h: even4 n

even1 n
n: nat
h: even4 n

exists m : nat, n = 2 * m

exists m : nat, 0 = 2 * m
n: nat
h: even4 n
ih:= exists m: nat, n = 2 * m
exists m : nat, S (S n) = 2 * m

exists m : nat, 0 = 2 * m

0 = 2 * 0
reflexivity.
n: nat
h: even4 n
ih:= exists m: nat, n = 2 * m

exists m : nat, S (S n) = 2 * m
m: nat
h: even4 (2 * m)

exists m0 : nat, S (S (2 * m)) = 2 * m0
m: nat
h: even4 (2 * m)

S (S (2 * m)) = 2 * S m
lia.
even4_to_even1 is defined

Membership in a list

In is defined
In is recursively defined (guarded on 3rd argument)

EXERCISE

Propose an inductive definition of membership (add the missing constructor(s)).

In_i is defined
In_i_ind is defined
In_i_sind is defined

EXERCISE

A: Type
x: A
l: list A

In x l <-> In_i x l
A: Type
x: A
l: list A

In x l <-> In_i x l
A: Type
x: A
l: list A

In x l -> In_i x l
A: Type
x: A
l: list A
In_i x l -> In x l
A: Type
x: A
l: list A

In x l -> In_i x l
A: Type
x: A
l: list A
h: In x l

In_i x l
A: 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 l
In_i x (a :: l)
A: Type
x: A
h: In x []

In_i x []
A: Type
x: A
h: False

In_i x []
contradiction.
A: Type
x, a: A
l: list A
h:= In x (a :: l)
ih: In x l -> In_i x l

In_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 l

In_i x (a :: l)
A: Type
x: A
l: list A
ih: In x l -> In_i x l

In_i x (x :: l)
A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x l
In_i x (a :: l)
A: Type
x: A
l: list A
ih: In x l -> In_i x l

In_i x (x :: l)
constructor.
A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x l

In_i x (a :: l)
A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x l

In_i x l
A: Type
x, a: A
l: list A
h: In x l
ih: In x l -> In_i x l

In x l
assumption.
A: Type
x: A
l: list A

In_i x l -> In x l
A: Type
x: A
l: list A
h: In_i x l

In x l
A: Type
x: A
l: list A

In x (x :: l)
A: Type
x, y: A
l: list A
h: In_i x l
IHh: In x l
In x (y :: l)
A: Type
x: A
l: list A

In x (x :: l)
A: Type
x: A
l: list A

x = x \/ In x l
A: Type
x: A
l: list A

x = x
reflexivity.
A: Type
x, y: A
l: list A
h: In_i x l
IHh: In x l

In x (y :: l)
A: Type
x, y: A
l: list A
h: In_i x l
IHh: In x l

y = x \/ In x l
A: Type
x, y: A
l: list A
h: In_i x l
IHh: In x l

In x l
assumption.
In_iff is defined

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.

fact_fix is defined
fact_fix is recursively defined (guarded on 1st argument)
fact_iter_f is defined
fact_iter is defined

forall n : nat, fact_fix n = fact_iter n

forall n : nat, fact_fix n = fact_iter n
n: nat

fact_fix n = fact_iter n
n: nat

fact_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)

(0, 1) = (0, 1)
reflexivity.
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)
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)
reflexivity.
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
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))
assumption.
fact_equiv is defined
Interactive Module Fib_Iter started

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.

  
sigma is defined
fib is defined

EXERCISE

  

fib 0 = 0

fib 0 = 0
reflexivity.
fib_eq0 is defined

EXERCISE

  

fib 1 = 1

fib 1 = 1
reflexivity.
fib_eq1 is defined

EXERCISE

Note. It's proven by reflexivity directly!

  

forall n : nat, fib (S (S n)) = fib n + fib (S n)

forall n : nat, fib (S (S n)) = fib n + fib (S n)
reflexivity.
fib_eq3 is defined
Module Fib_Iter is defined
rtclos is defined
rtclos_ind is defined
rtclos_sind is defined
rtclos' is defined
rtclos'_ind is defined
rtclos'_sind is defined

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 z

forall (A : Type) (R : A -> A -> Prop) (x y z : A), rtclos' R x y -> rtclos' R y z -> rtclos' R x z
A: Type
R: A -> A -> Prop
x, y, z: A
hxy: rtclos' R x y
hyz: rtclos' R y z

rtclos' R x z
A: Type
R: A -> A -> Prop
z, x: A
hyz: rtclos' R x z

rtclos' R x z
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 z
rtclos' R x z
A: Type
R: A -> A -> Prop
z, x: A
hyz: rtclos' R x z

rtclos' R x z
assumption.

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 z

rtclos' R x z
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 z

R x y
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 z
rtclos' R y z
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 z

R x y
assumption.
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 z

rtclos' R y z
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 z

rtclos' R w z
assumption.
rtclos'_trans is defined

EXERCISE


forall (A : Type) (R : A -> A -> Prop) (x y : A), rtclos R x y <-> rtclos' R x y

forall (A : Type) (R : A -> A -> Prop) (x y : A), rtclos R x y <-> rtclos' R x y
A: Type
R: A -> A -> Prop
x, y: A

rtclos R x y <-> rtclos' R x y
A: Type
R: A -> A -> Prop
x, y: A

rtclos R x y -> rtclos' R x y
A: Type
R: A -> A -> Prop
x, y: A
rtclos' R x y -> rtclos R x y
A: Type
R: A -> A -> Prop
x, y: A

rtclos R x y -> rtclos' R x y
A: Type
R: A -> A -> Prop
x, y: A
h: rtclos R x y

rtclos' R x y
A: Type
R: A -> A -> Prop
x: A

rtclos' R x x
A: Type
R: A -> A -> Prop
x, y: A
H: R x y
rtclos' R x y
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 z
rtclos' R x z
A: Type
R: A -> A -> Prop
x: A

rtclos' R x x
constructor.
A: Type
R: A -> A -> Prop
x, y: A
H: R x y

rtclos' R x y
A: Type
R: A -> A -> Prop
x, y: A
H: R x y

R x y
A: Type
R: A -> A -> Prop
x, y: A
H: R x y
rtclos' R y y
A: Type
R: A -> A -> Prop
x, y: A
H: R x y

R x y
assumption.
A: Type
R: A -> A -> Prop
x, y: A
H: R x y

rtclos' R y y
constructor.
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 z

rtclos' R x z
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 z

rtclos' R x y
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 z
rtclos' R y z
all: assumption.
A: Type
R: A -> A -> Prop
x, y: A

rtclos' R x y -> rtclos R x y
A: Type
R: A -> A -> Prop
x: A

rtclos R x x
A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y z
rtclos R x z
A: Type
R: A -> A -> Prop
x: A

rtclos R x x
constructor.
A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y z

rtclos R x z
A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y z

rtclos R x y
A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y z
rtclos R y z
A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y z

rtclos R x y
A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y z

R x y
assumption.
A: Type
R: A -> A -> Prop
x, y, z: A
H: R x y
H0: rtclos' R y z
IHrtclos': rtclos R y z

rtclos R y z
assumption.
rtclos_iff is defined

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

to_nat' is defined
to_nat' is recursively defined (guarded on 1st argument)

Note the following notation '(x,y) is performing pattern matching implicitly.

to_nat is defined

Cantor pairing inverse of_nat

of_nat is defined
of_nat is recursively defined (guarded on 1st argument)

EXERCISE

Show that of_nat is a left inverse of to_nat.


forall p : nat * nat, of_nat (to_nat p) = p

forall p : nat * nat, of_nat (to_nat p) = p

forall (n : nat) (p : nat * nat), to_nat p = n -> of_nat n = p
H:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = p
forall p : nat * nat, of_nat (to_nat p) = p

forall (n : nat) (p : nat * nat), to_nat p = n -> of_nat n = p
n: nat
p: nat * nat
h: to_nat p = n

of_nat n = p
p: nat * nat
h: to_nat p = 0

of_nat 0 = p
n: nat
p: nat * nat
h: to_nat p = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p
of_nat (S n) = p
p: nat * nat
h: to_nat p = 0

of_nat 0 = p
p: nat * nat
h: to_nat p = 0

(0, 0) = p
x, 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)
h: to_nat' 0 = 0

(0, 0) = (0, 0)
reflexivity.
n: nat
p: nat * nat
h: to_nat p = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p

of_nat (S n) = p
n, x, y: nat
h: to_nat (x, y) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p

of_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 = p

of_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 = p

of_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 = p
of_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 = p

of_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 = p

of_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 = p

of_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 = p
of_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 = p

of_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 = p

match 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 = p
to_nat (0, x) = n
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)
reflexivity.
n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p

to_nat (0, x) = n
n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p

x + to_nat' (x + 0) = n
n, x: nat
h: S (x + to_nat' x) = S n
ih:= forall p: nat * nat, to_nat p = n -> of_nat n = p

x + to_nat' x = n
lia.
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 = p

of_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 = p

match 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 = p
to_nat (S x, y) = n
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)
reflexivity.
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

to_nat (S x, y) = n
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

y + to_nat' (y + S x) = n
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

y + to_nat' (S y + x) = n
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

y + S (y + x + to_nat' (y + x)) = n
lia.
H:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = p

forall p : nat * nat, of_nat (to_nat p) = p
H:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = p
p: nat * nat

of_nat (to_nat p) = p
H:= forall (n : nat) (p: nat * nat), to_nat p = n -> of_nat n = p
p: nat * nat

to_nat p = to_nat p
reflexivity.
cancel_of_to is defined

EXERCISE

Show to_nat is injective.


forall p q : nat * nat, to_nat p = to_nat q -> p = q

forall p q : nat * nat, to_nat p = to_nat q -> p = q
p, q: nat * nat
e: to_nat p = to_nat q

p = q
p, q: nat * nat
e: of_nat (to_nat p) = of_nat (to_nat q)

p = q

[2!] means do the rewrite twice.

  
p, q: nat * nat
e: p = q

p = q
assumption.
to_nat_inj is defined

EXERCISE

Show to_nat is a left inverse to of_nat.


forall n : nat, to_nat (of_nat n) = n

forall n : nat, to_nat (of_nat n) = n
n: nat

to_nat (of_nat n) = n

to_nat (of_nat 0) = 0
n: nat
ih: to_nat (of_nat n) = n
to_nat (of_nat (S n)) = S n

to_nat (of_nat 0) = 0
reflexivity.
n: nat
ih: to_nat (of_nat n) = n

to_nat (of_nat (S n)) = S n
n: nat
ih: to_nat (of_nat n) = n

to_nat match of_nat n with | (0, y) => (S y, 0) | (S x0, y) => (x0, S y) end = S n
n, x, y: nat
ih: to_nat (x, y) = n

to_nat match x with | 0 => (S y, 0) | S x0 => (x0, S y) end = S n
n, y: nat
ih: to_nat (0, y) = n

to_nat (S y, 0) = S n
n, x, y: nat
ih: to_nat (S x, y) = n
to_nat (x, S y) = S n
n, y: nat
ih: to_nat (0, y) = n

to_nat (S y, 0) = S n
n, y: nat
ih: y + to_nat' (y + 0) = n

S (y + to_nat' y) = S n
n, y: nat
ih: y + to_nat' y = n

S (y + to_nat' y) = S n
lia.
n, x, y: nat
ih: to_nat (S x, y) = n

to_nat (x, S y) = S n
n, x, y: nat
ih: y + to_nat' (y + S x) = n

S (y + S (y + x + to_nat' (y + x))) = S n
n, x, y: nat
ih: y + to_nat' (S y + x) = n

S (y + S (y + x + to_nat' (y + x))) = S n
n, x, y: nat
ih: y + S (y + x + to_nat' (y + x)) = n

S (y + S (y + x + to_nat' (y + x))) = S n
lia.
cancel_to_of is defined

EXERCISE

Show of_nat is injective.


forall n m : nat, of_nat n = of_nat m -> n = m

forall 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 = m
n, m: nat
e: n = m

n = m
assumption.
of_nat_inj is defined

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.

num is defined
zero is defined
succ is defined
from_nat is defined
from_nat is recursively defined (guarded on 1st argument)
add is defined
= fun (X : Prop) (s : X -> X) (z : X) => s (s (s (s (s z)))) : num

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: nat

add (from_nat n) (from_nat m) = from_nat (n + m)
m: nat

add (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)
m: nat

add (from_nat 0) (from_nat m) = from_nat (0 + m)
reflexivity.
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))
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))
reflexivity.
add_from_nat is defined

EXERCISE

mul is defined

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: nat

mul (from_nat n) (from_nat m) = from_nat (n * m)
m: nat

mul (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: nat

mul (from_nat 0) (from_nat m) = from_nat (0 * m)
m: nat

mul zero (from_nat m) = zero
reflexivity.
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)
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))
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))
reflexivity.
mul_from_nat is defined

EXERCISE

Define the power function (check out the next exercise to make sure you see what it should give).

exp is defined

EXERCISE

n, m: nat

exp (from_nat n) (from_nat m) = from_nat (n ^ m)
n, m: nat

exp (from_nat n) (from_nat m) = from_nat (n ^ m)
n: nat

exp (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: nat

exp (from_nat n) (from_nat 0) = from_nat (n ^ 0)
reflexivity.
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))
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))
reflexivity.
exp_from_nat is defined

EXERCISE

Define a predecessor function.

For the solution we also encode pairs.

prod is defined
pair is defined
fst is defined
snd is defined
pred' is defined
pred is defined

EXERCISE

n: nat

pred' (from_nat n) = pair (from_nat (Nat.pred n)) (from_nat n)
n: nat

pred' (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))

pred' (from_nat 0) = pair (from_nat (Nat.pred 0)) (from_nat 0)
reflexivity.
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))
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))
reflexivity.
pred'_from_nat is defined
n: nat

pred (from_nat n) = from_nat (Nat.pred n)
n: nat

pred (from_nat n) = from_nat (Nat.pred n)
n: nat

fst (pred' (from_nat n)) = from_nat (Nat.pred n)
n: nat

fst (pair (from_nat (Nat.pred n)) (from_nat n)) = from_nat (Nat.pred n)
reflexivity.
pred_from_nat is defined