如何用Coq列表证明自然数的定理

时间:2018-02-08 23:25:22

标签: coq

我是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.

但我不知道如何继续这个证明。我在这个证明中坚持了一个星期。我很感谢你的帮助。

1 个答案:

答案 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.