coq - Coq 分支和回溯的多次成功?

我无法理解 Coq (8.5p1, ch9.2) 分支和回溯行为中的多次成功 的概念。例如,来自文档:

Backtracking branching

We can branch with the following structure:

expr1 + expr2

Tactics can be seen as having several successes. When a tactic fails it asks for more successes of the prior tactics. expr1 + expr2 has all the successes of v1 followed by all the successes of v2.

我不明白的是,为什么我们首先需要多次成功?一次成功还不足以完成证明吗?

另外从文档来看,似乎有一些成本较低的分支规则在某种程度上是“有偏见的”,包括

first [ expr1 | ::: | exprn ]

expr1 || expr2

为什么我们需要成本更高的选项 + 而不是总是使用后者更有效的战术?

最佳答案

问题在于,您有时会尝试实现一个目标,但进一步的子目标可能会导致您认为可行的解决方案被拒绝。如果您积累了所有的成功,那么您可以回溯到您做出错误选择的地方,并探索搜索树的另一个分支。

这是一个愚蠢的例子。假设我想证明这个目标:

Goal exists m, m = 1.

现在,这是一个相当简单的目标,所以我可以手动完成,但我们不要这样做。让我们编写一个策略,当遇到 exists 时,尝试所有可能的自然数。如果我写:

Ltac existNatFrom n :=
  exists n || existNatFrom (S n).

Ltac existNat := existNatFrom O.

然后,一旦我运行了 existNat,系统就会提交第一个成功的选择。特别是这意味着尽管 existNatFrom 的递归定义,当调用 existNat 时,我总是会得到 O 并且只有 O.

目标无法解决:

Goal exists m, m = 1.
  Fail (existNat; reflexivity).
Abort.

另一方面,如果我使用 (+) 而不是 (||),我将遍历所有可能的自然数(以惰性方式,通过使用回溯)。所以写:

Ltac existNatFrom' n :=
  exists n + existNatFrom' (S n).

Ltac existNat' := existNatFrom' O.

意味着我现在可以证明目标:

Goal exists m, m = 1.
  existNat'; reflexivity.
Qed.

https://stackoverflow.com/questions/38256705/

相关文章:

java - 在NIFI中创建自定义 Controller 服务时无法生成扩展的文档

intellij-idea - IdeaVim:如何在不使用箭头键的情况下循环浏览列表项?

java - 检查字符串中是否存在模式

django - 模型中的用户 OneToOneField

firebase - iOS 离线时的 FCM 行为

java - 为什么 Double::compareTo 可以作为 Stream.max(Compa

r - 如何原型(prototype)(启动)从其他插槽派生的 S4 插槽?

java - 如何将充满 if 语句的 for 循环更改为更优雅/高效的代码?

angularjs - 为什么模块 'ui.bootstrap' 不可用?

r - 从列值比较中确定 R 数据框行值