nus/cs3234/labs/week-04_more-about-soundness-and-completeness.v
2024-02-20 11:31:16 +08:00

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