1. 程式人生 > 實用技巧 >可計算性理論與複雜性介紹

可計算性理論與複雜性介紹

前言

原文:An Introduction to Computability Theory and Complexity作者: MEHMET BAJIN

正文

你有沒有想過:你正在閱讀這篇文章的裝置究竟是什麼?什麼是電腦?

計算科學可以追溯到在這些現代計算機裝置還沒有被想象出來之前很長一段時間。在一個更經常被問到的問題中,圍繞著程式語言、框架和庫的問題,我們常常想當然地認為,計算機的基本概念是必不可少的。

但是這些電腦似乎擁有無盡的潛力,它們有任何限制嗎?有使用計算機卻解決不了的問題嗎?

在本文中,我們將通過不再討論程式語言和計算機體系結構的細節來解決這些問題。通過了解計算機和演算法的能力和侷限性,我們可以改進我們的思考方式,並更好地解釋不同的策略。

計算機的抽象觀點產生了經得起時間考驗的結果,與上世紀70年代最初發展時一樣,對今天的我們來說依舊是有價值的。

可計算

什麼是電腦?什麼是問題?

在學校裡,我們經常被教授一個問題和功能的心理模型,就像這樣:

函式是一個通過輸入x以便獲得一個輸出f(x)的過程。

原來數學的定義是不一樣的:

一個函式是一組有序對,每對的第一個元素來自一個集合X(稱為域),每個對的第二個元素來自一個集合Y(稱為陪域或範圍),該域中每個元素都與該範圍中的唯一一個元素相配對(即X中每一個元素都存在惟一的Y中的元素與之對應)。

這是相當的拗口,但是,這到底意味著什麼呢?

這個定義告訴我們,計算機是計算函式的機器。

為什麼?

由於計算機將任意輸入轉換為某些輸出。換句話說,他們解決問題。函式的兩個定義,我們熟悉的和正式的,都有很多實際的用途。

然而,數學定義使我們能夠得出一些有趣的結論,例如存在不可計算的函式(即無法解決的問題):

因為,並不是每個函式都可以被描述為一個演算法。

遊戲規則

為了使我們的論點有所幫助,讓我們將計算機想象成機器接受一些輸入,執行一系列操作,並在一段時間後給出一些輸出。

我們把輸入稱為機器的字母表;也就是說,機器的字母表可能是二進位制的(0和1),也可能是ASCII字符集,任何有限的字元序列都是一個字串,例如“0110”。

此外,我們將機器的輸出表示為二進位制接受 - 拒絕決策,一旦機器(希望)完成其計算就交付。這個抽象符合早期函式的數學定義。

給定這些引數,對重新定義一個型別是很重要的:字串集合。也許我們關心某些機器接受的字串集合,或者我們正在建立一個接受某個集合中的字串而不接受其他字串的機器,或者我們問是否可以設計一個只接受某些特定下的所有東西的機器。

在所有這些情況下,一組字串被稱為一種語言,例如,表示偶數的所有二進位制字串的集合或具有偶數個字元的字串的集合。事實證明,像數字這樣的語言可以用諸如串聯(concatenation),聯合(union ),交叉(intersection)等操作符來操作

一個重要的運算子是Kleene星形(Kleene star)運算子,它也用於正則表示式。這可以被認為是所有可能的語言權力的結合。例如,如果我們的語言A是字串{'01','1'}的集合,則A *的一個成員是字串'0101111'。

可數性

在我們證明並不是所有的函式都是可計算的之前,最後一個問題是可數性的概念。直觀地說,我們的證明會顯示有更多的語言;這是比可能的解決方案更多的問題。這是因為字串是否屬於語言(yes/no)本身就是一個問題。

更確切地說, 我們的證據聲稱, 可能的程式集是可無窮大的, 而在字母表的語言集是不可無窮大。

在這一點上,你可能會想,“無窮大本身就是一個奇怪的想法;現在我必須處理其中的兩個!”

好吧,沒那麼糟。可數無限集是可以列舉的。可以這樣說,這是第一個元素,這是第二個元素,等等,最終給集合中的每個元素分配一個數字,例如,取偶數的集合。我們可以說,2 是第一個, 4 第二, 6 第三, 依此類推。這種集合是可無窮或可數的。

儘管有一些集合, 像實數一樣, 你有多聰明也無所謂。根本沒有列舉。這些集是不可數的無限或無數。

