跳轉到

2008 Z3 與 SMT 革命:理論求解器的聯合偵查#

案件編號:2008-Z3。報案人:軟體驗證、合約檢查、符號執行。案情:純 SAT 不懂整數、陣列與位元向量。破案者:de Moura 與 Bjorner。

案發現場#

2001 年 Chaff 讓純布林 SAT 快如閃電,但軟體驗證的公式不是純布林的。它們長這樣:「陣列 \(a\) 在 \(i\) 處更新後讀回是否等於 \(v\) ?」「32 位元無號加法是否溢位?」「整數計數器是否永不為負?」把這些硬編成 CNF,又大又慢,還丟失高層結構。

學界早有各理論的判定程序:等式與未解釋函數(EUF)、線性算術、陣列、位元向量,各自為政。缺少的是一個「聯合偵查指揮部」:讓 SAT 求解器管布林骨架,讓理論求解器管各自公理,兩者互相通報、共同破案。

2008 年,微軟的 de Moura 與 Bjorner 發布 Z3,高效、免費、介面友善,一舉把 SMT(Satisfiability Modulo Theories)送進千家萬戶。

偵查過程(含數學式/表格/理論)#

線索一:DPLL(T) 的雙向通報架構#

Z3 的心臟是 DPLL(T):SAT 引擎與理論求解器 \(T\) 的迴圈。布林抽象把每個理論原子(如 \(x + y \le 5\) )看成布林變數 \(p\) ,SAT 先找布林模型,理論再檢查該模型在 \(T\) 下是否一致:

\[ SAT \leftrightarrows Theory solvers \]

流程如審訊:SAT 提出嫌疑賦值 \(\sigma\) ,理論求解器驗身。若理論不一致(如 \(x > 0 \land x < 0\) 同真),回傳理論引理(theory lemma) \(\neg (p_1 \land p_2)\) ,SAT 學入子句再搜。懶惰(lazy)而高效,兼有早期剪枝與傳播。

表格:DPLL(T) 分工。

角色 負責 例子
SAT 核心(CDCL) 布林搜尋、學習、回跳 \(p \lor q\)
EUF 求解器 等式、同餘閉包 \(f(x) = f(y) \Leftarrow x = y\)
算術求解器 線性/非線性約束 \(x + 2y \le 5\)
陣列/位元向量 記憶體與機器整數 \(read(write(a,i,v),i) = v\)

線索二:理論表——每一條公理都是證詞#

SMT 的威力來自理論公理。精選對照表:

理論 簽名 關鍵公理
EUF \(=\) 、未解釋 \(f\) \(x = y \Rightarrow f(x) = f(y)\)
線性整數 LIA \(+\) 、 \(\le\) Fourier–Motzkin 消元
陣列 \(read\) 、 \(write\) \(read(write(a,i,v),i) = v\)
陣列外延 同上 \(i \ne j \Rightarrow read(write(a,i,v),j) = read(a,j)\)
位元向量 \(+_{32}\) 、 \(<<\) 、 \(\&\) 模 \(2^{32}\) 算術
量詞 \(\forall\) 、 \(\exists\) E-matching 實例化

偵查示例:要證 \(read(write(a,i,v),i) = v\) ,EUF+陣列公理一次結案,無需展開記憶體。位元向量理論則讓 \(x +_{32} 1 >_{u} x\) 的溢位查詢變成精確判定,而非抽象近似。

SMT-LIB 標準語言(2003 起,後續版本成熟)讓基準與求解器互通,SMT competition 複刻 SAT 的軍備賽榮景。

線索三:從合約驗證到 VS Code#

Z3 的破案範圍迅速擴大:

  • Dafny、Spec#、F* 把前後條件與不變式丟給 Z3,合約驗證按鍵即判。
  • 符號執行(SAGE、KLEE)把路徑條件丟給 Z3,每秒數千查詢。
  • VS Code 等現代編輯器的靜態檢查、依賴分析、甚至排程求解背後,常有 Z3 或其親戚。
  • Lean 4 的 de Moura 血統亦源於此:求解器與證明器本是一家。

表格:應用鏈。

應用 編碼 Z3 角色
有界模型檢查 單次賦值+ \(SS A\) 位元向量判定
合約驗證 \(VC\) 蘊含 量詞+算術+陣列
符號執行 路徑條件 增量求解
類型推斷/合成 約束集 組合優化 \(\nu Z\)

結案報告#

案件告破。Z3 證明:SAT 管骨架、理論管血肉,雙向引理交換即可馴服軟體公式。SMT 從論文走向基礎設施,驗證從實驗室走向按鍵。

遺產有三:

  1. SMT-LIB+競賽建立開放生態,CVC5、Yices、Boolector 百花齊放。
  2. 程式驗證工具鏈(Boogie、Dafny、F*、SeaHorn)統一以 SMT 為後端。
  3. 求解器即服務:Z3 Python/OCaml/C++ 綁定讓約束求解變成三行程式的事。

從因果鏈看,Z3 上承 DPLL、Chaff CDCL、歸結與各理論判定程序,下啟自動驗證普及與 Lean/AI 證明時代。

證據與工具#

證據 A:架構圖再現,獨立成行。

\[ SAT \leftrightarrows Theory solvers \]

左箭頭送理論引理,右箭頭送布林賦值,迴圈至 SAT 或 UNSAT。

證據 B:SMT-LIB 示例。

(set-logic QF_ABV)
(declare-const a (Array (_ BitVec 32) (_ BitVec 8)))
(declare-const i (_ BitVec 32))
(declare-const v (_ BitVec 8))
(assert (= (select (store a i v) i) v))
(check-sat)

此查詢應得 \(sat\) ,其否定則 \(unsat\) ,正好對應陣列公理。

證據 C:增量求解模式。 push 、 assert 、 check-sat 、 pop 四步迴圈,符號執行靠它重用學習子句,查詢吞吐提升數量級。

證據 D:延伸閱讀。de Moura 與 Bjorner 2008 年〈Z3: An Efficient SMT Solver〉;Barrett 等《Handbook of Satisfiability》SMT 章;SMT-LIB 官網基準庫與 Z3 GitHub 教程。