案例 vs case_tac/induct vs induct_tac

cases vs case_tac/induct vs induct_tac

我已经使用 Isabelle/HOL 几个月了,但我一直无法弄清楚使用 _tac 的确切意图。

具体来说,我说的是 cases vs case_tacinduct vs indut_tac(虽然如果知道 tac 的一般含义会很好,因为我也在使用其他方法比如cut_tac).

我注意到我不能将 casesinduct 与 apply 和 ⋀-绑定变量一起使用,但我可以,如果它是结构化证明为什么?

这方面的一个例子:

    lemma "¬(∀x. ¬(P x)) ⟹ ∃x. P x"
  apply (rule ccontr)
  apply (erule notE)
  apply (rule allI)
  apply (case_tac "P x")
  apply (erule notE)
  apply (erule exI)
  apply assumption
  done

另一方面,我注意到 inductinduct_tac 之间的另一个区别是我可以使用 double归纳后者,而不是前者。再一次,我不知道为什么。

提前致谢。

*_tacapply 脚本中使用的内置策略。特别是case_tacinduct_tac已经基本被Isabelle/Isar中的casesinduction证明方法所取代。正如您所提到的,case_tacinduct_tac 可以处理⋀-绑定变量。然而,这很脆弱,因为它们的名字通常是自动生成的,并且可能会随着 Isabelle 的改变而改变(当然,您可以使用 rename_tac 选择固定名称)。这就是当今结构化证明方法优于非结构化策略脚本的原因之一。现在,回到你的例子:为了能够使用cases,你可以引入一个结构化块,如下所示:

lemma "¬(∀x. ¬(P x)) ⟹ ∃x. P x"
  apply (rule ccontr)
  apply (erule notE)
  proof (intro allI)
    fix x
    assume "∄x. P x"
    then show "¬ P x"
      apply (cases "P x")
      apply (erule notE)
      apply (erule exI)
      apply assumption
      done
  qed

如您所见,结构化证明通常比较冗长,但比线性 apply-脚本更具可读性。

如果您仍然对“双重归纳”问题感到好奇,非常欢迎举个例子。最后,如果你想了解更多关于使用 Isabelle/Isar 语言环境的结构化证明,我强烈建议你阅读 this tutorial on Isabelle/HOL and The Isabelle/Isar Reference Manual 以获得更详细的信息。