我有一个关于如何在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
。
欢迎任何关于有效改写的建议。
感谢。
答案 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.