With the power of Humanize, we, the Humanfia team, have solved 670 of 672 problems on PutnamBench, using a fully agentic, YOLO-style approach. Every solution has been formally verified by Lean 4.
| Metric | Value |
|---|---|
| Benchmark | PutnamBench, all 672 formal statements |
| Verified proofs | 670 |
| Unresolved | 2 |
| Pass rate | 99.7% |
| Ranking | #1 on the offical leaderboard. |
| Verified? | Yes, all passed Lean 4 |
| Worker / reviewer model | gpt-5.5, reasoning effort xhigh |
| Lean | leanprover/lean4:v4.27.0, Mathlib a3a10db0 |
| Acceptance | Lean kernel + Comparator + AXLE, all required to agree |
This results has been verified by the putnambench team, and now ranks #1 on the offical leaderboard. A problem counts as solved only when the produced Lean file passes every gate
in Verification Method. Candidates that fail any gate are
retained for inspection but are never counted or labeled as proofs. The unresolved
IDs for a given run are written to unresolved.txt in that run's controller
directory.
This repository contains the exact solver, the pinned statements, the pinned toolchain, and the scripts to re-run the whole benchmark end to end. To check the result yourself, start with the AXLE API section directly below — it takes Python 3 and a network connection, nothing else.
The verified Lean files are published on Huggingface. Note that upon putnambench authors' request, we do NOT open source all solutions. Instead, we provide a preview of first 12 questions for review and release the whole solving pipeline. Feel free to eval and run if interested!
The fastest independent check is the AXLE verification API. It needs only
Python 3 and network access — no Lean, no Mathlib, no Comparator build, no
model calls, no API key. AXLE receives the proof together with the benchmark
statement, checks it in a clean Lean 4.27.0 environment, and returns Boolean
okay.
# 1. Get the published proofs.
git clone https://huggingface.co/datasets/humanfia-lab/putnambench-solution-preview
# 2. Write the pinned benchmark statements out of the packaged JSONL.
mkdir -p work/originals
python3 - <<'PY'
import json, pathlib
out = pathlib.Path("work/originals")
for line in pathlib.Path("inputs/putnam_bench.jsonl").read_text(encoding="utf-8").splitlines():
if line.strip():
record = json.loads(line)
(out / f"{record['problem_id']}.lean").write_text(
record["formal_statement"], encoding="utf-8"
)
PY
# 3. Verify a single proof.
python3 humanize/scripts/verify-putnambench-axle.py \
--originals-root work/originals \
--candidate putnam-bench-verified-and-code/Putnam-bench-verified/Putnam1962A2.lean
# 4. Verify every published proof, 50 candidates per invocation.
find putnam-bench-verified-and-code/Putnam-bench-verified -name '*.lean' -print0 \
| xargs -0 -n 50 sh -c '
args=""
for file in "$@"; do args="$args --candidate $file"; done
python3 humanize/scripts/verify-putnambench-axle.py \
--originals-root work/originals $args \
--output "work/axle-$(date -u +%s%N).json"
' shReading the result. The verifier exits 0 only when every candidate came
back okay: true, 1 when AXLE rejected a proof, and 2 on input or API
errors. The printed JSON carries all_okay and, per candidate, the problem,
status (correct / incorrect), the AXLE request_id, and SHA-256 hashes of
the candidate, the submitted content, and the original statement — so a third
party can confirm that what AXLE checked was exactly the published file against
the pinned benchmark statement.
Two notes so results are not misread:
- Candidate filenames must be
PutnamYYYYAN.leanorputnam_YYYY_aN.lean. That is how each proof is matched to its benchmark statement. formal_statement_solution_patched: trueis expected and sanctioned. It means the verifier replaced only the original<problem>_solution := sorrydeclaration with the candidate's concrete solution, so AXLE checks against a statement with no hole. The theorem itself is never modified.
This API check asks the least of a reader: it trusts nothing in this repository
except the benchmark statements, which are hash-pinned in
inputs/putnam_bench.jsonl. For the stronger, fully offline check, continue
below.
The AXLE check above needs no Lean. Everything below does. This project is pinned to Lean 4.27.0 and Mathlib v4.27.0.
Lean is installed through Elan, the Lean toolchain manager. On Ubuntu or Debian, first install the system packages needed by Elan, Lean, and the checker builds:
sudo apt-get update
sudo apt-get install -y curl git build-essential python3 jq ripgrep golang-goOn macOS, install the Xcode command-line tools instead:
xcode-select --installThen install Elan on either platform:
curl https://elan.lean-lang.org/elan-init.sh -sSf | sh
source "$HOME/.elan/env"Verify the installation. Entering the pinned project directory makes Elan download and select Lean 4.27.0 automatically:
(
cd inputs/math-flow-bench
lean --version
lake --version
)The Lean version should be 4.27.0. If elan, lean, or lake is not found,
open a new shell or run source "$HOME/.elan/env" again. A global
elan default is unnecessary because inputs/math-flow-bench/lean-toolchain
pins the version for this project. See the official Lean installation
guide for other platforms.
./reproduce.sh bootstrap reads your Elan home ($ELAN_HOME, else
$HOME/.elan), installs the pinned toolchain, fetches the Mathlib cache with
lake exe cache get so Mathlib is not compiled from source, and builds
Comparator, Lean4Export, and Landrun under work/. Elan must be installed
before that command; it fails with Elan home not found otherwise. The
Comparator gate additionally requires x86-64 Linux with Landlock, so gates 1-3
run anywhere Lean runs, while gate 4 is Linux-only.
AXLE is one of five gates. To reproduce all of them locally on the published files, build the pinned environment first:
./reproduce.sh bootstrapFor a proof of problem putnam_YYYY_aN, with <Module> its PutnamYYYYAN
form:
# Gate 1: no proof escapes.
rg -n '\b(sorry|admit|axiom|native_decide)\b' MathFlowBench/<Module>.lean
# Gate 2: the theorem statement and docstring are unchanged.
python3 inputs/math-flow-bench/scripts/validate-putnambench-output.py \
--problem putnam_YYYY_aN --putnambench-root source --candidate-root .
# Gate 3: it compiles in the pinned environment.
lake env lean MathFlowBench/<Module>.lean
# Gate 4: Comparator, restricted axioms, Lean kernel replay.
bash humanize/scripts/check-putnambench-comparator.sh comparator.jsonGate 1 must print nothing, and gate 4 must end with both Lean default kernel accepts the solution and Your solution is okay!. Gates 2-4 expect the
candidate at MathFlowBench/<Module>.lean inside a copy of
inputs/math-flow-bench whose .lake/packages points at the bootstrapped
work/math-flow-bench/.lake/packages, with the benchmark statement at
source/lean4/src/putnam_YYYY_aN.lean (the same file work/originals already
holds) and a matching comparator.json. prepare_workspace in
humanize/scripts/run-failed-putnambench.sh is the exact layout the solver used
and generates that comparator.json.
To re-verify proofs that this repository produced itself, run the batch auditor instead — see Independently re-verify the proofs.
Verification is deliberately redundant: the model that writes a proof never decides whether it is accepted. Acceptance requires an independent Lean kernel replay, an independent statement-equivalence checker, and an independent external verifier service, all in agreement.
Each candidate must clear all of the following gates:
- Exact statement provenance. The problem's
formal_statementis extracted from the pinnedinputs/putnam_bench.jsonlby exactproblem_idmatch, and the workspace source file must match it byte-for-byte. - Statement preservation.
scripts/validate-putnambench-output.pyconfirms the theorem statement and docstring in the candidate are unchanged from the benchmark statement. Weakened or restated theorems are rejected. - No proof escapes. The candidate must contain no
sorry,admit,axiom, ornative_decide.native_decideis rejected because it depends onLean.ofReduceBool/Lean.trustCompilerrather than the kernel. - Lean compilation.
lake env lean MathFlowBench/<Module>.leansucceeds against the pinned Lean 4.27.0 / Mathlib environment. - Comparator. The pinned
leanprover/comparatorbuild compares the candidate against a protectedComparatorChallenge.lean, verifies the theorem statement and any solution-definition hole, restricts axioms topropext,Quot.sound, andClassical.choice, and replays the proof through the Lean default kernel. The run must end with bothLean default kernel accepts the solutionandYour solution is okay!. Comparator, its config, the Lake files, and the wrapper are protected from worker edits; the run executes under real Landrun/Landlock sandboxing, not a stub. - AXLE. A separate reviewer process, which cannot edit the candidate, calls
https://axle.axiommath.ai/api/v1/verify_proofand must receive Booleanokay: trueagainst the JSONL-sourced statement. The reviewer's only permitted network call is this one. - Independent post-hoc audit.
humanize/scripts/audit-failed-putnambench-passes.shre-audits every terminal pass after the fact: it re-checks candidate and original hashes against the stored AXLE artifact, re-runs the statement validator and forbidden-marker scan, and recompiles the candidate from a clean canonical MathFlowBench build.
Isolation properties that make the result meaningful:
- The solver runs in a separate sanitized Git workspace per problem, with separate worker and reviewer Codex homes.
- Existing PutnamBench solutions are never mounted into either model's namespace.
- Worker tool shells have network syscalls blocked by seccomp — no web search, no solution lookup, no prior attempts, no session archives.
- Worker and reviewer are separate processes with separate prompts and separate state; the reviewer decides acceptance and cannot modify the proof.
Every run retains the full evidence trail: prompts, event streams, session paths, reviews, compilation logs, Comparator output, AXLE JSON responses and request IDs, file hashes, and terminal status files.
- x86-64 Linux with unprivileged user, mount, and network namespaces enabled, and a kernel able to run Landrun/Landlock.
- Bash, Git, curl, Python 3, jq, ripgrep, a C compiler, Go, the standard GNU tools, and Elan/Lake — see Install Lean 4.27.0.
- Codex CLI authenticated in
${CODEX_HOME:-$HOME/.codex}with access togpt-5.5. Bothauth.jsonandconfig.tomlmust be present; override the location with--base-codex-home PATH. - Outbound network access for dependency downloads, Codex calls, and reviewer
calls to
https://axle.axiommath.ai/api/v1/verify_proof. - Enough memory, disk, API quota, and process capacity for the chosen concurrency.
./reproduce.sh checkThis verifies the packaged hashes against MANIFEST.sha256, the pinned inputs,
and the source syntax.
./reproduce.sh bootstrapThis downloads and builds Lean 4.27.0, the pinned Mathlib, Comparator,
Lean4Export, and Landrun under work/. Nothing outside work/, runs/, and
all-runs/ is modified.
./solve-all-putnambench.sh --list-onlyThe selection is derived directly from inputs/putnam_bench.jsonl; the script
fails loudly if the file does not contain exactly 672 unique, well-formed
problem_id records with non-empty statements.
./solve-all-putnambench.sh --max-problems 2 --jobs 2 --campaigns 1To prepare and audit all 672 sanitized workspaces without making any model call:
./solve-all-putnambench.sh --prepare-only --jobs 64One campaign over all 672 problems:
./solve-all-putnambench.sh --jobs 64 --campaigns 1The published 670/672 figure comes from repeated campaigns, where each later campaign retries only the problems still unresolved:
./solve-all-putnambench.sh --jobs 64 --campaigns 3Use --campaigns 0 to keep launching fresh attempts for unresolved problems
until every selected problem passes:
./solve-all-putnambench.sh --jobs 64 --campaigns 0Unlimited campaigns can consume unbounded API quota and should be monitored. No
model can guarantee that every theorem will be solved. Exit code 0 means every
selected problem passed all gates; exit code 2 means a bounded campaign limit
was reached with problems still unresolved.
Historical configuration: gpt-5.5 at xhigh reasoning, 50-turn cap per problem
per campaign, four one-turn probe jobs, main concurrency 64, fallback concurrency
16 after rate limits, 7200-second worker and reviewer timeouts. Those are the
defaults; --jobs, --fallback-jobs, --max-turns, and the timeout flags
override them. See ./solve-all-putnambench.sh --help.
Outputs land under all-runs/. The controller directory
all-runs/<run-id>-controller/ contains:
SUMMARY.md— selected count, verified passes, unresolved count, campaigns completed, model, and turn cap;attempts.tsv— one row per attempt: campaign, problem, status, turn, candidate SHA-256, candidate path;initial.txtandselections/— the initial selection and each campaign's unresolved selection;unresolved.txt— the problem IDs that never passed.
Each campaign directory keeps its own prompts, event streams, proof candidates,
reviews, AXLE evidence, and Codex session index. Verified proof files are at
all-runs/<campaign-id>/workspaces/<job>/MathFlowBench/<Module>.lean.
WORKSPACE_ROOT="$PWD/work" \
OUT_ROOT="$PWD/all-runs" \
CANONICAL_ROOT="$PWD/work/math-flow-bench" \
bash humanize/scripts/audit-failed-putnambench-passes.shThis recompiles each passed candidate from the canonical built environment,
re-runs the statement validator and forbidden-marker scan, and re-checks the
stored AXLE evidence and hashes. Verified problems are recorded once in
<OUT_ROOT>/pass-audit/verified-passes.tsv; anything that fails re-verification
is written to audit-failures.tsv.
Model output is nondeterministic and service-side models can change, so proof text, turn counts, and wall-clock timing will differ between runs. A rerun is methodologically faithful when it uses:
- the full 672-problem selection derived from the packaged JSONL;
- the byte-identical
formal_statementvalues; - the pinned Lean, Mathlib, Comparator, Lean4Export, and Landrun commits;
- the vendored Humanize orchestration in
humanize/; gpt-5.5atxhighreasoning;- the unmodified acceptance gates above.
The number solved is a property of the model and the campaign budget, not of the harness. What the harness guarantees is that whatever number it reports is backed by kernel-checked, statement-preserving, independently audited proofs.
- Formal statements:
inputs/putnam_bench.jsonl- SHA-256:
2b3a9c40a41b303e9bc7f60f69e3a457c7ee1e45e3e0c240a05a0054970de455 - 672 unique
problem_idrecords, verified at selection time
- SHA-256:
- Lean:
leanprover/lean4:v4.27.0 - Mathlib: tag
v4.27.0, commita3a10db0e9d66acbebf76c5e6a135066525ac900 - Comparator:
leanprover/comparator@099775bf2e6073fcb22aacd3a2809fdeac3fc84a - Lean4Export:
leanprover/lean4export@590dec59d93ab6becdf16fdd8aee5abbb99cb856 - Landrun:
Zouuup/landrun@5ed4a3db3a4ad930d577215c6b9abaa19df7f99f - Humanize upstream:
PolyArch/humanize; this package vendors the exact comparator-enabled source snapshot used by the runner.
MANIFEST.sha256 covers the immutable packaged source, inputs, and reference
evidence. Generated dependencies and new runs are written only under work/,
runs/, and all-runs/.
solve-all-putnambench.sh— the 672-problem entry point: selection, campaigns over unresolved problems, aggregate controller state.reproduce.sh— integrity check, pinned dependency bootstrap, workspace preparation.humanize/— the exact comparator-enabled Humanize source snapshot: worker and reviewer orchestration, gates, the AXLE verifier client (scripts/verify-putnambench-axle.py), and the independent pass auditor (scripts/audit-failed-putnambench-passes.sh).inputs/— the pinned JSONL statements, the pinned Lean project template, and the earlier problem-subset list.reference/— retained evidence from an earlier subset run, kept for provenance only; it is not the source of the 670/672 figure.provenance/— source revisions and package notes.work/,runs/,all-runs/— generated; created on demand.
No credentials, Codex session database, downloaded dependencies, or generated workspaces are included in this package.