Wenda Li
University of Edinburgh
ICML 2026 Tutorial — Proving Theorems with Lean and Machine Learning

With support from

Part I, in one line: Rémy showed you Lean as a proof language — how humans write trusted ML-theory proofs.
Part II flips the arrow: machines writing the proofs.
The game of theorem proving: history & methodology
Success stories
Overview of approaches & benchmarks
Limitations & the near future
Demonstration + wrap-up
Verified reward: theorem proving is the rare domain with a perfect, cheap, automatic reward signal — a paradise for RL and test-time search.
Frontier capability benchmark: IMO gold (2025), Putnam 12/12, first research-level results — progress is fast and measurable.
You can use it today: AI copilots for formalising your own ML theory.
Could your next ML theory paper come with a machine-checked appendix?
The "AlphaGo for mathematics" framing — with a twist:
the action space is infinite, and the "board" is a proof state (or state of Lean).

Takeaway: ML for theorem proving is older than the LLM era — but the LLM era changed everything.
Premise selection: from a 200k-theorem library (Mathlib), retrieve the lemmas relevant to the current goal — k-NN → DeepMath → LeanHammer · LeanSearch · Moogle.
Tactic selection / step prediction: given a proof state, predict the next tactic and its arguments.
These two tasks are the interfaces where ML plugs into an interactive prover.

Sledgehammer pipeline — from Magnushammer (Mikuła et al., 2023)

HOList / DeepHOL — Bansal et al. (ICML 2019)
A proof assistant is a game engine — state: local context + goal(s); action: a tactic; terminal reward: kernel accepts ⇒ 1, else 0 — no false positives.

