我是Coq的新人。为了对列表和对列表进行练习,我使用Coq列表库来证明自然数的简单定理。我试图证明自然数的简单属性:
forall n, multiplier, a0....an, d1...dn:
((a0*multiplier)=d1)+((a1*multiplier)=d2)+((a2*multiplier)=d3)+...+((an*multiplier)=dn) = result
-> (a0+a1+a2+...+an) * multiplier = d1+d2+...+dn = result
((3 * 2)= 6)+((5 * 2)= 10)+((9 * 2)= 18)= 34 - > (3 + 5 + 9)* 2 = 6 + 10 + 18 = 34可以作为这种性质的一个例子(即n = 3和乘数= 2)。
我使用对列表(在一个列表中存储&,并在另一个列表中存储d)以在Coq中对此属性进行编码:
Require Import List.
Fixpoint addnumbers (L : list nat) : nat :=
match L with
| nil => 0
| H::tail => H + addnumbers tail
end.
Theorem resultAreEqual : forall (natListofpair :list (nat * nat))
(multiplier : nat) (result : nat),
Forall (fun '(a,d) => a * multiplier = d ) natListofpair ->
addnumbers(List.map (@fst nat nat) natListofpair) * multiplier = result ->
addnumbers (List.map (@snd nat nat) natListofpair) = result.
Proof.
intros.
destruct natListofpair.
subst. simpl. reflexivity.
rewrite <- H0.
inversion H.
destruct p. simpl.
但我不知道如何继续这个证明。我在这个证明中坚持了一个星期。我很感谢你的帮助。
答案 0 :(得分:4)
你遇到困难的一个原因是你以间接方式陈述了你的引理。在Coq中证明某些内容时,尽可能简单地说明它是非常重要的,因为这通常会导致更容易的证明。在这种情况下,通过在列表上使用高阶函数,语句可以变得更加简单。
Require Import Coq.Arith.PeanoNat.
Require Import Coq.Lists.List.
Definition sum (l : list nat) := fold_right Nat.add 0 l.
Lemma my_lemma l m : sum (map (Nat.mul m) l) = m * sum l.
sum
功能相当于您的addnumbers
。引理说&#34;将l
中的所有数字乘以m
并添加它们的结果与先添加它们并稍后乘以m
&#34的结果相同;
为了证明这一结果,我们需要一个关键因素,证明你的证据缺失:归纳。当我们想要推理无限大小的对象(例如列表)时,Coq中经常需要这样做。这是一个可能的证据。
Proof.
unfold sum.
induction l as [|x l IH]; simpl.
- (* Nil case *)
now rewrite Nat.mul_0_r.
- (* Cons case *)
now rewrite IH, Nat.mul_add_distr_l.
Qed.