关于逻辑:Coq中的true = false是什么意思?

What does `true = false` mean in Coq?

[我不确定这是否适合堆栈溢出,但是这里还有许多其他Coq问题,也许有人可以提供帮助。]

我正在通过http://www.cis.upenn.edu/~bcpierce/sf/Basics.html#lab28(下面介绍Case的地方)进行以下操作。请注意,我是一个完全的初学者,并且正在家里工作-我不是学生。

1
2
3
4
5
6
7
8
9
10
Theorem andb_true_elim1 : forall b c : bool,
  andb b c = true -> b = true.
Proof.
  intros b c H.
  destruct b.
  Case"b = true".
    reflexivity.
  Case"b = false".
    rewrite <- H. reflexivity.
Qed.

我正在查看重写的作用:

1
2
3
4
5
  Case :="b = false" : String.string
  c : bool
  H : andb false c = true
  ============================
   false = true

然后应用rewrite <- H.

1
2
3
4
5
  Case :="b = false" : String.string
  c : bool
  H : andb false c = true
  ============================
   false = andb false c

很明显,证明将如何成功。

我可以看到如何以机械方式操纵符号来获得证明。没关系。但是我对"含义"感到不安。特别是,如何在证明中间包含false = true

似乎我在提出一些有矛盾的论点,但我不确定是什么。我觉得我一直在盲目遵循规则,并以某种方式到达了我胡说八道的地步。

我在上面做什么?

我希望问题清楚。


通常,当您在一个定理证明者中进行案例分析时,很多案例会归结为"无法发生"。例如,如果要证明有关整数的某些事实,则可能需要对整数i是正数,零数还是负数进行案例分析。但是,在您的情况下或目标的某些部分可能还存在其他假设,这些假设与其中一种情况是矛盾的。例如,您可能从先前的断言中知道i永远不能为负。

但是Coq并不那么聪明。因此,您仍然必须仔细研究一下这样的机制,即可以将两个矛盾的假设粘合在一起,成为荒谬的证明,从而证明您的定理。

像在计算机程序中那样思考:

1
2
3
4
5
6
7
8
9
10
switch (k) {
  case X:
    /* do stuff */
    break;
  case Y:
    /* do other stuff */
    break;
  default:
    assert(false,"can't ever happen");
}

false = true目标是"不可能发生"。但是,您不能只是在Coq中断言自己的出路。实际上,您必须放下证明条款。

因此,您必须证明荒谬的目标false = true。唯一要做的就是假设H: andb false c = true。片刻的想法就会告诉您,这实际上是一个荒谬的假设(因为对于任何yandb false y都简化为false,因此不可能为真)。因此,只有您可以使用的唯一目标(即H)实现目标,而新目标是false = andb false c

因此您运用了一个荒谬的假设,试图实现一个荒谬的目标。看得出您最终会得到一些可以通过反射实际显示的东西。 Qed。

更新正式地,这是发生了什么。

回想一下,Coq中的每个归纳定义都带有归纳原理。以下是等式和False命题的归纳原理的类型(与类型为bool的术语False相对):

1
2
3
4
5
6
7
Check eq_ind.
eq_ind
  : forall (A : Type) (x : A) (P : A -> Prop),
    P x -> forall y : A, x = y -> P y
Check False_ind.
False_ind
 : forall P : Prop, False -> P

False的归纳原理说,如果您给我False的证明,我可以给您证明任何命题P

eq的归纳原理更加复杂。让我们考虑它仅限于bool。特别是False。它说:

1
2
3
Check eq_ind false.
eq_ind false
 : forall P : bool -> Prop, P false -> forall y : bool, false = y -> P y

因此,如果您从某个依赖于布尔b的命题P(b)开始,并且有一个P(false)的证明,那么对于等于False的任何其他布尔y P(y)

的证明

这听起来并不很有趣,但是我们可以将其应用于我们想要的任何命题P。我们想要一个特别讨厌的人。

1
2
3
4
5
Check eq_ind false (fun b : bool => if b then False else True).
eq_ind false (fun b : bool => if b then False else True)
 : (fun b : bool => if b then False else True) false ->
   forall y : bool,
   false = y -> (fun b : bool => if b then False else True) y

简化一下,这就是True -> forall y : bool, false = y -> (if y then False else True)

所以这想要一个True的证明,然后是我们可以选择的一些布尔y。因此,让我们这样做。

1
2
3
Check eq_ind false (fun b : bool => if b then False else True) I true.
eq_ind false (fun b : bool => if b then False else True) I true
 : false = true -> (fun b : bool => if b then False else True) true

这里是:false = true -> False

结合我们对False的归纳原理的了解,我们得到:如果您给我一个false = true的证明,则我可以证明任何命题。

回到andb_true_elim1。我们有一个假设H,它是false = true。我们想证明某种目标。如上所示,存在一个证明术语,可以将false = true的证明转化为您想要的任何东西的证明。因此,特别是Hfalse = true的证明,因此您现在可以证明您想要的任何目标。

战术基本上是建立证明条件的机制。


true = false是一条语句,它等同于两个不同的布尔值。由于这些值不同,因此该语句显然是不可证明的(在空上下文中)。

考虑您的证明:您到达了目标为false = true的阶段,因此显然您无法证明这一点……但事实是,您的背景(假设)也矛盾。例如,当您进行案例分析并且其中一个案例与您的其他假设相矛盾时,通常会发生这种情况。


我意识到这很老了,但我想澄清一下Lambdageek回答背后的一些直觉(以防万一有人发现了这个问题)

我注意到关键点似乎是我们定义了一个在每个点上具有不同值的函数F:bool->Prop(即true => Truefalse => False)。但是,从等式eq_ind的归纳原理可以很容易地看出

的直观思想(实际上,这是定义等式的" Leibniz"方式)

1
forall P:bool -> Prop, forall x,y:bool, (x = y) -> (P x) -> (P y),

但这意味着从true=falseI:True可以得出False

我们在这里使用的另一个基本属性是定义F的能力,该能力由bool的递归原理bool_rect

给出

1
forall P:bool -> Type, P true -> P false -> (forall b:bool, P b)

通过选择P := (fun b:bool => Prop),我们得到

1
(bool_rect P) : Prop -> Prop -> (bool -> Prop),

我们在其中输入TrueFalse以获得函数F

如果将所有这些放在一起,我们将得到

1
(eq_ind true (bool_rect (fun b => Prop) True False) I false) : true = false -> False

还值得指出的是,Coq将归纳/递归原理(如eq_indbool_rect)用作定义身份和布尔类型的公理。