可數的許多程式

首先,我們要證明計算機程式集是可數的。出於我們的目的,我們通過觀察一個有限字母的所有字串的集合是可數的。這是可行的,因為計算機程式本身就是有限的字串。

這個證明是直接的,我們不涉及細節。關鍵的一點是,那裡的計算機程式和自然數字一樣多。

重申:

任何字母表上的所有字串(例如,所有計算機程式的集合)的集合都是可數的。

再一次,我們不涉及到證明。

後果

雖然他們可能不會立即顯現出來,但語言的不可數性和所有計算機程式的可計數性的後果是深刻的。

為什麼?

假設A是一組ASCII字元,ASCII字元就是組成計算機程式所需要的。我們可以看到,表示JavaScript程式的字串集合是A *的一個子集(這裡的*是Kleene星形運算子)。JavaScript的選擇是任意的。由於這套程式是可數集的一個子集,我們已經知道這套JavaScript程式是可數的。

另外,讓我們考慮對於任何語言L,我們可以定義一些函式f,如果一些字串x在L中,則函式f的值為1,否則為0。所有這些功能是不同的。因為與所有語言的集合有1:1的對應關係,並且因為所有語言的集合都是不可數的,所以我們知道所有這些函式的集合是不可數的。

這是深刻的一點:

由於所有有效程式的集合都是可數的,但函式的集合是不可數的,所以必定有一些函式我們不能編寫程式。

我們還不知道這些函式或問題是什麼樣的,但我們知道它們存在。這是一個令人謙卑的認識,因為有一些問題沒有解決。我們認為電腦是非常強大和有能力的,但有些東西甚至超出了他們的範圍。

現在問題變成了“這些問題是什麼樣子的?”在我們繼續描述這些問題之前,我們必須首先以一種普遍的方式來模擬計算。

圖靈機

計算機的第一個數學模型之一是由Alan Turing開發的。這個稱為圖靈機的模型是一個非常簡單的裝置,完全可以捕捉我們的可計算性概念。

機器的輸入是輸入已寫入的磁帶。使用讀/寫頭,機器通過一系列步驟將輸入轉換為輸出。在每一步中,都要做一個決定:要寫什麼,要寫什麼,要不要把它左右移動。這個決定是基於兩件事:

  • 現在的符號在頭下面,
  • 機器的內部狀態,也隨著符號的編寫而更新

而已。

普遍性

1926年,阿蘭圖靈不僅開發了圖靈機,而且還在他的著名論文““On Computable Numbers”上,對計算的性質有了許多其他重要的見解。他意識到,計算機程式本身可以被認為是計算機的輸入。有了這個觀點,他有了一個漂亮的想法:圖靈機可以模擬或執行輸入。

Church-Turing Thesis

在我們繼續之前,讓我們來看一個重要的觀點:我們知道圖靈機是計算的一個模型,但它是否足夠普遍?為了回答這個問題,我們轉向Church-Turing Thesis,其相信下面的陳述:

一切可計算的東西都可以通過圖靈機來計算。

在圖靈開發圖靈機作為計算模型的同時,阿朗佐教會也開發了一種稱為lambda演算的計算模型。這些模型是強大的,因為它們都描述計算,並且以與當今任何計算機或任何計算機相同的方式進行計算。這意味著我們可以使用圖靈機來描述我們所尋求的無法解決的問題,因為我們知道我們的發現將適用於所有可能的計算機過去,現在和以後。

可識別性和可判定性

在我們具體描述一個無法解決的問題之前,我們不得不覆蓋更多的背景知識,即語言識別器和語言決策者的概念。

一個語言是可識別的,如果有一個圖靈機識別它。一個語言是可判定的,如果有一個圖靈機決定它。

為了成為一種語言的識別器,圖靈機必須接受語言中的每一個字串,並且不能接受任何不屬於該語言的東西。它可能拒絕或迴圈這樣的字串。要成為一個決定者,圖靈機必須始終停止輸入,要麼接受要麼拒絕。

在這裡,停止輸入的想法是至關重要的。事實上,我們看到決策者比識別者更強大。此外,一個問題是可以解決的,換句話說,只有存在決定函式描述的語言的圖靈機時,函式才是可判定的。

不可判定性

