[英]How to prove “~(nat = False)”, “~(nat = bool)” and “~(nat = True)” in coq
[英]What does `true = false` mean in Coq?
[我不確定這是否適合堆棧溢出,但這里還有許多其他 Coq 問題,所以也許有人可以提供幫助。]
我正在通過http://www.cis.upenn.edu/~bcpierce/sf/Basics.html#lab28 (就在 Case 介紹的下方)中完成以下工作。 請注意,我在這方面是一個完整的初學者,並且正在家里工作 - 我不是學生。
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.
我正在研究重寫的作用:
Case := "b = false" : String.string
c : bool
H : andb false c = true
============================
false = true
然后rewrite <- H.
被應用:
Case := "b = false" : String.string
c : bool
H : andb false c = true
============================
false = andb false c
很明顯證明將如何成功。
我可以看到如何以機械方式操縱符號來獲得證明。 沒關系。 但我對“意義”感到不安。 特別是,我怎么能在證明中間有false = true
?
似乎我正在提出某種矛盾的論點,但我不確定是什么。 我覺得我一直在盲目地遵守規則,不知何故到了我打字胡說八道的地步。
我在上面做什么?
我希望這個問題很清楚。
通常,當您在定理證明器中進行案例分析時,很多案例歸結為“不可能發生”。 例如,如果您要證明有關整數的一些事實,您可能需要對整數i
是正數、零還是負數進行案例分析。 但是,在您的上下文中,或者您的目標的某些部分,可能還有其他假設與其中一種情況相矛盾。 例如,您可能從之前的斷言中知道, i
永遠不會是否定的。
然而,Coq 並不那么聰明。 因此,您仍然必須通過實際證明這兩個相互矛盾的假設可以粘合在一起成為荒謬證明,從而證明您的定理的機制。
把它想象成一個計算機程序:
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
andb H: andb false c = true
。 稍加思考就會告訴你,這實際上是一個荒謬的假設(因為對於任何y
, andb false y
減少為 false,因此不可能為真)。 所以你用唯一可以使用的東西(即H
) false = andb false c
目標,你的新目標是false = andb false c
。
所以你應用一個荒謬的假設來試圖實現一個荒謬的目標。 瞧,你最終得到了一些你可以通過反身性來展示的東西。 Qed。
更新正式,這是發生了什么。
回想一下 Coq 中的每個歸納定義都帶有一個歸納原則。 以下是等式和False
命題的歸納原則的類型(與bool
類型的術語false
相對):
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
。 它說:
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
我們想要一個特別討厭的。
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
。 所以讓我們這樣做。
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
證明轉換為您想要的任何證明。 所以特別是H
是false = true
的證明,所以你現在可以證明你想要的任何目標。
策略基本上是構建證明項的機器。
true = false
是一個等於兩個不同布爾值的語句。 由於這些值不同,此陳述顯然無法證明(在空上下文中)。
考慮你的證明:你到達了目標為false = true
的階段,很明顯你無法證明它......但問題是你的上下文(假設)也是矛盾的。 例如,當您進行案例分析並且其中一個案例與您的其他假設相矛盾時,經常會發生這種情況。
我意識到這很舊,但我想澄清 Lambdageek 答案背后的一些直覺(以防有人發現這一點)
我注意到關鍵點似乎是我們定義了一個函數F:bool->Prop
在每個點都有不同的值(即true => True
和false => False
)。 然而,可以很容易地從等式的歸納原理eq_ind
直觀的想法(這實際上是定義等式的“萊布尼茨”方式)表明
forall P:bool -> Prop, forall x,y:bool, (x = y) -> (P x) -> (P y),
但這意味着從true=false
和I:True
,我們可以得出結論False
。
我們在這里使用的另一個基本屬性是定義F
的能力,它由 bool 的遞歸原則bool_rect
:
forall P:bool -> Type, P true -> P false -> (forall b:bool, P b)
通過選擇P := (fun b:bool => Prop)
,我們得到
(bool_rect P) : Prop -> Prop -> (bool -> Prop),
我們輸入True
和False
來得到我們的函數F
。
如果我們把這一切放在一起,我們會得到
(eq_ind true (bool_rect (fun b => Prop) True False) I false) : true = false -> False
還值得指出的是,Coq 將eq_ind
或bool_rect
等歸納/遞歸原則作為定義身份和布爾類型的公理。
證明這一點的正常人類方法是說,由於在這種情況下假設不匹配,因此我們不需要證明續集。 在 Coq 中,有一種表達方式。 這是通過一種名為inversion
的策略。
下面是一個例子:
Theorem absurd_implies_absurd :
true = false -> 1 = 2.
Proof.
intros H.
inversion H.
Qed.
第一步讓H
成為假設true = false
,因此要證明的目標是1 = 2
。
inversion H
步將自動證明目標! 正是我們想要的,魔法!
為了理解這種魔法,我們轉向了inversion
意味着什么的文檔。
對於初學者(像我一樣),反演的官方文檔簡潔而晦澀難懂,這里有一個更好的解釋。 在頁面上搜索關鍵詞倒置,你會發現這個:
如果c
和d
是不同的構造函數,則假設H
是矛盾的。 也就是說,錯誤的假設已經進入上下文,這意味着任何目標都是可證明的! 在這種情況下,反轉 H 將當前目標標記為已完成並將其從目標堆棧中彈出。
這正是我們想要的。 唯一的問題是這超出了本書的計划。 當然,將true
重寫為false
會起作用。 問題不在於它不起作用,問題在於它不是我們想要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.