Coq:如何证明 max a b <= a+b?
Coq: How to prove max a b <= a+b?
我无法使用 coq 的策略证明简单的逻辑 max a b <= a+b
。我应该如何解决它?以下是我迄今为止使用的代码。 s_le_n
已证明,为简单起见,此处不再赘述。
Theorem s_le_n: forall (a b: nat), a <= b -> S a <= S b.
Proof. Admitted.
Theorem max_sum: forall (a b: nat), max a b <= a + b.
Proof.
intros.
induction a.
- simpl. reflexivity.
- rewrite plus_Sn_m. induction b.
+ simpl. rewrite <- plus_n_O. reflexivity.
+ rewrite <- plus_Sn_m. simpl. apply s_le_n. rewrite IHa.
考虑到@re3el 的评论,我们从他们的 "pen and paper proof":
开始
if a>b max a b = a, a < a+b; else max a b = b, b < a+b
现在让我们把它翻译成 Coq!事实上,我们需要做的第一件事是 <
的可判定性,这是使用 le_lt_dec a b
引理完成的。剩下的就是例行公事了:
Require Import Arith.
Theorem max_sum (a b: nat) : max a b <= a + b.
Proof.
case (le_lt_dec a b).
+ now rewrite <- Nat.max_r_iff; intros ->; apply le_plus_r.
+ intros ha; apply Nat.lt_le_incl, Nat.max_l_iff in ha.
now rewrite ha; apply le_plus_l.
Qed.
但是,我们可以大大改进这个证明。有各种各样的候选者,使用 stdlib 的一个很好的是:
Theorem max_sum_1 (a b: nat) : max a b <= a + b.
Proof.
now rewrite Nat.max_lub_iff; split; [apply le_plus_l | apply le_plus_r].
Qed.
使用我选择的库 [math-comp],您可以链接重写以获得更紧凑的证明:
From mathcomp Require Import all_ssreflect.
Theorem max_sum_2 (a b: nat) : maxn a b <= a + b.
Proof. by rewrite geq_max leq_addl leq_addr. Qed.
事实上,根据简短的证明,也许根本就不需要原始引理。
编辑:@Jason Gross 提到了另一种更老练的人会使用的证明方式:
Proof. apply Max.max_case_strong; omega. Qed.
然而,这个证明涉及使用重量级的自动化策略,omega
;我强烈建议所有初学者暂时避免这种策略,并多学习如何做证明"manually"。事实上,使用任何启用 SMT 的策略,最初的目标都可以通过调用 SMT 来简单地解决。
我无法使用 coq 的策略证明简单的逻辑 max a b <= a+b
。我应该如何解决它?以下是我迄今为止使用的代码。 s_le_n
已证明,为简单起见,此处不再赘述。
Theorem s_le_n: forall (a b: nat), a <= b -> S a <= S b.
Proof. Admitted.
Theorem max_sum: forall (a b: nat), max a b <= a + b.
Proof.
intros.
induction a.
- simpl. reflexivity.
- rewrite plus_Sn_m. induction b.
+ simpl. rewrite <- plus_n_O. reflexivity.
+ rewrite <- plus_Sn_m. simpl. apply s_le_n. rewrite IHa.
考虑到@re3el 的评论,我们从他们的 "pen and paper proof":
开始if a>b max a b = a, a < a+b; else max a b = b, b < a+b
现在让我们把它翻译成 Coq!事实上,我们需要做的第一件事是 <
的可判定性,这是使用 le_lt_dec a b
引理完成的。剩下的就是例行公事了:
Require Import Arith.
Theorem max_sum (a b: nat) : max a b <= a + b.
Proof.
case (le_lt_dec a b).
+ now rewrite <- Nat.max_r_iff; intros ->; apply le_plus_r.
+ intros ha; apply Nat.lt_le_incl, Nat.max_l_iff in ha.
now rewrite ha; apply le_plus_l.
Qed.
但是,我们可以大大改进这个证明。有各种各样的候选者,使用 stdlib 的一个很好的是:
Theorem max_sum_1 (a b: nat) : max a b <= a + b.
Proof.
now rewrite Nat.max_lub_iff; split; [apply le_plus_l | apply le_plus_r].
Qed.
使用我选择的库 [math-comp],您可以链接重写以获得更紧凑的证明:
From mathcomp Require Import all_ssreflect.
Theorem max_sum_2 (a b: nat) : maxn a b <= a + b.
Proof. by rewrite geq_max leq_addl leq_addr. Qed.
事实上,根据简短的证明,也许根本就不需要原始引理。
编辑:@Jason Gross 提到了另一种更老练的人会使用的证明方式:
Proof. apply Max.max_case_strong; omega. Qed.
然而,这个证明涉及使用重量级的自动化策略,omega
;我强烈建议所有初学者暂时避免这种策略,并多学习如何做证明"manually"。事实上,使用任何启用 SMT 的策略,最初的目标都可以通过调用 SMT 来简单地解决。