如果你曾經寫過一個計算機程式,當程式執行的時候,你一定知道坐在那裡只是看著計算機旋轉它的輪子的感覺。您不知道該程式是否花了很長時間,或者程式碼中有錯誤導致無限迴圈。你甚至可能想知道為什麼編譯器不檢查程式碼,看它是否會在執行時停機或迴圈。

編譯器沒有這樣的檢查,因為它根本無法完成。並不是編譯器工程師不夠聰明或缺乏資源;根本不可能檢查任意的計算機程式以確定它是否停止。

我們可以使用圖靈機來證明這一點。圖靈機可以被描述為字串,所以有一個可數的數字。假設M1,M2等組成了所有圖靈機的集合。讓我們定義下面的函式:

f(i, j) = 1 if Mi accepts <Mj>, 0 otherwise

這裡,<M>是“M的字串編碼”的語法,並且這個函式表示如果Mi通過接受Mj作為輸入而停止,則輸出1,否則輸出0的問題。請注意,Mi必須停止(即成為決定者)。這是必需的,因為我們希望描述一個不可解釋的函式(即無法解決的問題)。

現在, 讓我們也定義一種語言 L, 它由不接受自己描述的圖靈機的字串編碼組成:

L = { <M> | M does not accept <M> }

例如,一些機器M1可能在輸入<M1>上輸出0,而另一個機器M2可能在輸入<M2>上輸出1。為了證明這種語言是不可判定的,我們會問決定語言L的機器ML是什麼,當它給出自己的描述<ML>作為輸入時。有兩種可能性:

ML接受<ML> 要麼 ML拒絕<ML>

如果ML接受自己的編碼,那麼這意味著<ML>不在語言L中;但是,如果是這樣的話,ML本來就不應該接受它的編碼。另一方面,如果ML不接受自己的編碼,那麼<ML>是語言L,所以ML應該接受它的字串編碼。

在這兩種情況下,我們都有矛盾,或者用數學術語來說是一個矛盾,證明L語言是不可判定的。因此,我們已經描述了我們的第一個無法解決的問題。

停機問題(Halting Problem)

雖然我們剛剛描述的問題似乎並不相關,但可以將其歸結為具有實際重要性的其他無法解決的問題,最明顯的是停機問題

圖靈機編碼的語言停在空串上。

停機問題適用於為什麼編譯器無法檢測到以前的無限迴圈的問題。如果我們不能確定程式是否在空字串上終止,那麼我們怎麼可能確定它的執行是否會導致無限迴圈呢?

在這一點上,似乎我們只是揮揮手來得出一些簡單的結論;然而,我們實際上已經意識到,沒有一個圖靈機可以告訴計算機程式是永久停止還是停留在一個迴圈中。這是實際應用中的一個重要問題,在圖靈機或任何其他型別的計算機上都無法解決。iPhone不能解決這個問題。具有多個核心的桌面無法解決此問題。雲無法解決這個問題。即使有人要發明量子計算機,也無法解決停機問題。

總結

在我們對可計算性理論的研究中,我們已經看到了如何有許多函式是不可計算的。我們通過計算精確地定義了我們的意思,從他自己的筆和紙的經驗一直回到圖靈的靈感來正式化圖靈機。我們已經看到了這個模型如何計算任何今天的計算機或者明天可以預見的計算機,並且我們意識到一類根本不可計算的問題。

可計算性還有一個缺點。只是因為我們可以解決問題並不意味著我們可以快速解決問題。畢竟,如果計算機在未來幾千萬年的太陽升起之前還沒有完成,那麼計算機有什麼好處呢?

離開可計算的功能和語言背後,我們現在討論計算的複雜性,調查有效的計算和著名的P對NP問題。

複雜

慢與快

電腦科學家認識到各種各樣的問題,我們關心的兩個類別包括計算機可以快速或有效地解決的問題,稱為P,問題的解決方案可以快速驗證,但無法快速獲得,稱為NP。

例如,假設你負責開發線上約會服務的演算法,並且有人提出了“每個人都可以約會”的問題。答案歸結為將相容的個人配對,使每個人都配對。原來有解決這個問題的高效演算法。這個問題在P集中。

那麼,如果我們想確定我們使用者中最大的集團呢?我們所說的集團,是指所有相互相容的最大的個人網路。當用戶數量低時,這個問題可以很快解決。我們可以很容易地識別出3個使用者的派系。然而,當我們開始尋找更大的集團時,問題變得越來越難以解決。這個問題在NP中。

