将Z上的Coq引理移到与nat相似的引理上

时间:2016-05-18 08:05:49

标签: coq

我有Z证明的引理。所有变量都限制为大于或等于零。

问:如何尽可能轻松,尽可能地使用#34; port" nat的引理,即使用该引理通过使用nat的引理来证明Z的类似引理?

示例:

Require Import ZArith.
Open Scope Z.

Lemma Z_lemma:
  forall n n0 n1 n2 n3 n4 n5 n6 : Z,
    n >= 0 -> n0 >= 0 -> n1 >= 0 ->
    n2 >= 0 -> n3 >= 0 -> n4 >= 0 ->
    n5 >= 0 -> n6 >= 0 ->

    n5 + n4 = n6 + n3 ->
    n1 + n0 = n2 + n ->
    n5 * n1 + n6 * n2 + n3 * n0 + n * n4 =
    n5 * n2 + n1 * n6 + n3 * n + n0 * n4.
Admitted.      

Close Scope Z.

Lemma nat_lemma:
  forall n n0 n1 n2 n3 n4 n5 n6 : nat,
    n5 + n4 = n6 + n3 ->
    n1 + n0 = n2 + n ->
    n5 * n1 + n6 * n2 + n3 * n0 + n * n4 =
    n5 * n2 + n1 * n6 + n3 * n + n0 * n4.

  (* prove this using `Z_lemma` *)

1 个答案:

答案 0 :(得分:4)

你可以通过定义一种利用Z.of_nat是单射的并且分布在(+)(*)上的事实的策略来对所有具有这种形状的引理进行一般性的处理:

Ltac solve_using_Z_and lemma := 
 (* Apply Z.of_nat to both sides of the equation *)
 apply Nat2Z.inj;
 (* Push Z.of_nat through multiplications and additions *)
 repeat (rewrite Nat2Z.inj_mul || rewrite Nat2Z.inj_add);
 (* Apply the lemma passed as an argument*) 
 apply lemma;
 (* Discharge all the goals with the shape Z.of_nat m >= 0 *)
 try (apply Zle_ge, Nat2Z.is_nonneg);
 (* Push the multiplications and additions back through Z.of_nat *)
 repeat (rewrite <- Nat2Z.inj_mul || rewrite <- Nat2Z.inj_add);
 (* Peal off Z.of_nat on each side of the equation *)
 f_equal;
 (* Look up the assumption in the environment*)
 assumption.

nat_lemma的证明现在变成了:

Lemma nat_lemma:
  forall n n0 n1 n2 n3 n4 n5 n6 : nat,
    n5 + n4 = n6 + n3 ->
    n1 + n0 = n2 + n ->
    n5 * n1 + n6 * n2 + n3 * n0 + n * n4 =
    n5 * n2 + n1 * n6 + n3 * n + n0 * n4.
Proof.
intros; solve_using_Z_and Z_lemma.
Qed.