如何使用plus communtativity和associativity重新排列Coq中的术语?

时间:2015-10-07 01:51:18

标签: coq coq-tactic

我有一个关于如何在Coq中重新排列术语的一般性问题。例如,如果我们有一个术语m + p + n + p,人类可以快速将术语重新排列为m + n + p + p(隐式使用plus_comm和plus_assoc)。我们如何在Coq中有效地做到这一点?

对于(愚蠢的)例子,

Require Import Coq.Arith.Plus.
Require Import Coq.Setoids.Setoid.

Theorem plus_comm_test: forall n m p: nat,
  m + p + (n + p) = m + n + 2 * p.
Proof. intros. rewrite plus_assoc. simpl. rewrite <- plus_n_O.

现在,我们有

1 subgoals
...
______________________________________(1/1)
m + p + n + p = m + n + (p + p)

我的问题是:

如何有效地将LHS重写为m + n + p + p

我尝试使用rewrite plus_comm at 2,但错误Nothing to rewrite.只需使用重写plus_comm即可将LHS更改为p + m + n + p

欢迎任何关于有效改写的建议。

感谢。

3 个答案:

答案 0 :(得分:2)

在这种特殊情况下(整数上的线性算术),你可以使用omega策略:

Require Import Omega.

Theorem plus_comm_test: forall n m p: nat,
  m + p + (n + p) = m + n + 2 * p.
Proof. intros; omega. Qed.

但是,有些情况omega还不够。在这些情况下,标准rewrite策略不是很方便。 Ssreflect库附带了自己的rewrite策略版本,可以更好地完成诸如重写目标子条款等任务。例如:

Require Import Ssreflect.ssreflect Ssreflect.ssrfun Ssreflect.ssrbool.
Require Import Ssreflect.ssrnat.

Theorem plus_comm_test: forall n m p: nat,
  m + p + (n + p) = m + n + 2 * p.
Proof.
move=> n m p.
by rewrite -addnA [p + _]addnC -[_ + p]addnA addnn -mul2n addnA.
Qed.

方括号中的注释(例如[p + _])提供了帮助rewrite策略找出行动方式的模式。 addn*引理和朋友是Ssreflect自己的标准算术结果版本,而不是自然数。

答案 1 :(得分:1)

正如亚瑟所说,有时omega是不够的,但我有时会将它用于这样的简单步骤。

Require Import Omega.
Theorem test: forall a b c:nat, a + b + 2 * c = c + b + a + c.
  intros.
  replace (c + b + a) with (a + b + c) by omega.
  replace (a + b + c + c) with (a + b + (c + c)) by omega.
  replace (c + c) with (2 * c) by omega.
  reflexivity.
Qed.

这是一个愚蠢的例子,因为omega可以一次解决所有这些问题,但有时候你想在没有一点帮助的情况下重写omega无法达到的函数内部的东西。

答案 2 :(得分:0)

ring策略能够证明这些重排是相同的。

使用您的示例:

Require Import ZArith.
Open Scope Z_scope.

(* Both "ring" and "omega" can prove this. *)
Theorem plus_comm_test : forall n m p : Z,
  m + p + (n + p) = m + n + 2 * p.
Proof.
  intros.
  ring.
Qed.

ring适用于整数,但我认为它不适用于自然数。

但是,ring能够证明omega无法证明的某些身份。 (docs说:“乘法是由omega处理的,但是只有两个乘数的乘积中至少一个是常数的目标才是可解决的。这是“ Presburger算术”的限制。)

例如:

(* "ring" can prove this but "omega" cannot. *)
Theorem rearrange_test : forall a b c : Z,
  a * (b + c) = c*a + b*a.
Proof.
  intros.
  ring.
Qed.