形式定義

P是多項式時間可解的一組問題。也就是說,計算步驟的數量由關於問題大小的多項式函式限定。我們知道“人人都可以約會嗎?”這個問題,也稱為雙邊匹配問題,在P中。

NP是在多項式時間內可驗證的一組問題。這當然包括P中的每個問題;但是,我們不知道這個遏制是否嚴格。我們知道可以有效驗證但不能有效解決的問題,但是我們不知道問題是否真的難以解決。集團問題就是這樣一個問題。我們知道我們可以高效地驗證解決方案,但是我們不確定能否有效地解決問題。

最後,NP-complete是NP中最難解決的一系列問題。他們被認為是最難的,因為NP中的任何問題都可以有效地轉化為NPC。結果是,如果有人能夠找到有效解決NPC問題的辦法,那麼整個NP類將被P所吸收。集團問題也在NPC中。

因此,我們得出P與NP的問題。許多電腦科學家和數學家堅信,P和NP是不相等的。如果是的話,其影響將是深遠的。現在的大部分數字基礎設施都依賴於NP中沒有P中存在的問題。如果情況並非如此,那麼例如,密碼方法就會在一夜之間崩潰,從而使一個擁有有效解決NPC問題的人甚至可以破壞最嚴密的安全協議。

Tractability Subtleties

對於電腦科學新手來說, 匹配和派系問題之間的區別似乎不是什麼大不了的事情。事實上, P 中的問題和 NP 中的問題之間的區別是非常微妙的。能夠辨別差異對於任何在現實世界中設計演算法的人來說都很重要。

考慮最短路徑問題。給定兩個位置,目的是確定它們之間的最短路徑。iPhone在幾毫秒內計算出來。這是一個計算上易於處理的問題。

另一方面,考慮一下旅行推銷員的問題,目標是在儘可能短的距離內訪問一個可能的目的地的子集。這個問題類似於最短路徑問題,但是NP-complete;這也解釋了為什麼供應鏈物流是一個10億美元的產業。

我們其實可以更微妙。不要求最短路徑(P),我們可以要求沒有周期的最長路徑。發現最長的路徑問題也是NP-complete。

這個微妙的區別還有更多的例子,包括在二分圖與一般圖中的頂點覆蓋的確定,或者在每個子句中有兩個與三個文字的布林公式的滿意度。問題在於P或NP中是否存在問題並不明顯,這就是為什麼執行時間分析是關鍵技能的原因。如果必須設計的演算法是針對P中的問題,那麼我們知道有一個有效的解決方案。另一方面,如果問題是NP,那麼我們就有一個強有力的理由來反對尋求解決方案,因為一般來說,這個演算法會花很長時間來解決這個問題。

總結

在這個複雜性的考察中,我們定義了問題P和NP的類別。P非正式地表示可以通過計算機有效解決的問題,而NP表示可以有效驗證的問題。

沒有人能夠證明P不等於NP。這兩類問題是否等價,就是眾所周知的P vs. NP問題,而且它是當今理論電腦科學中最重要的開放問題,如果不是所有的數學問題的話。事實上,在2000年,克萊數學研究所將P vs. NP問題列為數學中七個最重要的開放問題之一,並提供了數百萬美元的獎金,以證明這個問題的解決方案。

結論

在這篇文章中,我們深入到可計算性和複雜性的領域,回答諸如“什麼是電腦”這樣的大問題。雖然細節可以壓倒一切,但值得記住的是一些深刻的東西:

  • 有些東西根本無法計算,就像停機問題一樣。
  • 有些東西不能有效地計算,比如NPC中的問題。

比細節更重要的是思考計算和計算問題的方法。在我們的職業生涯中,甚至在我們的日常生活中,我們可能會遇到以前從未見過的問題,我們可以使用可靠的工具和技術來確定最佳的行動方案。

瞭解基礎知識

是否存在沒有解決方案的計算問題?

由於所有有效程式的集合都是可數的,但函式的集合是不可數的,所以必定有一些函式我們不能編寫程式。

什麼是 Church-Turing Thesis?

Church-TuringThesis指出,所有可計算的東西都可以通過圖靈機來計算。

什麼是 P versus NP問題?

確定每個計算問題的解可以在多項式時間內驗證的問題也可以用多項式時間求解。

發表於2018-09-19