>我有一个自然数列表,列表中的元素按降序排列。 我想写关于列表的引理,第一个元素h大于列表的所有元素。让列表为 [h;h1;t] .0 h1? 请指导我,如何写h大于列表尾部的所有元素。
你需要说
对于任何自然数,以及任何像
h::t
这样的列表,如果列表是降序的,如果数字在尾部,那么它比头部小。
所以你可以用辅酶语言写
Lemma head_is_max : forall n h t, desc (h::t) -> In n t -> h >= n.
如果 desc 是一个布尔谓词,你可以写
Lemma head_is_max : forall n h t, desc (h::t) = true -> In n t -> h >= n.
对t
进行归纳将用于证明。
以更复杂的方式,您可以使用列表上的谓词,该谓词断言列表的所有元素都具有特定属性,您可以将其定义为
Fixpoint All {T : Type} (P : T -> Prop) (l : list T) : Prop :=
match l with
| [] => True
| h :: t => P h / All P t
end.
所以All P l
意味着P x
对l
中的所有x
都成立。现在我们可以把提到的引理写成
Lemma head_is_max : forall h t, desc (h::t) -> All (fun n => h >= n) t.
要表示给定的自然数列表是按降序排列的,您可以使用 CoqList
模块中的现有函数。
Require Import List Lia.
Definition desc (l : list nat) : Prop :=
forall i j, i <= j -> nth j l 0 <= nth i l 0.
我做了什么? 我只是表示,对于任何大于i
j
,排名i
的值必须大于排名j
的值。 这在微妙的方式上是聪明的。 表达式实际上nth j l 0
表示排名i
的值(如果i
小于列表的长度l
否则0
。 碰巧0
比任何其他自然数都小,所以这个定义确实有效。 相反,如果您要求严格降序排列的数字列表,那么我将不得不编写一个更精确的定义,仅涉及小于列表长度的秩(您可以使用函数length
)。 我让你这样做作为一种练习。
当你写一个像这里desc
这样的逻辑谓词时,测试这个定义是很重要的,以确保你真的抓住了你心中的概念。 为了测试我自己的定义,我编写了以下代码:
Definition sample1 := 1 :: 2 :: 3 :: nil.
Definition sample2 := map (fun x => 10 - x) sample1.
Lemma s2_desc : desc sample2.
Proof.
intros [ | [ | [ | [ | ]]]] [ | [ | [ | [ | ]]]];
intros ilej; simpl; lia.
Qed.
Lemma s1_n_desc : ~desc sample1.
Proof.
intros abs; generalize (abs 0 1 (le_S _ _ (le_n _))).
compute; lia.
Qed.
s2_desc
的证明是通过蛮力证明,它实际上尝试所有小于 4 的秩对,并检查 在所有这些情况下,自然数(列表中的等级或值)之间的比较确实给出了逻辑上可证明的公式。
s1_n_desc
证明用于检查我对desc
的定义是否真的拒绝了显然不符合标准的列表。 我写了这个证明是一件好事,因为它帮助我发现了我的desc
代码中的一个错误,而这个错误没有被以前的证明捕获:我写了nth 0 l i
而不是nth i l 0
!
最后但并非最不重要的一点是,我的解决方案从Require Import List Lia.
这意味着我们使用两个现有的 Coq 模块。 第一个提供了关于列表的常用函数,第二个提供了一个自动工具来执行关于数字(实际上是自然数或整数)之间比较的简单证明。
下一步,还可以编写一个布尔函数,该函数在其输入时准确计算true
值。 降序并开发测试证明,以验证这两个函数的行为是否相应地。
你需要定义你所说的descending
是什么意思,并在你的证明中使用它。 @Yves也许有最整洁的方式。 这是另一个定义 只是写下一个简单的归纳定义。 如果尾部呈降序,并且第一个元素大于或等于第二个元素,则列表呈降序。
归纳定义的一个好处是,你可以对它们进行归纳,这在每个证明案例中都为你提供了大量信息,而工作量很小。
Require Import List.
Inductive descending : list nat -> Prop :=
desc_nil : descending nil
| desc_1 n : descending (cons n nil)
| desc_hd n m l :
m <= n ->
descending (cons m l) ->
descending (cons n (cons m l)).
Lemma head_gt l d:
descending l -> forall m, In m l -> m <= hd d l.
Proof.
induction 1; intros k H'.
now exfalso; apply in_nil in H'.
now replace k with n; [ | inversion H'].
now inversion H';
[ subst; apply le_n
| eapply PeanoNat.Nat.le_trans; auto].
Qed.