我正在浏览software foundations course,看到了以下简单代码:
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).
但是,当使用apply ev_SS.
策略证明ev 4
为真时:
Theorem ev_4 : ev 4.
Proof. (* goal: ev 4*)
apply ev_SS. (* goal changed to: ev 2, why??? *)
apply ev_SS.
apply ev_0.
Qed.
ev_SS.
的应用使我感到困惑。如果我在“推理规则”中插入数字,我会发现它在增加而不是减少:
ev 2 == ev 2 -> ev (S (S 2)).
我误会什么?
类似地,这是怎么回事:
Theorem ev_4' : ev 4.
Proof.
apply (ev_SS 2 (ev_SS 0 ev_0)).
Qed.
一般来说,有没有更好的方法来探索Coq中从一个地方到另一个地方的转变如何发生?如果可以的话,我可以更清楚地检查证明者中的情况以及原因。
答案 0 :(得分:4)
策略apply
尝试使用function / lemma / etc。证明当前的目标。在您的情况下,当前目标是ev 4
,因此要使用ev_SS
,我们需要将ev_SS
的结论与目标进行匹配。 ev_SS : forall n : nat, ev n -> ev (S (S n)).
,因此结论是ev (S (S n))
。要将其与ev 4
匹配,n
必须为2。
apply
一旦弄清了您仍然需要证明的内容,就会使这些事情成为新的目标。在这种情况下,ev_SS
以自然数n
和类型ev n
为前提。由于计算得出n
必须为2,因此将ev 2
作为目标。 apply
的下一个用法是n := 0
,因此剩下的目标是ev 0
。最后,ev_0
没有任何前提,因此使用apply ev_0
不会留下任何剩余目标。
如果这没有帮助,请考虑一下非正式证明。根据定义,零是偶数,如果n是偶数,则n + 2是偶数。我们如何证明4是偶数?好吧,甚至因为2是偶数。为什么? 2是偶数,因为0是偶数。为什么?按照定义,0甚至是偶数。
定理ev_4'
一次具有整个证明项。 apply
看到没有更多要证明的东西,因此没有新的目标。 apply的用法与策略exact
完全相同。
要了解有关战术工作原理的详细信息,建议阅读the documentation。但是,由于文档通常是技术性的,并且缺少示例,因此阅读其他人的Coq脚本并简单地进行实验很重要。
关于您的评论:
在数学中,我更习惯于从假设中得出目标,然后以这种方式得出结论。但是似乎在Coq中我们通常从目标开始,这似乎是倒退(尽管正确)。通常对于Coq来说是正确的,还是仅针对此示例?
使用set (ev_2 := ev_SS ev_0)
,然后使用exact (ev_SS ev_2)
之类的方法,可以从前提出发而不是从目标出发。这可能是一个很好的单独问题。
又为什么将ev_0:ev 0视为真实命题?是因为它是归纳定义的一部分吗?
是的。请记住,ev
被定义为
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).
因此ev_0 : ev 0
的定义。
您能否也向我解释适用的语法(ev_SS 2(ev_SS 0 ev_0))。手段?
这意味着“用参数apply
调用策略(ev_SS 2 (ev_SS 0 ev_0))
。如果您尚未意识到,Coq将使用语法f x
代替通常的{{1 }}在数学中。Coq还使用currying来表示具有多个参数的函数。我们写的是f(x)
而不是f(x, y)
,这实际上意味着f x y
,所以{ {1}}是一个以f(x)(y)
作为参数的函数,如果我们要使用更常规的语法重写该行,则它将是f(x)
。
答案 1 :(得分:0)
当您对术语进行评估时,“ n
将增加”,但是当您进行归纳证明时,您会问“我如何到达这里?”而且,如果您有证据证明ev (S (S n))
是正确的,那么您可能到达那里的唯一方式(如果您的逻辑是正确的)是ev n
也是如此。
答案 2 :(得分:0)
在阅读了tactics上更多的Coq文档之后,我认为我对Coq策略的困惑比对这个特定示例的困惑更大。从我的阅读看来,tactics implement backward reasoning.
是什么,就像文档中所说的那样。来自文档:“to prove this I have to prove this and this”. For instance, to prove A ∧ B, I have to prove A and I have to prove B.
因此,要证明ev 4
,我们需要证明ev 2
,依此类推。 Apply只是尝试将当前目标与我们提供的任何术语相匹配,并产生一定数量的子目标,我们需要证明这些目标现在可以证明或匹配。
我认为最主要的是,由于ev_SS
的定义,我们知道如果ev 2
为真,则因为我们将蕴涵定义为真ev 2 => ev 4
,所以可以得出{ {1}}。因此,我们实际上仅需要检查ev 4
是否正确。如果我们确实证明了这一点,那么根据Modus Ponens(MP),我们知道ev 2
是正确的。因此,这就是为什么向后推理“有效”的原因,因为我们将目标与某些真实的推理规则的结论相匹配,因此当我们证明前提为真时,目标就是因为推理规则)。我之所以这样说是因为从目标开始对我来说很奇怪,因为我们还不知道这是真的(还)。虽然,现在我看到我们确实通过简单地显示前提并匹配正确的推理规则来证明目标是正确的。至少对于这个例子。
我认为一般的战术都实施某种向后推理,我们需要显示子目标,不确定它是否始终是推理规则,但我认为一般的想法对我来说还是有意义的。