Coq “匹配”能比“重写”快吗`
在Coq中编写Coq “匹配”能比“重写”快吗`,coq,coq-tactic,Coq,Coq Tactic,在Coq中编写Ltac时,可能会尝试编写 try match goal with |- context [?x && true] => rewrite andb_true_r end 而不是 try rewrite andb_true_r 不要毫无意义地调用rewrite——这是一个更大策略的内部循环,我们预计在大多数情况下,重写都会失败 但这真的更快吗?或者重写失败的速度和我写的手写的匹配一样快吗?是的!在我的一个战术中,我实现了60%的加速 下面是显示这种行为的另
Ltac
时,可能会尝试编写
try match goal with
|- context [?x && true] => rewrite andb_true_r
end
而不是
try rewrite andb_true_r
不要毫无意义地调用rewrite
——这是一个更大策略的内部循环,我们预计在大多数情况下,重写都会失败
但这真的更快吗?或者
重写
失败的速度和我写的手写的匹配
一样快吗?是的!在我的一个战术中,我实现了60%的加速
下面是显示这种行为的另一个微观基准:
Require Import Coq.Bool.Bool.
Goal forall b, b = true.
intros.
(* Lets create a large goal *)
do 300 rewrite <- orb_false_r with (b := b).
Time do 300 try rewrite orb_true_r.
(* Finished transaction in 2.57 secs (2.431u,0.003s) (successful) *)
Time do 300 try lazymatch goal with |- context [_ || true] => rewrite orb_true_r end.
(* Finished transaction in 0.05 secs (0.05u,0.s) (successful) *)
Abort.
需要导入Coq.Bool.Bool。
全部b的目标,b=正确。
介绍。
(*让我们创建一个大目标*)
300重写重写orb\u true\u r结束。
(*在0.05秒(0.05 U,0.s)内完成交易(成功)*)
中止
基于您的自我回答,Coq对所使用的精确匹配策略非常敏感。注意以下策略之间的差异:
Require Import Coq.Bool.Bool.
Goal forall b, b = true.
intros.
(* Create a large goal *)
do 300 rewrite <- orb_false_r with (b := b).
Time do 300 try idtac.
(* Finished transaction in 0.001 secs (0.004u,0.s) (successful) *)
Time do 300 try match goal with |- context [_ || true] => idtac end.
(* Finished transaction in 0.108 secs (0.108u,0.s) (successful) *)
Time do 300 try match goal with |- context [_ || ?b] => constr_eq b true end.
(* Finished transaction in 3.21 secs (3.208u,0.s) (successful) *)
Time do 300 try rewrite orb_true_r.
(* Finished transaction in 2.862 secs (2.863u,0.s) (successful) *)
加速在
setoid_rewrite
中更为明显,在许多情况下,重写模会展开,因此可以不必要地减少目标,一次又一次失败。基准测试说明了什么?与rewrite?和b_true_r.
相比,你的意思是什么,但不知何故,整个证明都失败了……你可能想尝试重写1?和b_true_r.
,因为重写?和b_true_r.
重写次数尽可能多,可能根本不重写,也就是说,它不会失败。我知道,但我怀疑这会影响重写
失败的时间。我将澄清这个问题。rewrite
和match
有许多不同的折衷办法,因此根据具体情况,它们可以慢一些,也可以快一些。您是否正在使用香草重写?它的速度很慢,您可能想看看ssreflect版本中的匹配如何影响基准测试。在您的示例中,ssr的重写速度大约慢两倍。请注意,该策略称为setoid\u rewrite
,不是rewrite\u setoid
。可能值得注意的是rewrite
不调用setoid\u rewrite
(通常在rewrite
单独失败时成功)setoid_rewrite
在许多情况下也比rewrite
昂贵得多,因此通常值得避免。文档中说:“此外,所有相应的不固定策略(即自反性、对称性、传递性、替换、重写)当所涉及的关系不是莱布尼茨等式时,它们会退回到前缀对应项。”因此,在某些情况下,它们会退回到setoid_rewrite
,但您是对的:在这种情况下不是,因为等式是eq
Goal forall b, b || (fun x => x) true = true.
intros.
Fail match goal with |- context [_ || true] => rewrite orb_true_r end.
rewrite orb_true_r. (* succeeds *)