跳轉到

1973 年 Boyer-Moore 證明器:歸納法的自動偵探#

報案人:Robert Boyer 與 J Strother Moore(愛丁堡大學,後赴德州)。 涉案物:一台只懂 Lisp 卻會做數學歸納法的機器。代號:Nqthm。

案發現場#

1970 年代初,自動定理證明的主流是歸結原理。 它擅長一階邏輯的短證明,卻在一個地方屢屢失手:數學歸納法。 要證「 \(append\) 滿足結合律」「 \(reverse\) 對合」這類程式性質, 歸結器只能盲目展開公理,找不到歸納假設藏在哪裡。

另一邊,Lisp 程式滿天飛,卻沒人能保證它們正確。 Boyer 與 Moore 在愛丁堡目睹了這個裂縫:程式用遞迴定義, 性質用歸納證明,兩者明明是同一枚硬幣,機器卻看不出來。

1973 年,兩人立志打造一台「懂歸納」的證明器: 輸入 Lisp 函數定義與猜想,機器自動選歸納變元、丟出引理、完成證明。 這就是 Boyer-Moore 證明器,後來的 Nqthm 與 ACL2 的前身。

偵查過程#

線索一:結構歸納——把遞迴變成推理#

偵探的第一個發現:遞迴定義本身就藏著歸納模式。 例如自然數與串列:

\[ nat ::= 0 \mid s(n) \]
\[ list ::= nil \mid cons(x, xs) \]

Lisp 的 \(append\) 定義為:

\[ append(nil, y) = y \]
\[ append(cons(a, x), y) = cons(a, append(x, y)) \]

要證性質 \(P(x)\) 對一切 \(x\) 成立,只需證 \(P(nil)\) 與 \(P(x) \to P(cons(a, x))\) 。一般模式為:

\[ \frac{P(nil) \quad \forall a \, \forall x \, (P(x) \to P(cons(a, x)))}{\forall x \, P(x)} \]

Boyer-Moore 的絕招是「從函數的遞迴結構反推出該用的歸納模式」。 函數在哪個參數上做 \(nil\) 與 \(cons\) 分案,證明就在哪裡做歸納。

線索二:瀑布模型 waterall——證明的流水線#

證明器把猜想丟進一座「瀑布」,水流經過層層水池, 每一池都是一種化簡啟發式:

水池 動作 範例
化簡池 用定義與已證引理重寫 \(car(cons(a, x))\) 化為 \(a\)
丟棄池 消去無關假設、展開 \(if\) 分裂 \(if\) 兩支
泛化池 把重複出現的子項換成新變元 強化猜想以利歸納
消去池 用等式消元、引進引理 化 \(x\) 為構造子形式
歸納池 選歸納變元,產生基例與歸納步 丟出 \(P(nil)\) 與歸納假設

水流圖為:

\[ 猜想 \to 化簡 \to 泛化 \to 消去 \to 歸納 \to 子目標 \to 化簡 \to \cdots \]

子目標再送回瀑布頂端,直到全部化為 \(true\) 。 人類只需偶爾在半山腰遞一條關鍵引理,剩下的都由水流自動沖刷。

線索三:一個現場示範#

目標: \(append(x, nil) = x\) 。

  1. 化簡池試圖重寫,發現 \(x\) 是變元,卡住。
  2. 泛化池認為已夠一般,無需強化。
  3. 歸納池偵查 \(append\) 第一個參數的遞迴模式,提議對 \(x\) 做結構歸納。
  4. 產生基例 \(append(nil, nil) = nil\) ,由定義 \(append(nil, y) = y\) 直接得證。
  5. 歸納步假設 \(append(x, nil) = x\) ,目標變為 \(append(cons(a, x), nil) = cons(a, x)\) 。
  6. 左式按定義展開為 \(cons(a, append(x, nil))\) ,再用歸納假設重寫為 \(cons(a, x)\) ,得證。

全程機器自動選了歸納變元 \(x\) ,人類沒有下任何指令。 這在 1973 年是爆炸性新聞。

結案報告#

Boyer-Moore 證明器證明了數百條 Lisp 定理, 從算術、串列到簡單的作業系統與編譯器正確性, 拿下 1980 年代自動推理的半壁江山。

它的結案意義:

  1. 歸納自動化:證明歸納不只是天才的靈感,也可以是從遞迴定義計算出來的策略。
  2. 瀑布架構:化簡+啟發式的流水線成為後世證明器的範本。
  3. ACL2 伏筆:Nqthm 改寫為 ACL2 後打入工業界, 本幕最後一案將以 AMD 與 Motorola 的晶片驗證收網。

證據與工具#

  • 歸納公理模式:基例 \(P(nil)\) 加上歸納步 \(P(x) \to P(cons(a, x))\) 可得 \(\forall x \, P(x)\) 。
  • 化簡即重寫: \(append(nil, y)\) 恆重寫為 \(y\) , \(car(cons(a, x))\) 恆重寫為 \(a\) 。
  • 瀑布五池對照表見上,流程為猜想自頂端流入、子目標迴流的迴圈。
(defun append (x y)
  (if (endp x) y
      (cons (car x) (append (cdr x) y))))
;; 猜想:(equal (append x nil) x),對 x 做結構歸納
  • 延伸實驗:手動對 \(reverse(reverse(x)) = x\) 設計歸納模式,體會先證引理的動機。
  • 文獻:Boyer 與 Moore 1979 年《A Computational Logic》,Nqthm 手冊與 ACL2 前史。