computo ergo sumEnglish
この説明の全体

入口

  1. Lean とは何か
  2. 使い方の入口
  3. 有限の判定を decide に載せる
  4. 数え上げを Finset で書く
  5. 単射一本で上界を出す
  6. 級数と不等式
  7. 証明書を Lean に検査させる
  8. 通っても、言いたいことが言えているか
  9. 言明を読む手順
  10. Lean では現実的に厳しいもの
  11. よくある罠
  12. 用語集
  13. Lean の仕組み

Lean では現実的に厳しいもの — 量・述べ方・在庫

紙で書けている証明が Lean に載らないことがあります。理由は三つ——有限だが大きすぎる、述べ方が決まっていない、下敷きの数学が mathlib に無い。どれに当たっているかで打つ手が違います。

このページの順序
  1. 厳しさには三つの出所がある
  2. 有限だが大きすぎる
  3. 「列挙がそれで全部」を述べる形が無い
  4. mathlib に在庫が無い数学
  5. 三つの見分け方

01

厳しさには三つの出所がある

紙で書けている証明が、Lean に載らないことがあります。理由は三つに分かれ、どれに当たっているかで打つ手が違います。

量有限だが大きすぎる 書き方は決まっているのに、検査の費用が現実の範囲を超える
型述べ方が無い 言いたいことを Lean の言明にする形が決まっていない
在庫mathlib に無い 下敷きになる数学がまだ形式化されていない

量の問題は測れます。述べ方の問題は設計の問題です。在庫の問題は、自分で積むか、紙に残すかの判断です。三つとも「できない」ではなく「いま払える費用でできない」で、費用の桁が違います。


02

有限だが大きすぎる

実演 — decide の費用は探索空間で決まる

decide は有限の場合を全部数え上げます。費用は場合の数そのものです。小さな例で測ります。頂点 Fin k のうち最初の 4 点が互いに隣接するグラフを取り(4 点が互いに隣接していれば 3 色では塗れません)、3 色の塗り方が一つも無いことを decide に確かめさせます。塗り方は 3^k 通りです。

def Adj (k : ℕ) (i j : Fin k) : Bool := i.val < 4 && j.val < 4 && i.val ≠ j.val

def Proper (k : ℕ) (f : Fin k → Fin 3) : Bool :=
  decide (∀ i j : Fin k, Adj k i j = true → f i ≠ f j)

set_option maxRecDepth 100000 in
theorem noCol6 : ∀ f : Fin 6 → Fin 3, Proper 6 f = false := by decide

k を替えて検査の時間を測りました。import Mathlib だけのファイルが 5.01 秒なので、その差が decide の費用です。

検査したもの探索空間検査差
import Mathlib だけ(基準)—5.01 s—
Fin 4 → Fin 3 の網羅815.41 s0.4 s
Fin 6 → Fin 3 の網羅7299.19 s4.2 s
Fin 8 → Fin 3 の網羅6,561止まる(heartbeat の上限 200000 に当たって 64 s で終了)
Fin 6 → Fin 3(maxRecDepth を既定のまま)729止まる(maximum recursion depth has been reached)

読めることが三つあります。

この形の壁に当たったときにやることは、上限を上げて待つことではなく、1 件あたりの費用を測って全体の桁を出すことです。

実例 — 148 万件の判定は 100〜1000 CPU 時間

単位距離グラフの上界の議論では、候補のグラフを段階的に篩に掛けて落とします。篩の最初の段は、辺の集合だけを見て「点の数が多すぎる」「次数が大きすぎる」で落とす判定で、候補の 86% がここで落ちます。この判定を Lean の中で回すとどうなるかを測りました。

測ったもの実測
基準(import Mathlib だけ)5.373 s
判定を 20 回7.092 s
差から 1 候補あたり86 ms
候補の数1,482,463
この段だけで約 35 時間

次の段はもっと重く、全体では 10²〜10³ CPU 時間の桁になります。証明書の本数(771 本)は既に手の内にある規模で、桁を支配しているのは判定を回す回数の側です。

この見積りから出る設計の話が一つあります。候補ごとに decide を打つのは、候補の個数が Lean の外で決まっているからです。候補の一覧を Lean の項として持ち込めば、decide の回数は 1 回になります。ただし一覧を項として持つと項の大きさが 10⁶ の桁になり、費用が「回数」から「項の大きさ」に移るだけかもしれません。どちらが安いかは測れる問いです。

存在は安く、非存在は高い

費用の非対称が一つあり、これは量の問題の中でいちばん効きます。

存在:証人を一つ渡して検めるだけ  非存在:全部を網羅する

上の実演と同じ設定で、塗れる側を測ります。最初の 3 点だけが互いに隣接するグラフなら 3 色で塗れます。塗り方を一つ書いて渡します。

theorem col20 : ∃ f : Fin 20 → Fin 3, Proper3 20 f = true :=
  ⟨fun i => ⟨i.val % 3, Nat.mod_lt _ (by norm_num)⟩, by decide⟩

20 点でも 5.21 秒——基準との差は 0.2 秒です。探索空間は 3^20 = 34 億通りありますが、証人を渡せば数え上げは起きません。6 点の非存在(729 通り)より安く済みます。

言明探索空間検査
20 点で 3 色に塗れる(存在・証人つき)320 ≈ 34 億5.21 s
6 点で 3 色に塗れない(非存在・網羅)7299.19 s

