364 lines
8.6 KiB
Coq
364 lines
8.6 KiB
Coq
(* week-04_more-about-soundness-and-completeness.v *)
|
|
(* LPP 2023 - CS3234 2023-2024, Sem2 *)
|
|
(* Olivier Danvy <danvy@yale-nus.edu.sg> *)
|
|
(* Version of 09 Feb 2024 *)
|
|
|
|
(* ********** *)
|
|
|
|
(* Paraphernalia: *)
|
|
|
|
Require Import Arith.
|
|
|
|
(* ********** *)
|
|
|
|
Definition recursive_specification_of_addition (add : nat -> nat -> nat) :=
|
|
(forall y : nat,
|
|
add O y = y)
|
|
/\
|
|
(forall x' y : nat,
|
|
add (S x') y = S (add x' y)).
|
|
|
|
(* ********** *)
|
|
|
|
Lemma about_a_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j : nat,
|
|
add i j = i + j.
|
|
Proof.
|
|
intro add.
|
|
unfold recursive_specification_of_addition.
|
|
intros [S_add_O S_add_S] i.
|
|
induction i as [ | i' IHi'].
|
|
- intro j.
|
|
rewrite -> (Nat.add_0_l j).
|
|
exact (S_add_O j).
|
|
- intro j.
|
|
rewrite -> (S_add_S i' j).
|
|
Check (plus_Sn_m i' j).
|
|
rewrite -> (plus_Sn_m i' j).
|
|
rewrite -> (IHi' j).
|
|
reflexivity.
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Proposition soundness_of_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j k : nat,
|
|
add i j = k ->
|
|
i + j = k.
|
|
Proof.
|
|
intros add S_add i j k H_k.
|
|
symmetry.
|
|
rewrite <- H_k.
|
|
exact (about_a_recursive_addition add S_add i j).
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Proposition completeness_of_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j k : nat,
|
|
i + j = k ->
|
|
add i j = k.
|
|
Proof.
|
|
intros add S_add i j k H_k.
|
|
rewrite <- H_k.
|
|
exact (about_a_recursive_addition add S_add i j).
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Lemma about_decomposing_a_pair_using_the_injection_tactic :
|
|
forall i j : nat,
|
|
(i, j) = (0, 1) ->
|
|
i = 0 /\ j = 1.
|
|
Proof.
|
|
intros i j H_ij.
|
|
injection H_ij.
|
|
|
|
Restart.
|
|
|
|
intros i j H_ij.
|
|
injection H_ij as H_i H_j.
|
|
exact (conj H_i H_j).
|
|
Qed.
|
|
|
|
Lemma about_decomposing_a_pair_using_the_injection_tactic' :
|
|
forall i j : nat,
|
|
(i, 1) = (0, j) ->
|
|
i = 0 /\ j = 1.
|
|
Proof.
|
|
intros i j H_ij.
|
|
injection H_ij as H_i H_j.
|
|
symmetry in H_j.
|
|
exact (conj H_i H_j).
|
|
Qed.
|
|
|
|
Lemma about_decomposing_a_pair_of_pairs_using_the_injection_tactic :
|
|
forall a b c d: nat,
|
|
((a, 1), (2, d)) = ((0, b), (c, 3)) ->
|
|
a = 0 /\ b = 1 /\ c = 2 /\ d = 3.
|
|
Proof.
|
|
intros a b c d H_abcd.
|
|
injection H_abcd as H_a H_b H_c H_d.
|
|
symmetry in H_b.
|
|
symmetry in H_c.
|
|
exact (conj H_a (conj H_b (conj H_c H_d))).
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Proposition true_is_not_false :
|
|
true <> false.
|
|
Proof.
|
|
unfold not.
|
|
intro H_absurd.
|
|
discriminate H_absurd.
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Proposition now_what :
|
|
(forall n : nat, n = S n) <-> 0 = 1.
|
|
Proof.
|
|
split.
|
|
|
|
- intro H_n_Sn.
|
|
Check (H_n_Sn 0).
|
|
exact (H_n_Sn 0).
|
|
|
|
- intro H_absurd.
|
|
discriminate H_absurd.
|
|
|
|
Restart.
|
|
|
|
split.
|
|
|
|
- intro H_n_Sn.
|
|
Check (H_n_Sn 42).
|
|
discriminate (H_n_Sn 42).
|
|
|
|
- intro H_absurd.
|
|
discriminate H_absurd.
|
|
Qed.
|
|
|
|
Proposition what_now :
|
|
forall n : nat,
|
|
n = S n <-> 0 = 1.
|
|
Proof.
|
|
intro n.
|
|
split.
|
|
|
|
- intro H_n.
|
|
Search (_ <> S _).
|
|
Check (n_Sn n).
|
|
assert (H_tmp := n_Sn n).
|
|
unfold not in H_tmp.
|
|
Check (H_tmp H_n).
|
|
contradiction (H_tmp H_n).
|
|
|
|
- intro H_absurd.
|
|
discriminate H_absurd.
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Proposition soundness_of_recursive_addition_revisited :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j k : nat,
|
|
add i j = k ->
|
|
i + j = k.
|
|
Proof.
|
|
intro add.
|
|
unfold recursive_specification_of_addition.
|
|
intros [S_add_O S_add_S] i.
|
|
induction i as [ | i' IHi'].
|
|
- intros j k H_add.
|
|
rewrite -> (S_add_O j) in H_add.
|
|
rewrite -> H_add.
|
|
exact (Nat.add_0_l k).
|
|
- intros j k H_add.
|
|
rewrite -> (S_add_S i' j) in H_add.
|
|
case k as [ | k'].
|
|
+ discriminate H_add.
|
|
+ injection H_add as H_add.
|
|
Check (IHi' j k').
|
|
Check (IHi' j k' H_add).
|
|
rewrite <- (IHi' j k' H_add).
|
|
Check plus_Sn_m.
|
|
exact (plus_Sn_m i' j).
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Proposition completeness_of_recursive_addition_revisited :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j k : nat,
|
|
i + j = k ->
|
|
add i j = k.
|
|
Proof.
|
|
intro add.
|
|
unfold recursive_specification_of_addition.
|
|
intros [S_add_O S_add_S] i j.
|
|
induction i as [ | i' IHi'].
|
|
- intros k H_k.
|
|
rewrite -> (Nat.add_0_l j) in H_k.
|
|
rewrite <- H_k.
|
|
exact (S_add_O j).
|
|
- intros k H_k.
|
|
rewrite -> (S_add_S i' j).
|
|
rewrite -> (plus_Sn_m i' j) in H_k.
|
|
case k as [ | k'].
|
|
+ discriminate H_k.
|
|
+ injection H_k as H_k.
|
|
Check (IHi' k').
|
|
Check (IHi' k' H_k).
|
|
rewrite <- (IHi' k' H_k).
|
|
reflexivity.
|
|
|
|
Restart.
|
|
|
|
intro add.
|
|
unfold recursive_specification_of_addition.
|
|
intros [S_add_O S_add_S] i j.
|
|
induction i as [ | i' IHi'].
|
|
- intros k H_k.
|
|
rewrite -> (Nat.add_0_l j) in H_k.
|
|
rewrite <- H_k.
|
|
exact (S_add_O j).
|
|
- intros k H_k.
|
|
rewrite -> (S_add_S i' j).
|
|
rewrite -> (plus_Sn_m i' j) in H_k.
|
|
Check (IHi' (i' + j)).
|
|
Check (IHi' (i' + j) (eq_refl (i' + j))).
|
|
rewrite -> (IHi' (i' + j) (eq_refl (i' + j))).
|
|
exact H_k.
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Check Nat.add_assoc.
|
|
|
|
Corollary associativity_of_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j k : nat,
|
|
add i (add j k) = add (add i j) k.
|
|
Proof.
|
|
intros add S_add i j k.
|
|
rewrite -> (about_a_recursive_addition add S_add i (add j k)).
|
|
rewrite -> (about_a_recursive_addition add S_add j k).
|
|
rewrite -> (about_a_recursive_addition add S_add i j).
|
|
rewrite -> (about_a_recursive_addition add S_add (i + j) k).
|
|
exact (Nat.add_assoc i j k).
|
|
|
|
Restart.
|
|
|
|
intros add S_add i j k.
|
|
Check (soundness_of_recursive_addition add S_add i j (add i j) (eq_refl (add i j))).
|
|
rewrite <- (soundness_of_recursive_addition add S_add j k (add j k) (eq_refl (add j k))).
|
|
rewrite <- (soundness_of_recursive_addition add S_add i (j + k) (add i (j + k)) (eq_refl (add i (j + k)))).
|
|
Check (soundness_of_recursive_addition add S_add i j (add i j) (eq_refl (add i j))).
|
|
rewrite <- (soundness_of_recursive_addition add S_add i j (add i j) (eq_refl (add i j))).
|
|
Check (soundness_of_recursive_addition add S_add (i + j) k (add (i + j) k) (eq_refl (add (i + j) k))).
|
|
rewrite <- (soundness_of_recursive_addition add S_add (i + j) k (add (i + j) k) (eq_refl (add (i + j) k))).
|
|
exact (Nat.add_assoc i j k).
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
Check Nat.add_comm.
|
|
|
|
Lemma commutativity_of_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j : nat,
|
|
add i j = add j i.
|
|
Proof.
|
|
Admitted. (* for the sake of the argument below *)
|
|
|
|
Corollary commutativity_of_Nat_dot_add :
|
|
forall add : nat -> nat -> nat,
|
|
recursive_specification_of_addition add ->
|
|
forall i j : nat,
|
|
i + j = j + i.
|
|
Proof.
|
|
intros add S_add i j.
|
|
Check (about_a_recursive_addition add S_add i j).
|
|
rewrite <- (about_a_recursive_addition add S_add i j).
|
|
rewrite <- (about_a_recursive_addition add S_add j i).
|
|
Check (commutativity_of_recursive_addition add S_add i j).
|
|
exact (commutativity_of_recursive_addition add S_add i j).
|
|
|
|
Restart.
|
|
|
|
intros add S_add i j.
|
|
Check (completeness_of_recursive_addition add S_add i j (i + j) (eq_refl (i + j))).
|
|
rewrite <- (completeness_of_recursive_addition add S_add i j (i + j) (eq_refl (i + j))).
|
|
rewrite <- (completeness_of_recursive_addition add S_add j i (j + i) (eq_refl (j + i))).
|
|
exact (commutativity_of_recursive_addition add S_add i j).
|
|
Qed.
|
|
|
|
(* ********** *)
|
|
|
|
(* Exercise 07 *)
|
|
|
|
Definition tail_recursive_specification_of_addition (add : nat -> nat -> nat) :=
|
|
(forall y : nat,
|
|
add O y = y)
|
|
/\
|
|
(forall x' y : nat,
|
|
add (S x') y = add x' (S y)).
|
|
|
|
(* ***** *)
|
|
|
|
Lemma about_a_tail_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
tail_recursive_specification_of_addition add ->
|
|
forall i j : nat,
|
|
add i j = i + j.
|
|
Proof.
|
|
Abort.
|
|
|
|
(* ***** *)
|
|
|
|
Proposition soundness_of_tail_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
tail_recursive_specification_of_addition add ->
|
|
forall i j k : nat,
|
|
add i j = k ->
|
|
i + j = k.
|
|
Proof.
|
|
(* first, as a corollary of about_a_tail_recursive_addition *)
|
|
|
|
Restart.
|
|
|
|
(* and second, by induction *)
|
|
Abort.
|
|
|
|
(* ***** *)
|
|
|
|
Proposition completeness_of_tail_recursive_addition :
|
|
forall add : nat -> nat -> nat,
|
|
tail_recursive_specification_of_addition add ->
|
|
forall i j k : nat,
|
|
i + j = k ->
|
|
add i j = k.
|
|
Proof.
|
|
(* first, as a corollary of about_a_tail_recursive_addition *)
|
|
|
|
Restart.
|
|
|
|
(* and second, by induction *)
|
|
Abort.
|
|
|
|
(* ********** *)
|
|
|
|
(* end of week-04_more-about-soundness-and-completeness.v *)
|