看過離散數學上的證明。
也在知乎上搜過。
還有劉未鵬關於停機問題的那篇的部落格
基本都是文字加**論述,但我始終有幾個問題沒太想明白,感覺證明得牽強,於是自己理解了一下,記於此處,希望能有人來討論、指點。
一般都是這麼證明的(此處我用c++**):
假設存在這麼乙個演算法可以判斷出別的程式是否可以停機。
1bool halting_judge (program a, char*input)
2
因為一般的程式都是要有輸入輸出的,這裡的input就是程式a的輸入。使用char形式是因為後面證明時需要把程式**作為輸入,而程式**是字串,這裡就直接規定好了。
然而圖靈大佬想說具有這種能力的程式是不存在的。於是我們創造下面這個函式:
1bool hack (program a, char*input)28
else
9return
true
;10 }
這個函式的作用是:如果程式a可以停機,則接下來進行無限迴圈讓hack函式無法停機;如果程式a無法停機,則return使hack函式可以停機。
接下來用hack程式代入a,用hack的**代入input:
bool hack (program a, char*input)else
return
true
;}
於是人們說:如果halting_judge判斷hack為停機,則hack(hack)就無限迴圈,不停機;如果halting_judge判斷hack為無法停機,則hack(hack)會返回,為停機。so,hack到底是不是停機的呢?矛盾了,所以halting_judge無法判斷。
可能是我理解錯什麼了吧?個人認為這樣的證明未免有些模糊。
首先想到,所謂hack(hack),括號裡的hack應該指的是程式吧?那作為程式它的兩個引數是什麼呢?難道什麼引數都行?這裡不解釋一下嗎?
然後看一看halting_judge的定義,想一下上面的問題,則發現括號裡的hack它的引數是hack**字串。
至此可以發覺,我們上述的hack函式是不能代入進去的,它和program a不是一類函式!因為hack有兩個引數,乙個是程式,乙個是字串;而當時定義halting_judge函式的時候,它只能承受這樣一類程式a:這個程式的引數只需要乙個——字串。
我的意思是說:雖然halting_judge裡隨便敷衍過去了,但實際上預設的a執行起來只需要input,而不是像hack那樣需要乙個program加乙個input才能執行。
也就是說,要把halting_judge改成(hack程式,hack程式,hack**)這種形式,或者把hack改成(char* input)這種形式,才可以實現hack自身代入。而第二種改法就是我之後要使用的。
另外,我們先拋開這個小bug不說,假如hack函式輸入只需要用input來代替,則,(接下來我只說一種情況),如果hack(input)用halting_judge判斷完是停機的,那麼hack(hack(input))是不停機的,也只能說明hack的輸入為input時停機,hack的輸入為hack(input)時不停機,憑什麼用乙個簡單的hack就代替了全部情況呢?就說hack停不停機是矛盾的呢?這邏輯就像「父親(我的)是程式設計師,父親(父親(我的)的)——也就是爺爺~不是程式設計師,所以父親到底是不是程式設計師這矛盾了判斷有誤」……單說父親不說誰的,耍流氓。
當然了還是那句話,很可能是我理解上的差錯。但各種短證明都會在結尾矛盾的那個地方輕飄飄一筆帶過,確實難以捉摸。
下面是我的想法:
我修改一下hack函式:
1bool hack (char*code)29
else
10return
true
;11 }
然後hack就可以自身代入了,把hack這段**傳入進去就是下面這樣:
1bool hack (char*hackcode)29
else
10return
true
;11 }
程式往下走,if判斷語句我們進去,情況是:
1bool halting_judge (program hack, char*hackcode)
2
而程式hack會不會停止呢?取決於它while(1)了還是return true了,即,注意,我們現在是在用halting_judge判斷:當hack函式的輸入為hackcode時是否停機。
有沒有發現這個和第一步一樣?又遞迴回來了!最初一步也就是還沒走到halting_judge的時候,就是用hack函式輸入hackcode。
那麼總結一下就是,只有我們把hack函式的輸入設定為hackcode,才真正變成了用halting_judge去檢測hack程式它自己(而不是什麼hack(hack(……))),之後再討論兩種情況才能達到自相矛盾的效果。
這時才表現了證明中的輸入非要用hack本身(其實是它的code)的重要意義:你把輸入換成pojcode試試,判斷就成了(poj,pojcode),沒法指向hack自身。
剛剛我說hack(hack(input))和hack(input)不能全統一為hack,那這裡為什麼可以?因為這裡這倆hack都是用hackcode編譯出來的。比喻來說,你就是hackcode,假如把你拎出來會導致我們能從人群中確定你爸爸。現在把你拎出來,和我們先把你帶進幼兒園再把你拎出來,我們從人群中找出來的你爸爸,是乙個人。
這上面的表述大費周章其實就是為了真真正正地達到:讓hack程式執行是否停機,然後讓halting_judge判斷的也是hack程式本身是否停機,然後通過矛盾反證halting_judge不存在。兩種情況都矛盾我就不多說了。
以上就是我的思考。等有能力看懂劉未鵬先生關於y combinator和哥德爾不完備性的精彩論述,以及我自身不斷學習計算機技術以後,我會繼續補充和改正以上論述的。由於初涉計算機領域,個人邏輯也不怎麼樣,非常希望大家指出我文章中的錯誤,感謝!
停機問題 The Halting Problem
看停機問題時,覺得它跟我國的 以子之矛攻子之盾 的想法很相似 也跟c語言的struct內不能包含自身很相似 停機問題描述 是否存在這樣的一段 h,這段 h以任意的 p作為輸入,它判斷 p在執行的過程中是否會停止。如果 p在執行的過程中會一直執行下去,不會停止,則程式h輸出 loop 反之,如果 p在...
停機問題的理解
關於停機問題維基百科給出的定義是 停機問題 halting problem 是邏輯數學中可計算性理論的乙個問題。通俗的說,停機問題就是判斷任意乙個程式是否會在有限的時間之內結束執行的問題。該問題等價於如下的判定問題 給定乙個程式 這個問題的結論是乙個可以解決停機問題的通用演算法是不存在的。問題倒是很...
停機問題的誤解
停機問題 halting problem 是否存在這樣乙個程式,他能判斷任意程式在輸入確定的情況下是否為死迴圈。可以用while true 表示死迴圈,構造例子如下 判斷 輸入 假設有兩個程式 a b 那麼 判斷 a 停機 判斷 b 死迴圈現在問題就是 是否存在這樣乙個判斷程式?先構造乙個相反函式,...