更多练习 More Exercises

20: 3 stars, standard, especially useful (mul_comm)

使用[assert]帮助证明[add_shuffle3]。你还不需要使用归纳法。

Theorem add_shuffle

Theorem add_shuffle3 : forall n m p : nat,
  n + (m + p) = m + (n + p).
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem add_shuffle3 : forall n m p : nat,
  n + (m + p) = m + (n + p).
Proof.
intros.
assert (H: n + (m + p) = (n + m) + p).
  { rewrite add_assoc. reflexivity. }
  rewrite H. assert (H': m + (n + p) = (m + n) + p).
  { rewrite add_assoc. reflexivity. }rewrite H'.  assert (H'': m + n = n + m).
  { rewrite add_comm. reflexivity. }rewrite H''.  reflexivity. Qed.

现在证明乘法的交换性。你可能想定义并证明一个“助手”定理,用于证明这个定理。提示:什么是n×(1+k)?

Theorem mul_commTheorem add_shuffle3 : forall n m p : nat,

Theorem mul_comm : forall m n : nat,
  m * n = n * m.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem helper : forall n k : nat,
n * (1+k) = n + n * k.
Proof.
induction n as [| n' IHn']. 
- simpl. reflexivity.
- simpl. intros k. rewrite -> IHn'. rewrite add_assoc. rewrite add_shuffle3. rewrite add_assoc. reflexivity. 
Qed.

Theorem helper' : forall n : nat,
S n = n + 1.
Proof.
induction n as [| n' IHn']. 
- simpl. reflexivity.
- simpl. rewrite -> IHn'. reflexivity. 
Qed.

Theorem mul_comm : forall m n : nat,
  m * n = n * m.
Proof.
intros. induction n as [| n' IHn'].
- simpl. rewrite mul_0_r. reflexivity.
- simpl. replace (S n') with (n' + 1).
-- rewrite add_comm. rewrite -> helper. rewrite -> IHn'. reflexivity.
-- rewrite <- helper'. reflexivity.
Qed.

21: 3 stars, standard, optional (more_exercises)

拿一张纸。对于以下每个定理,首先考虑(a)是否可以仅使用简化和重写来证明,(b)它还需要案例分析(析构函数),或者(c)它还需要归纳。写下你的预测。然后填写证明。(无需提交文件;这只是为了鼓励您在黑客攻击之前进行反思!)

Theorem leb_refl

Check leb.

Theorem leb_refl : forall n:nat,
  (n <=? n) = true.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem leb_refl : forall n:nat,
  (n <=? n) = true.
Proof.
intros. induction n as [| n' IHn'].
- simpl. reflexivity.
- simpl. rewrite -> IHn' . reflexivity.
Qed.

Theorem zero_neqb_S

Theorem zero_neqb_S : forall n:nat,
  0 =? (S n) = false.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem zero_neqb_S : forall n:nat,
  0 =? (S n) = false.
Proof.
intros []. 
- simpl. reflexivity.
- simpl. reflexivity.
Qed.

Theorem andb_false_r

Theorem andb_false_r : forall b : bool,
  andb b false = false.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem andb_false_r : forall b : bool,
  andb b false = false.
Proof.
intros []. 
- simpl. reflexivity.
- simpl. reflexivity.
Qed.

Theorem plus_leb_compat_l

Theorem plus_leb_compat_l : forall n m p : nat,
  n <=? m = true -> (p + n) <=? (p + m) = true.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem plus_leb_compat_l : forall n m p : nat,
  n <=? m = true -> (p + n) <=? (p + m) = true.
Proof.
intros. 
induction p as [| p' IHp'].
- simpl. rewrite -> H . reflexivity.
- simpl. rewrite -> IHp' . reflexivity.
Qed.

Theorem S_neqb_0

Theorem S_neqb_0 : forall n:nat,
  (S n) =? 0 = false.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem S_neqb_0 : forall n:nat,
  (S n) =? 0 = false.
Proof.
intros. 
induction n as [| n' IHn'].
- simpl. reflexivity.
- simpl. reflexivity.
Qed.

Theorem mult_1_l

Theorem mult_1_l : forall n:nat, 1 * n = n.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem mult_1_l : forall n:nat, 1 * n = n.
Proof.
intros. 
induction n as [| n' IHn'].
- simpl. reflexivity.
- simpl. assert (H:n' + 0 = 0 + n').
  { rewrite add_comm. reflexivity. }
  rewrite H. simpl.  reflexivity.
Qed.

Theorem all3_spec

Theorem all3_spec : forall b c : bool,
  orb
    (andb b c)
    (orb (negb b)
         (negb c))
  = true.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem all3_spec : forall b c : bool,
 orb
   (andb b c)
   (orb (negb b)
        (negb c))
 = true.
Proof.
intros [] [].
- simpl. reflexivity.
- simpl. reflexivity.
- simpl. reflexivity.
- simpl. reflexivity.
Qed.

Theorem mult_plus_distr_r

Theorem mult_plus_distr_r : forall n m p : nat,
  (n + m) * p = (n * p) + (m * p).
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem mult_plus_distr_r : forall n m p : nat,
(n + m) * p = (n * p) + (m * p).
Proof.
induction n as [| n' IHn']. 
- simpl. reflexivity.
- simpl. intros m p. rewrite -> IHn'. rewrite add_assoc. reflexivity. 
Qed.

Theorem mult_assoc

Theorem mult_assoc : forall n m p : nat,
n * (m * p) = (n * m) * p.
Proof.
(* FILL IN HERE *) Admitted.

Coq代码

Theorem mult_assoc : forall n m p : nat,
  n * (m * p) = (n * m) * p.
Proof.
induction n as [| n' IHn']. 
- simpl. intros m p. reflexivity.
- simpl. intros m p. rewrite -> mult_plus_distr_r.  rewrite -> IHn'. reflexivity.
Qed.

22: 2 stars, standard, optional (eqb_refl)

Theorem eqb_refl

Theorem eqb_refl : forall n : nat,
  (n =? n) = true.
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

   Theorem eqb_refl : forall n : nat,
 (n =? n) = true.
Proof.
induction n as [| n' IHn']. 
- simpl. reflexivity.
- simpl. rewrite -> IHn'. reflexivity.
Qed.回想一下您在[Basics]一章中为[binary]练习编写的[incr]和[bin_to_nat]函数。证明下图所示为通勤:

也就是说,增加一个二进制数,然后将其转换为(一元)自然数,得到的结果与首先将其转换为自然数,然后增加的结果相同。

命名你的定理[bin_to_nat_pres_incr](“pres”代表“preserves”)。

在开始进行此练习之前,请将[incr]和[bin_to_nat]的定义从您的解决方案复制到此处的[binary]练习中,以便此文件可以自行分级。如果您想更改原始定义以使属性更易于证明,请随意更改!*)

