本文へスキップ
hdknr blog

形式手法(Formal Methods)

仕様や設計を数学的に厳密な形で書き、その性質を機械で検査する技術群。AI コード生成の普及で再評価され、LLM に形式化させて検査器に判定させる使い方が実用になっている

概要

形式手法(Formal Methods)は、仕様や設計を数学的に厳密な形で書き、その性質を機械で検査する技術群。テストが「人間が選んだ入力で正しく動くか」を確かめるのに対し、形式手法の検査器はモデルのすべての入力・すべての実行順を調べ、性質を破る反例を 1 つ返すか「反例なし」と答える。テストが「実装が仕様どおりか」を見るのに対し、形式手法は「仕様そのものが正しいか」まで検査できる。型システムも軽量な形式手法の一種である。

詳細

テストとの違い

テスト形式手法
調べる範囲人間が選んだ入力・実行順モデルの全入力・全実行順(有限の範囲内)
対象実装仕様・設計のモデル
答え通った/落ちた反例/「反例なし」
弱点選ばなかったケースは調べないモデルが実装と食い違えば結果も外れる

検査器が保証するのは「このモデルについて」の結果にすぎない。そのため、反例は必ず実装のテストで再現させてからバグと判断する。

道具の選び方

道具は「問いの形」で選び、反例を出せる最小の道具を使う。mizchi さんの仕様化スキル formal-methods-reconciler の分類に沿うと次のとおり。

問いの形例道具
純粋な述語(入力 → 真偽)料金計算、設定値の組み合わせZ3(SMT ソルバ)
関係(ユーザー・ロール・リソース)権限、テナント分離Alloy
状態遷移・並行実行キャッシュ、リトライ、分散プロトコルTLA+(モデル検査器 TLC)、Quint
事前・事後条件つきの逐次コードループ不変条件Dafny
無限の範囲での定理アルゴリズムの正しさLean、Rocq

同スキルは「Z3 で時相的なインターリーブを扱うな」「単純な述語に TLA+ を使うな」とも戒めている。mizchi さんの経験則では、マイクロサービスやマルチスレッドのキャッシュ制御には「ほぼ確実に漏れがある」ので TLA+ か Quint、迷ったら Z3 か TLA+。

LLM との役割分担

基本姿勢は「LLM がモデルを提案・修正し、検査器が判定する」(formal-methods-reconciler)。

mizchi さんが挙げるプロンプト例は、「今あるコードを形式化できる部分を形式化して、それをテストオラクルに、実装がそれに従ってるか確認して」「モデル検査で反例が出たら、それを実際のテストケースに落として」「何を検査したか、ドメインの言葉を使わずに例え話で説明して」。

実践で効く 4 つの規律

  1. 反例は実装で再現させる:同じ入力・同じ実行順をテストで強制する。並行実行なら threading.Event などで止める位置を作り、トレースの順番どおりに割り込ませる。再現しなければ、まずモデルの前提(原子性、ロック、リトライ)を疑う
  2. 「反例なし」は空振りを疑う:性質が自明に成り立っていないか(例:キャッシュに一度も値が入らない)、前提が一度も真にならないか(例:誰も終わらない)を確かめる。「破られるべき」不変条件を置いて違反が出ること、修正を外した変異版が落ちることをセットで見る。考え方は ミューテーションテスト と同じ
  3. 性質は 1 つだけで検査しない:ある規則だけを検査して unsat を得た修正が、別の規則を黙って破っていることがある。仕様全体を同時に満たせない入力を探す(Z3 なら ForAll で「どんな出力でも全規則を満たせない入力」を求める)と、仕様そのものの矛盾が見える
  4. 仕様の矛盾は人間に返す:どう実装しても満たせない仕様は実装側で直せない。決まるまで pytest の xfail(strict=True) で記録しておくと、判断が入って挙動が変わったときに XPASS で気づける

実例(2026-10 の検証)

仕様レビューの検査役として使う

要求仕様書作成ループでは、エージェント同士の仕様レビューに Formal Checker を置き、対象を 3 つに絞る — 決定表・計算ルールは Z3(どのルールにも当てはまらない入力=抜け、2 つのルールが違う結果を出す入力=矛盾)、並行・リトライ・取り消しが絡む業務フローは TLA+、権限・ロールは Alloy。画面や文言、順番どおりに進むだけのフローは対象外。反例は具体的な入力なので、利用者には式を見せず「A と B のどちらにしますか?」という選択肢付きの質問に直して Q&A 表に起票する。形式手法が確かめるのは仕様内部の整合性だけで、「利用者が本当に必要としているか」は判定できない。

なぜ今なのか(verification bottleneck)

人間がコードを書く時代、形式手法は二重コストだった。形式検証されたマイクロカーネル seL4 は、8,700 行の C コードの検証に 25 人年を要している。

AI エージェントがコード生成を担うと構図が逆転する。

人間のレビューが最大のボトルネック(verification bottleneck)になり、かつてコスト超過で退けられた形式手法が相対的に実用的な選択肢になった。金融テクノロジー企業 Jane Street の技術責任者 Yaron Minsky が、25 年間の懐疑を捨てて専門チームを新設したことで再注目された。同社は OxCaml(社内版 OCaml)の型システムを深くコントロールしつつ、Lean・Dafny・Rocq(旧 Coq)を補完として位置づけている。

形式手法は AI 自身へのフィードバック機構にもなる。「テストが通った」は曖昧な信号だが、「すべての入力で成立する」は普遍的な保証であり、AI 生成コードを評価・改善するループの停止条件として使える。

関連ページ

ソース記事