Yang et al., "Formal Mathematical Reasoning: A New Frontier in AI" (2024)
theorem zero_add (n : Nat) : 0 + n = n := byn:ℕ⊢ 0 + n = n
induction n⊢ 0 + 0 = 0n✝:ℕa✝:0 + n✝ = n✝⊢ 0 + (n✝ + 1) = n✝ + 1
case zero =>⊢ 0 + 0 = 0 rflAll goals completed! 🐙
case succ n' ih =>n':ℕih:0 + n✝ = n✝⊢ 0 + (n✝ + 1) = n✝ + 1 simp only [Nat.add_succ, ih]All goals completed! 🐙
Everything in §3 is an instance of this loop with different design choices.
miniF2F pass rate:
≈29% (GPT-f/PACT, 2021) → 99.6% (Seed-Prover, Jul 2025)
— with AlphaProof scoring perfect on miniF2F-valid along the way (test-time RL; Nature 2025).
The yardstick of the field for four years — now saturated.
What it did:
4/6 problems, 28/42 — one point below the gold cutoff.
Solved P1, P2, and P6 (hardest; only 5 human contestants solved it); AlphaGeometry 2 solved P4 in 19 s; both combinatorics problems unsolved.
How:
AlphaZero-style RL over Lean; ~1M informal problems autoformalised into ~80–100M formal statements as the RL curriculum.
Test-time RL: generating and proving variants of the target problem — minutes for one problem, up to three days for the others.
Honest caveats: days per problem (humans get 2×4.5 h); statements manually formalised by humans. Peer-reviewed: Nature, Nov 2025.
Aristotle (Harmonic): gold-level — P1–P5 with Lean-verified proofs (35/42); announced after honouring IMO's embargo. P6 unsolved by every AI system.
Seed-Prover (ByteDance): official, IMO-confirmed 30/42 = silver within its 3-day window; lemma-style whole-proof generation.
Informal golds, both 35/42: Gemini Deep Think (within the 4.5 h limit, graded by IMO coordinators) and an OpenAI experimental model (self-graded, not IMO-certified).
Why formal matters — and the fine print: formalised inputs, extended compute windows, undocumented handling of "determine the answer" parts. Trust the proofs, interrogate the conditions.
IMO 2026 is July 15–16 in Shanghai — right around this tutorial. Expect fresh results.
Live Putnam 2025 (Dec 6, 2025), all Lean-verified after the fact:
AxiomProver: 12/12 — 8 within the exam window, 4 over the following days.
Numina-Lean-Agent (open-source harness): 12/12 — Claude Code + Lean MCP, benchmarked after the exam.
Seed-Prover 1.5: 11/12 within 9 h. Aristotle: 10/12 — via the consumer product, run by an outside user.
Informal reference (MathArena, graded blind by official Putnam graders): best agentic model 103/120 — top-3-human territory.
Competition math has effectively fallen — in about 18 months.
The unit-distance problem falls (May 20, 2026): an internal OpenAI reasoning model
produced an original construction disproving Erdős's ~80-year-old planar
unit-distance conjecture — point sets with n^{1+\delta} unit distances.
The construction imports class field towers and Golod–Shafarevich — a genuinely
different corner of mathematics; within days, Will Sawin refined it to an
explicit exponent \delta \approx 0.014.
The Lean follow-up — verification catching up to discovery:
Aleph Prover: a 33,087-line Lean 4 formalisation 8 days after the announcement — modulo two classical results taken as trusted assumptions.
Parallel community + AI effort on the Lean Zulip: a fully-from-the-axioms formalisation, still in progress as of late June.
An AI system found the mathematics; formal proof is how we trust it at this speed.
Sphere packing in dimensions 8 & 24 (Math Inc., Dec 2025): the autoformalisation agent Gauss, with the existing project team, finished the Lean formalisation of Viazovska's Fields-Medal proofs — dim 8 in 5 days, dim 24 in ~2 more weeks. The human team had estimated ~6 months for dim 8 alone.
De Giorgi–Nash–Moser theory (Armstrong & Kempe, Apr 2026): a central chapter of modern PDE regularity theory — ~56,000 lines of Lean in about two weeks, with LLM agents writing all the Lean ("no human hand touched the Lean files").
Quantitative stochastic homogenisation (Armstrong & Kuusi, Jun 2026): the same workflow applied to their own current research paper — formalisation keeping pace with the research frontier.
Honest framing: the mathematics + proof architecture came from humans; AI removed the formalisation cost barrier (months → days).
The same recipe is spilling into program verification — proving code correct.
lean-zip (Kim Morrison, 2026) — a fully verified DEFLATE / gzip / ZIP
codec in Lean 4, with inflate (deflate data) = ok data proved for every input:
~32,000 lines, 1,100+ theorems, zero sorrys.
The kicker: implementation and proofs written almost entirely by loosely-supervised AI agents working from a plan document — long-horizon agentic formalisation, not a single prover call.
And it's practical: 2–3× faster than OCaml's decompress, within ~2× of zlib.
A field organising around this: Software Verification in Lean 2026 (INRIA Paris, Apr 2026) — Lean automation (de Moura), verified SymCrypt, post-quantum crypto & TLS 1.3, specification quality.
One proving engine, two frontiers: research mathematics and trustworthy real-world software — advancing together.
Three ingredients, mapping back to the core loop:
Verified reward at scale — Lean as an RL environment; no reward hacking on the final answer.
Autoformalisation closing the data gap — AlphaProof's ~1M informal → ~80–100M formal curriculum; Lean Workbook's 57k contest problems; Herald's 580k statement pairs.
Test-time compute — search, variants, lemma trees, days of thinking.
Let's open the hood and organise the design space.
training ↓ · interaction →
stepwise / subgoal-level
whole-proof
repository-level
trained (RL / expert iteration / SFT)
AlphaProof · HTPS · ABEL · InternLM-StepProver · BFS-Prover · DeepSeek-Prover-V1.5 · GPT-f · ReProver (LeanDojo)
Kimina-Prover · Goedel-Prover-V2 · DeepSeek-Prover-V2 · Seed-Prover · Baldur · Pythagoras-Prover · STP
Seed-Prover 1.5 · Leanstral 1.5 · Aristotle†
training-free / agentic
LLM + Lean REPL / MCP · Hilbert · Delta Prover
Draft-Sketch-Prove · LEGO-Prover
Numina-Lean-Agent · Claude / Codex + lake build
† Aristotle: per its paper, a tactic-level prover (MCGS + expert iteration) inside an agentic informal-lemma loop; it now clearly works with repositories, but that part is not in the paper.
The AlphaZero recipe for proofs:
Policy + value networks over proof states;
Expert iteration on found proofs;
Curriculum from easy to hard.
Examples: AlphaProof, HTPS, ABEL, InternLM-StepProver.
Pros: dense feedback, principled search.
Cons: prover-in-the-loop is slow; value estimation is hard; engineering-heavy.
A GPT-f training example (Metamath):
{
"proof_label": "unidmrn",
"goal": "[[ ]] |- U. U. ‘’ A
= ( dom A u. ran A )",
"proof_step": "[[ |- A = B |- C = B ]]
|- A = C \\
{{ A : U. U. ‘’ A }} \\
{{ B : ( ran ‘’ A u. dom ‘’ A ) }} \\
{{ C : ( dom A u. ran A ) }}",
"proof_step_hash": "37yZVNorgF8=",
"parent_hash": ["n4Kl7judEN4="]
}
HTPS — MCTS over proof hypertrees: selection / expansion / back-propagation.