23: 2 stars, standard, optional (add_shuffle3')

[replace]策略允许您指定要重写的特定子项以及要重写的内容:[replace(t)with(u)]用表达式[u]替换目标中表达式[t]的(所有副本),并生成[t=u]作为附加子目标。当简单的[重写]操作目标的错误部分时,这通常很有用。

使用[replace]策略对[add_shuffle3']进行证明,就像[add_shuffle3]一样,但不需要[assert].

Theorem add_shuffle3'

Theorem add_shuffle3' : forall n m p : nat,
  n + (m + p) = m + (n + p).
Proof.
  (* FILL IN HERE *) Admitted.

Coq代码

Theorem add_shuffle3' : forall n m p : nat,
n + (m + p) = m + (n + p).
Proof.
intros.
replace (n + (m + p)) with ((n + m) + p).
replace (m + (n + p)) with ((m + n) + p).
- replace (m + n) with (n + m).
-- reflexivity. 
-- rewrite add_comm. reflexivity. 
- rewrite add_assoc. reflexivity. 
- rewrite add_assoc. reflexivity. 
Qed.

24: 3 stars, standard, especially useful (binary_commute)

回想一下您在[Basics]一章中为[binary]练习编写的[incr]和[bin_to_nat]函数。证明下图所示为通勤:

alt

也就是说,增加一个二进制数,然后将其转换为(一元)自然数,得到的结果与首先将其转换为自然数,然后增加的结果相同。

命名你的定理[bin_to_nat_pres_incr](“pres”代表“preserves”)。

在开始进行此练习之前,请将[incr]和[bin_to_nat]的定义从您的解决方案复制到此处的[binary]练习中,以便此文件可以自行分级。如果您想更改原始定义以使属性更易于证明,请随意更改!*)

(* FILL IN HERE *)
(* Do not modify the following line: *)
Definition manual_grade_for_binary_commute : option (nat×string) := None.

25: 5 stars, advanced (binary_inverse)

这是先前关于二进制数练习的进一步延续。您可能会发现,您需要返回并更改早期的定义,以便在这里工作。

(a) 首先,编写一个函数将自然数转换为二进制数。

Fixpoint nat_to_bin (n:nat) : bin
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

证明,如果我们从任何nat开始,将其转换为二进制,再将其转换回,我们得到的nat与我们开始使用的相同。(提示:如果你对nat_to_bin的定义涉及任何额外的函数,你可能需要证明一个辅助引理,说明这些函数如何与nat_to_bin相关。)

Theorem nat_bin_nat : forall n, bin_to_nat (nat_to_bin n) = n.
Proof.
  (* FILL IN HERE *) Admitted.

(* Do not modify the following line: *)
Definition manual_grade_for_binary_inverse_a : option (nat*string) := None.

(b) 人们可能会自然而然地认为我们也可以证明相反的方向——从一个二进制数开始,转换成一个自然数,然后返回到二进制数,应该得到与我们开始时相同的数。然而,事实并非如此!解释(在评论中)问题是什么。

(* FILL IN HERE *)
(* Do not modify the following line: *)

(c) 定义一个规范化函数——也就是说,一个函数直接从一个bin规范化到另一个bin规范化(即,不通过转换为nat和back),这样,对于任何二进制数b,将b转换为自然数,然后再转换回二进制产生(规范化b)。证明它。(警告:这部分有点棘手——你可能最终定义了几个辅助引理。找到你需要的一个好方法是从证明主语句开始,看看你在哪里卡住了,看看你是否能找到一个引理——可能需要它自己的归纳证明——这将使主证明取得进展。)不要用nat_to_bin和bin_to_nat来定义它!

(* FILL IN HERE *)
(* Do not modify the following line: *)
Definition manual_grade_for_binary_inverse_c : option (nat×string) := None.