Coq中的证明自动化如何分解证明 我在跟随软件基金会,我在一章名为“IMP”。

Coq中的证明自动化如何分解证明 我在跟随软件基金会,我在一章名为“IMP”。,coq,proof,Coq,Proof,作者公开了一种小型语言,如下所示: Inductive aexp : Type := | ANum : nat -> aexp | APlus : aexp -> aexp -> aexp | AMinus : aexp -> aexp -> aexp | AMult : aexp -> aexp -> aexp. 下面是计算这些表达式的函数: Fixpoint aeval (a : aexp) : nat := match a w

作者公开了一种小型语言,如下所示:

Inductive aexp : Type :=
  | ANum : nat -> aexp
  | APlus : aexp -> aexp -> aexp
  | AMinus : aexp -> aexp -> aexp
  | AMult : aexp -> aexp -> aexp.
下面是计算这些表达式的函数:

Fixpoint aeval (a : aexp) : nat :=
  match a with
  | ANum n ⇒ n
  | APlus a1 a2 ⇒ (aeval a1) + (aeval a2)
  | AMinus a1 a2 ⇒ (aeval a1) - (aeval a2)
  | AMult a1 a2 ⇒ (aeval a1) × (aeval a2)
  end.
本练习旨在创建一个优化评估的函数。例如:

APlus a (ANum 0) --> a
这是我的优化功能:

Fixpoint optimizer_a (a:aexp) :aexp :=
  match a with
    | ANum n => ANum n
    | APlus (ANum 0) e2 => optimizer_a e2
    | APlus e1 (ANum 0) => optimizer_a e1
    | APlus e1 e2 => APlus (optimizer_a e1) (optimizer_a e2)
    | AMinus e1 (ANum 0) => optimizer_a e1
    | AMinus e1 e2 => AMinus (optimizer_a e1) (optimizer_a e2)
    | AMult (ANum 1) e2 => optimizer_a e2
    | AMult e1 (ANum 1) => optimizer_a e1
    | AMult e1 e2 => AMult (optimizer_a e1) (optimizer_a e2)
  end. 
现在,我要证明优化函数是正确的:

Theorem optimizer_a_sound : forall a, aeval (optimizer_a a) = aeval a.
这个证明很难。所以我试着用一些引理来分解证明

这里有一个引理:

Lemma optimizer_a_plus_sound : forall a b, aeval (optimizer_a (APlus a b)) = aeval (APlus (optimizer_a a) (optimizer_a b)).
我有证据,但很无聊。我在a上做一个归纳,然后,对于每种情况,我都会解构b,并解构exp来处理b为0的情况

我需要这样做是因为

n+0 = n
不会自动减少,我们需要一个加0的定理

现在,我想知道,我怎样才能用Coq建立一个更好的证明,以避免在证明过程中出现一些无聊的重复

这是我对这个引理的证明:

我想我应该使用“提示重写加上”但我不知道如何使用


顺便说一下,我还想知道一些技巧来展示初始定理(我的优化函数的奥秘)。

< P>当你在数据结构上使用归纳法,需要考虑案例时,这里有一种方法可以用来考虑变量<代码> x <代码>的情况,摆脱不可能的情况,解决一些琐碎的问题

destruct X; try congruence; auto.
在你的例子中,我们可以用它来证明关于
优化\u a
函数的有用的重写引理

Lemma opt1: forall a b, a = ANum 0 -> optimizer_a (APlus a b) = optimizer_a b.
  intros.
  destruct a; try congruence; auto;
  destruct n; try congruence; auto.
Qed.

Lemma opt2: forall a b, b = ANum 0 -> optimizer_a (APlus a b) = optimizer_a a.
  intros;
  destruct a; try congruence; auto;
  destruct b; try congruence; auto;
  destruct n; try congruence; auto;
  destruct n0; try congruence; auto.
Qed.

Lemma opt3:
  forall a b,
    a <> ANum 0 -> b <> ANum 0 ->
    optimizer_a (APlus a b) = APlus (optimizer_a a) (optimizer_a b).
Proof.
  intros.
  destruct a; try congruence; auto;
  destruct b; try congruence; auto;
  destruct n; try congruence; auto;
  destruct n0; try congruence; auto.
Qed.
我们可以解构
ANum0_dec a
并在上下文中获取
a=ANum 0
,或者在上下文中获取
ANum 0

Require Import Arith. (* for "auto with arith" to handle n = n + 0 *)

Lemma optimizer_a_plus_sound :
  forall a b,
    aeval (optimizer_a (APlus a b)) = aeval (APlus (optimizer_a a) (optimizer_a b)).
Proof.
  intros a b.
  destruct (ANum0_dec a);  destruct (ANum0_dec b).
  - rewrite opt1; subst; auto.
  - rewrite opt1; subst; auto.
  - rewrite opt2; subst; simpl; auto with arith.
  - rewrite opt3; subst; auto.
Qed.

如果你使用上面的技巧,你可以定义你自己的战术,所以你不必输入太多。因为证明很短,你可以不用引理。(我为自毁同余自动调用了战术
dca

较短的证明不是可读的,但它本质上是:考虑变量的情况。

Lemma ANum0_dec: forall a, {a = ANum 0} + { a <> ANum 0}.
  destruct a; try destruct n; try (right; discriminate); left; auto.
Qed.

Require Import Arith.

Ltac dca v := destruct v; try congruence; auto.

Lemma optimizer_a_plus_sound :
  forall a b,
    aeval (optimizer_a (APlus a b)) = aeval (APlus (optimizer_a a) (optimizer_a b)).
Proof.
  intros a b;
  destruct (ANum0_dec a), (ANum0_dec b).
  - dca a; dca n.
  - dca a; dca n0.
  - dca b; dca n0; dca a; simpl; auto with arith; dca n0.
  - dca a; dca b; dca n1; dca n2.
Qed.

你也可以用这种简洁的形式做完整的证明。

|APlus e1 e2=>APlus(optimizer_a e1)(optimizer_a e2)
中,如果
optimizer_a e1
返回
ANum 0怎么办?
Lemma ANum0_dec: forall a, {a = ANum 0} + { a <> ANum 0}.
  destruct a; try destruct n; try (right; discriminate); left; auto.
Qed.

Require Import Arith.

Ltac dca v := destruct v; try congruence; auto.

Lemma optimizer_a_plus_sound :
  forall a b,
    aeval (optimizer_a (APlus a b)) = aeval (APlus (optimizer_a a) (optimizer_a b)).
Proof.
  intros a b;
  destruct (ANum0_dec a), (ANum0_dec b).
  - dca a; dca n.
  - dca a; dca n0.
  - dca b; dca n0; dca a; simpl; auto with arith; dca n0.
  - dca a; dca b; dca n1; dca n2.
Qed.
Theorem optimizer_a_sound : forall a, aeval (optimizer_a a) = aeval a.

  induction a.
  * auto.
  * rewrite optimizer_a_plus_sound; simpl; auto.
  *     (* ... and so on for Minus and Mult *)