神奇的自產生程式,兼談人工生命

發表於2013-12-25

最近讀到馮·諾依曼的《Theory of Self-Reproducing Automata》的中譯本,被自複製自動機理論深深吸引了!生命是什麼?這本書讓我對生命有了新的認識。

熱力學第二定律是宇宙的死亡法則:系統的熵總是趨於增加,系統總是由有序趨向無序,由有形趨向混沌,最後終結於熱寂。宇宙萬物都逃不過這條法則,唯有生命例外。通過與外界交換能量,生命可以保持內在的有序。只有生命可以違抗熱力學第二定律。

熱力學與資訊理論有著內在聯絡:一個系統越有序,它包含的資訊就越多;一個系統越無序,它包含的資訊就越少。資訊總是沿著減少的方向流動。只有生命可以抗拒這個規律:生命可以“創造”出資訊。“創造”是生命之所以為生命的本質。

生命的另一個神奇之處是,他們自己包含了自己的全部資訊,他們自己可以產生一個跟自己一樣的新生命。唯有生命可以做到自己創造自己。

馮·諾依曼認為,一個簡單的系統是無法抗拒熱力學第二定律的,這樣的系統只會越來越趨向於無序,能量會向更低的方向流動,資訊會越來越少。只有當系統複雜到某一個程度的時候,不妨設為臨界點 C ,一旦越過了這個臨界點,系統可以自己創造自己,這樣系統就可以逆熱力學第二定律而上,並且變得越來越複雜。

這裡的臨界點 C 跟不少人提出的“技術奇異點”是一樣的:人們認為,當人工智慧達到了這樣一種程度,即它們可以自己創造自己的時候,這就是人工智慧真正覺醒的時候。“奇異點”就是機器可以自己造出自己的時候,“奇異點”之後,機器將進化,並且變得越來越複雜,超出人類所能理解的範圍,它們在某種程度上已經具備了生命的特質,那將是人工智慧的時代。

總而言之,生命之所以區別於世界萬物,就在於生命可以包含自己的全部資訊。所以下面就是我們的問題了:

問題(自產生程式):編寫一個程式,不讀取任何輸入,只把自己的原始碼輸出。

這個問題是個非常本質的問題,跟使用什麼程式語言無關(不要想到使用反射之類的東西)。

試想,如果要輸出自己的原始碼,那麼,顯然,程式中應該有“print …”語句。但 print 什麼出來呢?如果硬要寫的話就會變成:

最後是一個無限迴圈。

一般地,我們知道,如果程式 A 能產生程式 B ,那麼 A 必須包含 B 的全部資訊,而且應該比 B 的資訊還多,因為還要包含額外的列印語句。也就是說,一般情況下,資訊是減少的。而這個自產生程式,自己要包含自己的全部資訊,從某種程度上已經具有生命的意味了。

下面列出一些自產生程式及其思路。

需要注意的是,使用程式語言本身的反射功能或者讀取檔案等做法都被視為 cheating ,比如這樣的 bash 指令碼:

或者像這樣的 javascript :

因為這些程式沒有體現出自產生程式的遞迴和自指特性,或者結果嚴重依賴於程式語言的具體實現。

 

輸出原始碼在該語言中的轉義

Python :

Lua 5.1 :

另一個 Lua 版:

Scala :

 

用某種方法 encode 原始碼,使之不包含引號,然後還原出原始碼

Bash :

Lua 5.2 使用 load():

Scala :

 

使用 eval :在 eval 的字串中引用自己

Lua load() 的另一種用法:

js 的 eval():

 

使用語言中的更強的轉義機制

類似上面的第二種,但不用引號。

Lua 的 long string :

Scala 的三引號:

 

使用 C 的巨集

先執行傳入的引數,再把引數變成字串。

gcc :

至於它們是怎麼實現的,就留給讀者自己琢磨了。自產生程式也稱為 Quine ,可以參考 Quine Page 。

相關文章