AlphaProof — the AlphaZero recipe at scale: autoformalised curriculum + search.

The paradigm: treat the entire proof as a sequence — sample complete proofs, check with Lean, resample or repair on failure. Chain-of-thought / LRM reasoning made this viable: informal sketch interleaved with formal output.
Stepwise: fine-grained feedback, expensive prover interaction
Whole-proof: cheap parallel sampling, coarse feedback
The 2025 default: RL fine-tuning of reasoning models to emit complete Lean proofs.
Kimina-Prover: 80.7% miniF2F preview → 92.2% with test-time search.
DeepSeek-Prover-V2 (671B): 88.9%; subgoal decomposition.
Goedel-Prover-V2: 90.4% with self-correction at only 32B — an 8B variant matches the 671B DeepSeek.
Key tricks: informal CoT before the formal proof; subgoal decomposition; sample-and-repair / self-correction loops.
Reasoning-style generation + RL: informal reasoning blocks interleaved with Lean snippets; RL policy iteration against a Lean server.

Test-time scaling: pass rate grows with sample budget and model size.

IMO 1962 P2 — "find all x with √(3−x) − √(x+1) > 1/2" (answer: −1 ≤ x < 1 − √31/8):
BFS-Prover (Approach 1) — a bare search trace; kernel-checked when found, on a 2025 Mathlib (it no longer replays):
theorem imo_1962_p2 (x : ℝ) (h₀ : 0 ≤ 3 - x) (h₁ : 0 ≤ x + 1)
(h₂ : 1 / 2 < Real.sqrt (3 - x) - Real.sqrt (x + 1)) :
-1 ≤ x ∧ x < 1 - Real.sqrt 31 / 8 := by
constructor
linarith
rw [← sub_pos]
field_simp [Real.sqrt_lt] at h₂ ⊢
apply lt_of_le_of_lt
rw [mul_comm]
rw [sub_eq_add_neg]
apply lt_of_le_of_lt
rw [← lt_sub_iff_add_lt]
ring_nf
rw [← lt_sub_iff_add_lt]
linarith [Real.sq_sqrt (by linarith : 0 ≤ 1 + x)]
rw [Real.sqrt_lt (by norm_num)]
rw [Real.sqrt_lt] <;> nlinarith
norm_num at this
Kimina-Prover (Approach 2) — one pass:
a have chain, every leaf an nlinarith with hand-fed hints:
theorem imo_1962_p2 (x : ℝ) (h₀ : 0 ≤ 3 - x) (h₁ : 0 ≤ x + 1)
(h₂ : 1 / 2 < Real.sqrt (3 - x) - Real.sqrt (x + 1)) :
-1 ≤ x ∧ x < 1 - Real.sqrt 31 / 8 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
have h3 : -1 ≤ x := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarithAll goals completed! 🐙
have h4 : Real.sqrt (3 - x) - Real.sqrt (x + 1) > 1 / 2 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 linarithAll goals completed! 🐙
have h5 : Real.sqrt (x + 1) ≥ 0 := Real.sqrt_nonneg (x + 1)x:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0⊢ -1 ≤ x ∧ x < 1 - √31 / 8
have h6 : (7 / 4 - 2 * x) > Real.sqrt (x + 1) := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarith [Real.sq_sqrt (show (0 : ℝ) ≤ 3 - x byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 linarithAll goals completed! 🐙),
Real.sq_sqrt (show (0 : ℝ) ≤ x + 1 byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 linarithAll goals completed! 🐙),
Real.sqrt_nonneg (3 - x), Real.sqrt_nonneg (x + 1)]
have h7 : (7 / 4 - 2 * x) ^ 2 > (Real.sqrt (x + 1)) ^ 2 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarith [h6, Real.sqrt_nonneg (x + 1)]All goals completed! 🐙
have h8 : (7 / 4 - 2 * x) ^ 2 > x + 1 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
have h10 : (Real.sqrt (x + 1)) ^ 2 = x + 1 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
rw [Real.sq_sqrt]x:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2⊢ 0 ≤ x + 1
linarithAll goals completed! 🐙
nlinarith [h7, h10]All goals completed! 🐙
have h9 : 64 * x ^ 2 - 128 * x + 33 > 0 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarith [h8]All goals completed! 🐙
have h10 : x < 1 - Real.sqrt 31 / 8 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
by_contra hxx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2h8:(7 / 4 - 2 * x) ^ 2 > x + 1h9:64 * x ^ 2 - 128 * x + 33 > 0hx:¬x < 1 - √31 / 8⊢ False
push_neg at hxx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2h8:(7 / 4 - 2 * x) ^ 2 > x + 1h9:64 * x ^ 2 - 128 * x + 33 > 0hx:1 - √31 / 8 ≤ x⊢ False`push_neg` has been deprecated. Prefer using `push Not` instead.
If you'd rather continue using `push_neg` in your project, you can implement it as follows:
```
open Lean.Parser.Tactic in
macro "push_neg" cfg:optConfig loc:(location)? : tactic =>
`(tactic| push $cfg:optConfig Not $[$loc]?)
```
have h12 : Real.sqrt 31 > 0 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
apply Real.sqrt_pos.mprx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2h8:(7 / 4 - 2 * x) ^ 2 > x + 1h9:64 * x ^ 2 - 128 * x + 33 > 0hx:1 - √31 / 8 ≤ x⊢ 0 < 31
norm_numAll goals completed! 🐙
nlinarith [sq_nonneg (x - (1 - Real.sqrt 31 / 8)), sq_nonneg (Real.sqrt 31),
Real.sq_sqrt (show (0 : ℝ) ≤ 31 byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 norm_numAll goals completed! 🐙), h12]
exact ⟨h3, h10⟩All goals completed! 🐙
One mechanism, two timescales — build a pool of intermediate lemmas and reuse them:
Within a single problem (test-time / lemma-style): Seed-Prover's conjecture/lemma pool with iterative refinement — training-style compute spent on one target at inference time.
Across problems (library learning & self-play): STP's conjecturer ↔ prover self-play; LEGO-Prover's skill library; retrieval-augmented proving (ReProver).
Unifying point: it is literally the same object on both sides — mathematics is cumulative, and reuse makes per-problem proving compound instead of restarting every time.
LEGO-Prover's growing skill library:

Cost honesty: the test-time / self-play end is the most expensive corner of the design space.
Across problems — STP: conjecturer ↔ prover self-play:

Within a problem — Seed-Prover's lemma-style refinement:

As base LLMs got stronger, "no fine-tuning" became competitive:
Delta Prover: decomposition + iterative reflection — 95.9% miniF2F with an off-the-shelf model.
Hilbert (Apple): recursive informal-reasoning + formal-proof construction — 70% PutnamBench (SOTA at release, Sep 2025; since surpassed).
Agentic scaffolds: Numina-Lean-Agent (Claude Code + Lean MCP), Aristotle-as-product, general LLM + Lean REPL tool use.
Discussion point: will scaffolds keep beating bespoke fine-tuning as frontier models improve? — the "bitter lesson at test time" question.
Hilbert — recursive decomposition: prover ↛ shallow solve ↛ subgoal decomposition, recurse.

Numina-Lean-Agent — a coding agent + Lean MCP tools: kernel feedback, retrieval, informal proving, discussion.

miniF2F (488 problems) saturated: 99.6%. PutnamBench (672 problems): 50% → 99.4% in under a year.
The frontier has moved to research-level problems, where numbers collapse:
FATE (research-level algebra): at release, best system 3% on FATE-H, 0% on FATE-X — while informal reasoning on the same problems scores 71%/33%. Formalisation, not reasoning, is the bottleneck.
Formal Conjectures (DeepMind): 2,615 statements incl. 1,029 open conjectures — contamination-free by construction.
A fast-growing benchmark family where the theorem is "this program meets its spec":
Verified code generation — model writes implementation + spec + proof:
CLEVER (161, HumanEval-derived): anti-shortcut curation — no test-case supervision or LLM-written specs; generated specs must be proved equivalent to hidden ground truth.
Verina (189): end-to-end from natural language — code, spec, and proof, each graded separately.
VeriSoftBench (≈500): repository-scale — whole verified Lean repos with dependencies, not isolated functions.
FVAPPS (4,715): the largest — competitive-programming tasks with
auto-generated specs as sorry theorems.
Proving verification conditions from deployed code:
NTP4VC (600 VCs, from 7.5k+ candidates): real kernel code (Linux, Contiki) through Why3/Frama-C, rendered in Lean, Isabelle, and Rocq.
Constructions differ widely — spec provenance, scale, granularity — so read the construction before the leaderboard.
training ↓ · interaction →
stepwise / subgoal-level
whole-proof
repository-level
trained (RL / expert iteration / SFT)
AlphaProof · HTPS · ABEL · InternLM-StepProver · BFS-Prover · DeepSeek-Prover-V1.5 · GPT-f · ReProver (LeanDojo)
Kimina-Prover · Goedel-Prover-V2 · DeepSeek-Prover-V2 · Seed-Prover · Baldur · Pythagoras-Prover · STP
Seed-Prover 1.5 · Leanstral 1.5 · Aristotle†
training-free / agentic
LLM + Lean REPL / MCP · Hilbert · Delta Prover
Draft-Sketch-Prove · LEGO-Prover
Numina-Lean-Agent · Claude / Codex + lake build
† Aristotle: per its paper, a tactic-level prover (MCGS + expert iteration) inside an agentic informal-lemma loop; it now clearly works with repositories, but that part is not in the paper.
The trend: tactic-level → repository-level. Academia mostly explores repo-level scaffolds; industry may attempt repo-level training.
Tactic/whole-proof training is still worth exploring: proving with extremely
small models (Pythagoras-4B beats the 671B DeepSeek), advanced tactic usage
(e.g. grind), canonical proof formats.
AI can now generate verified formal proofs by the thousand.
The frontier question is no longer "can a machine prove it?" but what humans still have to do:
Can we trust the proofs? (reward hacking)
Who supplies the definitions?
Can we read & maintain what the machine emits?
The reward is "the kernel accepts" — but an agent optimising hard finds cracks:
Gaming the harness, not the kernel — DeepSeek-Prover-V2: apply? inserts a
"synthetic sorry" whose warning gets suppressed by an unrelated error — a
pipeline that only checks "no errors, no sorry" accepts a bogus proof
(analysis: Thomas Zhu).
Extending the trusted base — native_decide pulls the Lean compiler + C++
runtime into the TCB; a past kernel soundness gap (since patched) failed to
flag it. #print axioms is the audit.
A "perfect verifier" is only as trustworthy as the harness around it — and an RL objective will find every gap.
How humans cope: #print axioms audits; Comparator & SafeVerify — sandboxed
re-checking against a trusted statement file; independent kernel implementations,
raced on lean-kernel-arena.
The prover proves the statement you write, not the one you mean — and Lean's
totality conventions ("junk values": x / 0 = 0, Real.sqrt (-1) = 0) make it easy
to state something else entirely, then cheerfully verify it.
The Riemann Hypothesis: Loeffler & Stoll's formal RH read "if s is not a
negative even integer and ζ(s) = 0 then Re(s) = 1/2." Buzzard & Ellenberg
asked: what about s = 1, ζ's pole? Totality hands riemannZeta 1 a junk
value — had it been 0, the statement would be trivially false, and not RH.
By luck it is ½(γ − log 4π) ≈ −0.98 — now certified by
riemannZeta_one_ne_zero. Whether the statement was RH hinged on an
unexamined junk value.
Everyday version: ∀ n m : ℕ, (n - m) + m = n silently drops n ≥ m
(truncated subtraction) — and vacuous misformalisations: contradictory
hypotheses prove anything.
Mathematics is largely about choosing definitions & abstractions — which current systems essentially can't. A machine-checked ✓ certifies the proof — never that you asked the right question.
Generation optimises for compile, not for library-quality:
LLM proofs are "less readable, modular, maintainable, and reusable than proofs in mature libraries" — systems "prioritize compilation above all else" → monolithic, ad-hoc scripts.
At library scale: a mergeable Mathlib lemma must be non-redundant, at the right generality, consistently named, in accepted style — "bulk-submitting AI proofs imposes substantial review burden."
Already real: ~2.3k open PRs awaiting review from ~30 maintainers — a human review budget that AI-generated volume overwhelms.
The community is drawing lines: Mathlib's policy — AI code without Lean-expert supervision "fails Mathlib's standards"; low-quality LLM PRs are closed summarily; repeat offenders lose PR and Zulip access.
Being worked on: proof-refactoring agents, style-aware rewards, lemma extraction; benchmarks that measure the gap — APE-Bench (best agent ≈47%, cost-capped pass@1).
Generating a proof ≠ producing maintainable mathematics — merely-correct is not mergeable.
The bar a contribution must meet — Euclid's infinitude of primes, as it lives
in Mathlib/Data/Nat/Prime/Infinite.lean:
/-- Euclid's theorem on the **infinitude of primes**.
Here given in the form: for every `n`, there exists a prime number `p ≥ n`. -/
theorem exists_infinite_primes (n : ℕ) : ∃ p, n ≤ p ∧ p.Prime :=
let p := minFac (n ! + 1)
have f1 : n ! + 1 ≠ 1 := Nat.ne_of_gt <| succ_lt_succ <| factorial_pos _
have pp : p.Prime := minFac_prime f1
have np : n ≤ p :=
le_of_not_ge fun h =>
have h₁ : p ∣ n ! := dvd_factorial (minFac_pos _) h
have h₂ : p ∣ 1 := (Nat.dvd_add_iff_right h₁).2 (minFac_dvd _)
pp.not_dvd_one h₂
⟨p, np, pp⟩
/-- A version of `Nat.exists_infinite_primes` using the `BddAbove` predicate. -/
theorem not_bddAbove_setOf_prime : ¬BddAbove { p | Nat.Prime p } := by⊢ ¬BddAbove {p | Nat.Prime p}
rw [not_bddAbove_iff]⊢ ∀ (x : ℕ), ∃ y ∈ {p | Nat.Prime p}, x < y
intro nn:ℕ⊢ ∃ y ∈ {p | Nat.Prime p}, n < y
obtain ⟨p, hi, hp⟩ := exists_infinite_primes n.succn:ℕp:ℕhi:n.succ ≤ php:Nat.Prime p⊢ ∃ y ∈ {p | Nat.Prime p}, n < y
exact ⟨p, hp, hi⟩All goals completed! 🐙
Documented; every step a named lemma (minFac_prime, dvd_factorial) —
names follow a grammar, so they can be guessed and found.
Ten readable lines on layers of API — then immediately reused, in the form downstream proofs want. Review and linters hold this bar.
IMO 1962 P2 — "find all x with √(3−x) − √(x+1) > 1/2" (answer: −1 ≤ x < 1 − √31/8):
BFS-Prover (Approach 1) — a bare search trace; kernel-checked when found, on a 2025 Mathlib (it no longer replays):
theorem imo_1962_p2 (x : ℝ) (h₀ : 0 ≤ 3 - x) (h₁ : 0 ≤ x + 1)
(h₂ : 1 / 2 < Real.sqrt (3 - x) - Real.sqrt (x + 1)) :
-1 ≤ x ∧ x < 1 - Real.sqrt 31 / 8 := by
constructor
linarith
rw [← sub_pos]
field_simp [Real.sqrt_lt] at h₂ ⊢
apply lt_of_le_of_lt
rw [mul_comm]
rw [sub_eq_add_neg]
apply lt_of_le_of_lt
rw [← lt_sub_iff_add_lt]
ring_nf
rw [← lt_sub_iff_add_lt]
linarith [Real.sq_sqrt (by linarith : 0 ≤ 1 + x)]
rw [Real.sqrt_lt (by norm_num)]
rw [Real.sqrt_lt] <;> nlinarith
norm_num at this
Kimina-Prover (Approach 2) — one pass:
a have chain, every leaf an nlinarith with hand-fed hints:
theorem imo_1962_p2 (x : ℝ) (h₀ : 0 ≤ 3 - x) (h₁ : 0 ≤ x + 1)
(h₂ : 1 / 2 < Real.sqrt (3 - x) - Real.sqrt (x + 1)) :
-1 ≤ x ∧ x < 1 - Real.sqrt 31 / 8 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
have h3 : -1 ≤ x := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarithAll goals completed! 🐙
have h4 : Real.sqrt (3 - x) - Real.sqrt (x + 1) > 1 / 2 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 linarithAll goals completed! 🐙
have h5 : Real.sqrt (x + 1) ≥ 0 := Real.sqrt_nonneg (x + 1)x:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0⊢ -1 ≤ x ∧ x < 1 - √31 / 8
have h6 : (7 / 4 - 2 * x) > Real.sqrt (x + 1) := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarith [Real.sq_sqrt (show (0 : ℝ) ≤ 3 - x byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 linarithAll goals completed! 🐙),
Real.sq_sqrt (show (0 : ℝ) ≤ x + 1 byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 linarithAll goals completed! 🐙),
Real.sqrt_nonneg (3 - x), Real.sqrt_nonneg (x + 1)]
have h7 : (7 / 4 - 2 * x) ^ 2 > (Real.sqrt (x + 1)) ^ 2 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarith [h6, Real.sqrt_nonneg (x + 1)]All goals completed! 🐙
have h8 : (7 / 4 - 2 * x) ^ 2 > x + 1 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
have h10 : (Real.sqrt (x + 1)) ^ 2 = x + 1 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
rw [Real.sq_sqrt]x:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2⊢ 0 ≤ x + 1
linarithAll goals completed! 🐙
nlinarith [h7, h10]All goals completed! 🐙
have h9 : 64 * x ^ 2 - 128 * x + 33 > 0 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
nlinarith [h8]All goals completed! 🐙
have h10 : x < 1 - Real.sqrt 31 / 8 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
by_contra hxx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2h8:(7 / 4 - 2 * x) ^ 2 > x + 1h9:64 * x ^ 2 - 128 * x + 33 > 0hx:¬x < 1 - √31 / 8⊢ False
push_neg at hxx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2h8:(7 / 4 - 2 * x) ^ 2 > x + 1h9:64 * x ^ 2 - 128 * x + 33 > 0hx:1 - √31 / 8 ≤ x⊢ False`push_neg` has been deprecated. Prefer using `push Not` instead.
If you'd rather continue using `push_neg` in your project, you can implement it as follows:
```
open Lean.Parser.Tactic in
macro "push_neg" cfg:optConfig loc:(location)? : tactic =>
`(tactic| push $cfg:optConfig Not $[$loc]?)
```
have h12 : Real.sqrt 31 > 0 := byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8
apply Real.sqrt_pos.mprx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)h3:-1 ≤ xh4:√(3 - x) - √(x + 1) > 1 / 2h5:√(x + 1) ≥ 0h6:7 / 4 - 2 * x > √(x + 1)h7:(7 / 4 - 2 * x) ^ 2 > √(x + 1) ^ 2h8:(7 / 4 - 2 * x) ^ 2 > x + 1h9:64 * x ^ 2 - 128 * x + 33 > 0hx:1 - √31 / 8 ≤ x⊢ 0 < 31
norm_numAll goals completed! 🐙
nlinarith [sq_nonneg (x - (1 - Real.sqrt 31 / 8)), sq_nonneg (Real.sqrt 31),
Real.sq_sqrt (show (0 : ℝ) ≤ 31 byx:ℝh₀:0 ≤ 3 - xh₁:0 ≤ x + 1h₂:1 / 2 < √(3 - x) - √(x + 1)⊢ -1 ≤ x ∧ x < 1 - √31 / 8 norm_numAll goals completed! 🐙), h12]
exact ⟨h3, h10⟩All goals completed! 🐙
Data augmentation for LLM training: verified synthetic proofs as high-quality reasoning data — formal math as a training ground that improves general reasoning (the reverse direction: TP for ML).
Large-scale autoformalisation: formalising the mathematical literature (textbooks → papers), enabling search & verification over mathematics as a corpus.
Formal-driven discovery: proof search as a discovery instrument, not just a checker — DeepMind agents (LLM + Lean feedback + AlphaProof) closed 9 open Erdős problems and 44 OEIS conjectures.
Two directions to watch:
Verified programs — e.g. WybeCoder (Meta): prove-as-you-generate — code, invariants, and proofs co-evolve during generation.
Verified ML — e.g. TorchLean (LeanDojo group): neural networks as first-class Lean objects, with one semantics for execution and proof.
Full-circle vision: ML theory proved in Lean (Part I) + AI proving assistance (Part II) ⇒ trustworthy-by-construction ML papers and systems.
The bottleneck is shifting from "can we prove it" to "what should we prove".
All demo material: github.com/Wenda302/ICML26_demo
Claude + lake build — a general coding agent proving inside a Lean repo.
Leanstral 1.5 (Mistral, open weights) — an agentic open prover.
Aristotle (commercial) — natural-language problem → verified Lean proof.
(Numina-Lean-Agent is just as viable — no time to demo it today.)
Claude / Codex + lake build — the generic, easiest entry: no scaffold at
all, works in any Lean repo; you pay for the model.
Leanstral 1.5 — open-weight model + open-source generic harness (vibe),
high-quality proofs; free right now.
Aristotle — closed-source but very easy to use and very strong on hard problems; appears optimised against a fixed Lean version.
Numina-Lean-Agent — open-source harness optimised for hard problems; bring your own agentic LLM (Claude, DeepSeek Pro 4) and expect customisation effort.
Theorem proving = a game with a perfect verifier — ideal for RL + search.
2024–26: IMO silver → gold → Putnam 12/12 → new mathematics: an Erdős conjecture disproved, open problems closed by formal proof search, and research-scale formalisations in days instead of months.
Design space: stepwise / whole-proof / repository-level × trained / training-free; benchmarks moving from puzzles to research & engineering.
The open gaps are human-facing: trust, definitions & formulation, maintainable proofs — likely not solved by scale alone.
You can use these tools on your own ML theory today.
All materials will be available from the tutorial website:
leanmachinelearning.org/icml-tutorial/
Thank you — questions?