だから篩の段を設計するときは、その段が「どちらの向き」に使われるかを先に見ます。篩は候補を落とす道具なので、どの段も非存在の向きに使われます。「3 色に塗れないから落とす」は、そのまま書くと網羅になります。

実例で言うと、上の篩の段のうち彩色を根拠にする印だけは Lean で回せません。15 点・3 色で 3^15 = 1,434 万通りの網羅になり、再帰の深さの上限で落ちます(実測)。言明そのものは初等的で、格子の上なら十行で閉じます。重さの出所は言明の難しさではなく、使う向きです。

この段を篩から外しても全体は閉じますが、下流に流れる候補が 4.8 倍に増えます。一つの段を落としたら下流の個数が何倍になるかを、見積りの中に変数として持っておきます。


03

「列挙がそれで全部」を述べる形が無い

候補を並べて一つずつ潰す形の議論には、二つの部分があります。

言明Lean での形
(i)並べた候補はどれも条件を満たさないある。候補ごとに証明書を渡して decide(07)
(ii)並べた候補で全部である(列挙の完全性)決まっていない

(ii) が難しいのは、量の問題ではありません。言明を立てる形が決まっていないのです。書くには少なくとも次が要ります。

三つ目が本体です。外の探索は速さのために枝を刈っていて、刈った理由は探索のコードの中にしかありません。それを Lean に移すのは、探索を Lean で書き直すのと同じ作業です。07 証明書を Lean に検査させるの分業(探すのは外・確かめるのは Lean)が、ここでは効きません。証明書に当たるものが無いからです。

Lean に入っているのは一覧の長さだけです。

theorem cands_card : cands.length = 117 := by decide

これは「一覧が 117 個ある」であって「候補が 117 個で全部」ではありません。両者の差は 08 通っても、言いたいことが言えているかの型②です。

だから等級を分けて書きます。(i) は Lean、(ii) は 計算 です。上界の主張は (i) と (ii) の両方に乗っているので、主張全体の等級は 計算 になります。定理名が付いているのは (i) だけなので、表を作らないとこの一段が落ちます。


04

mathlib に在庫が無い数学

三つ目は、下敷きになる数学がまだ形式化されていない場合です。この場合、費用は「自分で積む」費用になります。

在庫の有無は grep で分かります。mathlib のソースを検索した結果です。

探した語当たったファイル意味
Bakry0Bakry–Émery の理論は無い
Ricci0Riemann 幾何の曲率が無い
logSobolev・log_sobolev0対数ソボレフ不等式が無い
bessel4名前は出るが、変形ベッセル関数の不等式は無い
toSphere1球面の上の測度はある(MeasureTheory/Constructions/HaarToSphere.lean)

この表が、何を紙に残すかを決めます。四つ目と五つ目のように部分的に在庫がある場合は、在る部分に繋ぐのが安いことがあります。球面の測度は在ったので、性質で定義した測度が mathlib の定義と一致することを示す定理を一本置いて繋げました(08 §04 の (c))。

紙に残すと決める基準

次の三つが揃ったら、紙に残す判断です。

基準

  1. その数学が教科書の定理である。自分の議論の新しい部分ではなく、外から引いてくる部分である
  2. mathlib に無い。grep で確かめる。似た名前が出ても、必要な形の言明が無ければ「無い」
  3. 自分で積むと、本体より大きくなる。Riemann 幾何を一から積むのは、元の議論より何倍も大きい作業である

逆に、次のどれかに当たるなら紙に残しません。自分の議論の新しい部分である(引いてくるものではない)/在庫の一部を使えば繋がる/量の問題であって述べ方の問題ではない。

残したことを明記する書き方

紙に残した部分は、結果の表の中に行として置きます。書くのは三つです。

書くもの例
何が紙か(言明を一行で)測地線に沿った二階微分が Riemann 的な Hesse 形式に等しいこと・球面の Ric = 2
なぜ紙か標準的事実だが、mathlib に Riemann 幾何の在庫がほぼ無い
どこで継いでいるかLean 側の hess_gauge(二階微分の下界)から、紙側の曲率の下界へ

三つ目が効きます。継ぎ目の場所を書くと、読み手はそこだけを検分できます。「一部は紙です」とだけ書くと、どこを見ればよいか分かりません。

そして、紙の行が結論の直前にあるなら、結論の等級は紙です。Lean の行がいくつ並んでいても変わりません。受け取る側がこれを確かめる手順が 09 言明を読む手順の⑦にあります。


05

三つの見分け方

出所見分け方打つ手
量書き方は決まっていて、走らせると上限に当たる1 件あたりの費用を測り、全体の桁を出す。存在の向きに書き換えられないかを見る。段を落とすなら下流が何倍になるかを数える
述べ方言明を書こうとすると、何を型にすべきか決まらない要る部品を列挙する。証明書に当たるものが在るかを見る。無ければ等級を分けて明記する
在庫grep で当たらない三つの基準で紙に残すかを決める。残すなら継ぎ目の場所を書く

三つとも、結論は「Lean に載らない」ではなく「この部分は別の等級である」です。等級を分けて書けば、結果は使えます。分けずに書くと、Lean の行が紙の行を保証しているように読めてしまいます。


次は 11 よくある罠——上の上限に当たったときの文面と、その読み方です。用語は 12 用語集。

改訂 2026-09-20:初版。