如何使用加公共性和结合性重新排列Coq中的术语?

如何使用加公共性和结合性重新排列Coq中的术语?,coq,coq-tactic,Coq,Coq Tactic,我有一个关于如何在Coq中重新排列术语的一般性问题。例如,如果我们有一个术语m+p+n+p,人类可以快速地将这些术语重新排列为类似m+n+p+p(隐式使用plus\u comm和plus\u assoc)。我们如何在Coq中有效地做到这一点 举个(愚蠢的)例子 Require Import Coq.Arith.Plus. Require Import Coq.Setoids.Setoid. Theorem plus_comm_test: forall n m p: nat, m + p +

我有一个关于如何在Coq中重新排列术语的一般性问题。例如,如果我们有一个术语
m+p+n+p
,人类可以快速地将这些术语重新排列为类似
m+n+p+p
(隐式使用plus\u comm和plus\u 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.
我的问题是:

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

我尝试在2处使用
rewrite plus\u comm
,但它给出了一个错误
无需重写。
只需使用rewrite
plus\u comm
即可将LHS更改为
p+m+n+p

任何关于有效重写的建议都是欢迎的

谢谢。

在这种特殊情况下(整数上的线性算术),您可以使用
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
策略,对于任务(如根据目标的子项进行重写)效果更好。例如:

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+\uz]
,提供了帮助
重写策略确定行动方向的模式。
addn*
引理和朋友是Ssreflect对自然数的标准算术结果的自己版本。

正如Arthur所说,有时ω是不够的,但我有时会将其用于像这样的简单步骤

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
如果没有一点帮助就无法触及这些内容…

策略能够证明这些重新排列是平等的

以您的例子:

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" 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.
ring
对整数有效,但我认为对自然数无效

然而,
ring
能够证明一些
omega
无法证明的恒等式。(比如,“乘法由ω处理,但只有乘积的两个被乘数中至少有一个是常数的目标才可解。这就是“Presburger算术”的限制。)

例如:

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" 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.

谢谢你的回答。但我所展示的是关于
nat
的更大证明的一部分。
m+p+n+p
部分包含在其他内容中。同时,我也在努力学习Coq是如何工作的。你知道一种更原始的Coq方法来做这件事而不涉及外部库吗?我希望我知道。。。我个人永远也不知道如何在标准Coq中学习
rewrite
的所有功能的语法。我相信当使用
Setoid
库时,可能会有一个错误导致选择发生错误,但我不确定。在任何情况下,您都可以显式地向引理提供参数,这有助于避免在某些情况下出现歧义,例如,
rewrite您还可以使用
assert
分别使用
omega
来证明您想要的等式,然后直接用它重写。我似乎记得setoid_rewrite会以我想要的方式执行比rewrite更多的操作,特别是当使用
at
重写第n次出现时。这绝对是一种痛苦。