如何使用加公共性和结合性重新排列Coq中的术语?
我有一个关于如何在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 +
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
,但它给出了一个错误无需重写。
只需使用rewriteplus\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次出现时。这绝对是一种痛苦。