Back to Research

The Axiom Profile of Mathlib

DOI: 10.5281/zenodo.20710920

Every theorem in a proof library rests on a measurable set of axioms, and a library's distribution of those sets — its axiom profile — is a fact about the mathematics, not an opinion about it. This paper measures the profile of the entire Mathlib library: 707,053 declarations at a pinned commit, each declaration's transitive axiom closure computed from a content-addressed archive of the elaborated terms, certified against the Lean kernel by full replay. The findings: 25.09% of Mathlib (177,395 declarations) depends on no axioms at all; only 23 distinct axiom profiles occur in the whole corpus, and 99.96% of declarations lie on the Boolean cube over three axioms — propositional extensionality, quotient soundness, and choice; the library contains zero incomplete proofs. Choice reaches half the corpus (50.84%), but its entry structure is extraordinarily narrow: every choice-dependent declaration reaches the axiom through a frontier of just 206 declarations that use it directly, and a structural counterfactual over the dependency graph shows 55.4% of all choice-dependence flowing through three generic classical-instance gateways jointly. The measurement separates two things the per-declaration view conflates: mathematics that needs choice, and mathematics that inherits choice from shared infrastructure. Every figure is recomputable from the query outputs deposited with this paper.

MathlibLean 4Formal VerificationAxiom ProfilesConstructive MathematicsAxiom of Choice

What an axiom profile is

A proof checked by a kernel is not unconditionally true; it is true relative to what it assumes. In Lean 4 (de Moura and Ullrich 2021) the assumptions are explicit objects — declarations introduced by the axiom keyword — and every theorem’s dependence on them is a computable fact: walk the proof term, collect every constant it references, close transitively, and keep the axioms. Lean ships this facility per declaration as #print axioms. The set that comes back is the declaration’s axiom profile: the exact, minimal description of the axioms the kernel was asked to take on faith.1

The profile is the legibility layer of formal mathematics. Two proofs of the same statement are not interchangeable if one consumes Classical.choice and the other does not — they license different uses, transfer to different foundations, and extract to different computational content. A library’s profile distribution is therefore a structural fact about the formalized library, in the same way a codebase’s dependency graph is a structural fact about the software. An axiom profile is a property of a formalization, not of a theorem in the abstract: the same result can carry a different profile under a different encoding or foundation, and that encoding-dependence is itself part of what the measurement exposes. What has been missing is the measurement at corpus scale: not this theorem’s assumptions but the whole library’s — the distribution of profiles, the reach of each axiom, and the topology of how the non-constructive principles actually enter.

This paper reports that measurement for Mathlib (the mathlib Community 2020), the largest unified library of formalized mathematics in existence: 707,053 declarations across 9,597 modules, at commit 8f9d9cff6bd728b17a24e163c9402775d9e6a365 on toolchain leanprover/lean4:v4.28.0. Three findings organize the results.

First, the profile space is tiny. A corpus of seven hundred thousand declarations could in principle exhibit thousands of distinct axiom combinations. Mathlib exhibits 23 — and 99.96% of the corpus lies on the Boolean cube over just three axioms: propext (propositional extensionality), Quot.sound (quotient soundness), and Classical.choice. All eight subsets of the three occur. The remainder is a thin compiler band plus the axiom sorryAx reaching exactly one declaration — itself. Mathlib contains zero incomplete proofs.

Second, a quarter of Mathlib is axiom-free. 177,395 declarations — 25.09% — depend on no axioms at all: fully constructive in the strictest sense the kernel can certify, computing under no assumptions whatsoever.

Third, choice is wide but narrow. Half the corpus (50.84%) reaches Classical.choice transitively — yet only 206 declarations in all of Mathlib reference the axiom directly, and a counterfactual analysis over the dependency graph shows the majority of all choice-dependence flowing through three generic classical-instance gateways. For most of the choice-dependent corpus, the axiom enters through shared infrastructure rather than through direct, local reference at the site itself.

The measurement substrate

A corpus-scale claim is only as good as the chain of custody behind it, so the substrate is stated before the results. Computing transitive axiom closure correctly at this scale is not automatic — a dependency graph that mis-traces how an axiom enters through shared infrastructure yields a materially different distribution — so the extraction below is certified against the kernel and cross-checked across independent implementations, not trusted to a single computation.

The measurement does not run over source text or over a live elaborator session. It runs over a content-addressed archive of the fully elaborated corpus: every declaration’s type and value terms stored as hash-consed nodes in a frozen binary grammar, 180.2 million unique nodes for the full library, with per-module manifests recording exactly which declarations each module contributes. The store’s identity is a single content hash; the figures below are deterministic functions of that hash and the manifest set, in the sense that re-running any query against the same store produces byte-identical reports.

The archive was certified faithful against the Lean kernel three ways before any query ran:

  • Kernel replay. Every declaration — all 707,053 — was decoded from the stored bytes alone and re-submitted to the kernel, which accepted it. The stored terms are not a transcription of the corpus; they are the corpus, as the kernel sees it.
  • Exact reconstruction. Every declaration re-emitted from the store matches the original elaborated form byte-exactly, down to binder names.
  • Block re-entry. Every inductive block re-enters the kernel from the store and the regenerated recursors match the stored ones.

The dependency and axiom-closure views — per-declaration direct references and per-declaration transitive axiom closure — were then derived from the store and certified by three independent implementations agreeing: a Python walk over the stored bytes; a Lean walk over the live kernel environment, byte-identical at a 167,447-declaration sample; and a third, name-graph recomputation that reproduces the axiom view from the dependency view exactly, on all 707,053 rows. The headline aggregations below are each additionally cross-derived by an independent second pass. Nothing reported here depends on trusting a single program.

The axiom profile

177,395 of 707,053 declarations — 25.09% of Mathlib — depend on no axioms at all.

There are only 23 distinct axiom profiles in the entire corpus. Eight are the subsets of {propext, Quot.sound, Classical.choice}, and all eight occur. Together those eight cover 706,794 declarations: 99.96% of Mathlib lives on the Boolean cube over three axioms. The remaining 259 declarations are a compiler band — lcProof and relatives, Lean.trustCompiler, Lean.ofReduceBool/ofReduceNat, fourteen profiles in all — plus sorryAx reaching exactly one declaration: itself. Mathlib contains zero sorried declarations.

The full distribution:

axiom profiledeclarationsshare
{Classical.choice, Quot.sound, propext}355,36150.26%
\varnothing (axiom-free)177,39525.09%
{Quot.sound, propext}82,33111.64%
{propext}78,89611.16%
{Quot.sound}8,7441.24%
{Classical.choice}2,5900.37%
{Classical.choice, propext}1,2080.17%
{Classical.choice, Quot.sound}2690.04%
compiler band (14 profiles)2580.04%
{sorryAx} (the axiom’s own row)1

And the per-axiom reach — declarations whose transitive closure contains the axiom:

axiomreachshare of corpus
propext517,88073.24%
Quot.sound446,77463.19%
Classical.choice359,47050.84%
lcProof2470.03%
Lean.trustCompiler5
each of ofReduceBool, ofReduceNat, Quot.lcInv, lcAny, lcCast, lcErased, lcUnreachable, lcVoid, sorryAx1

Reach counts every declaration whose transitive closure contains the axiom, including the few compiler-band declarations off the cube, so each reach slightly exceeds the sum of its cube vertices — choice 359,470 against 359,428, propext 517,880 against 517,796, Quot.sound 446,774 against 446,705. The gaps are exactly the compiler-band declarations whose closures also carry a core axiom.

Two readings of this table deserve emphasis. The first is hygiene: a corpus built by thousands of contributors over a decade exhibits twenty-three assumption-sets, no stray domain axioms in general circulation, and not one incomplete proof. This is a remarkable fact about Mathlib’s engineering discipline, and the measurement makes it checkable rather than reputational.

The second is structure: the three-axiom cube is not an arbitrary cutoff but the actual shape of the library. The fully classical vertex carries half the corpus (50.26%); the fully constructive vertex carries a quarter (25.09%); the remaining mass distributes over the partial combinations, dominated by the choice-free pairs. The constructive fraction of Mathlib is not a rounding error — it is the second-largest vertex of the cube.

Where choice enters

Half the corpus reaches Classical.choice. The per-declaration view stops there, and read naively it suggests that half of formalized mathematics needs the axiom of choice. The dependency graph supports a sharper question: how does the axiom reach all those declarations?

Only 206 declarations in all of Mathlib reference Classical.choice directly. Every one of the 359,470 choice-dependent declarations reaches the axiom through this frontier. The frontier is the complete set of entry points; everything else is inheritance.

The frontier’s internal structure is measured by a knockout: a structural counterfactual on the dependency graph. Knocking out a declaration hh means recomputing every axiom closure with hh‘s outgoing edges cut — the graph model of ”hh reproven without its current assumptions” — and reporting the freed set: declarations choice-dependent at baseline whose recomputed closure is choice-free.

The semantics must be stated precisely, because the numbers are easy to over-read. A knockout measures how much dependence flows through a declaration — infrastructure-mediated inheritance. It does not say the declaration is replaceable: Classical.propDecidable, the instance making every proposition classically decidable, is not provable without choice, and no rewrite will make it so. What the freed count says is how many declarations reach choice only through it.

Measured:

  • Classical.propDecidable has 8,049 direct dependents. Knocking it out frees 91,188 declarations — 25.4% of the entire choice-dependent set.
  • The top-three joint knockout — propDecidable, Classical.indefiniteDescription, Classical.ofNonempty — frees 199,160 declarations: 55.4% of all choice-dependence in Mathlib.
  • The joint effect is strongly superadditive: 199,160 jointly, versus 97,477 as the sum of the three individual knockouts. Dependence flows through the gateway triple jointly — cutting one reroutes through the others.

The reading: for the majority of the choice-dependent corpus, the axiom enters through generic classical instances — decidability supplied classically because it is convenient and uniform — rather than through direct, local reference to choice at the site of the theorem. The 206-declaration frontier, and within it the three-gateway structure, is the actual interface between Mathlib and the axiom of choice. A library that wanted to offer constructive variants would not face 359,470 declarations of work; it would face a frontier whose dominant members are already enumerated, with the impact of each candidate priced in advance by exactly this arithmetic.

The graph the measurement runs on

The dependency structure underneath these results is of independent interest, and three of its facts bear directly on how a corpus like this can be maintained and re-verified.

The name-level graph has 707,053 declarations and 18,419,389 direct-dependency edges (mean out-degree 26.1, median 17; median in-degree 1). Eq — propositional equality itself — is referenced directly by 430,768 declarations, 61% of the corpus, and its reverse dependency cone covers 617,711 declarations, 87.4% of Mathlib: the maximal blast radius any change to a foundational type could have.

The reverse-cone distribution is extremely heavy-tailed. In a deterministic structured sample of the corpus, half of all declarations are used, transitively, by at most 11 others, while the foundational hubs are used by hundreds of thousands. For maintaining a moving corpus the consequence is concrete: a change to a typical declaration invalidates almost nothing and is nearly free to re-verify, while the expensive tail is small and exactly enumerable in advance. Verification cost under drift is not uniform — it is priced per declaration by the graph, before any work is spent.

The longest dependency chain in Mathlib has depth 338, its summit in the completely-positive-maps layer of the C*-algebra tower; the mean depth is 52.2. And the module quotient of the graph — 9,597 modules, 474,559 cross-module edge classes — contains exactly one cycle, which turns out to be a finding rather than an error: Lean realizes certain auxiliary declarations lazily (equation lemmas, match auxiliaries, private realizations), and a realized auxiliary lands in whichever module happens to force it first. Two import-incomparable modules can therefore each hold realizations of a shared upstream definition that reference each other — here, Nat.factorial’s realizations, split across Mathlib.Data.List.Permutation and Mathlib.Data.Nat.Factorial.DoubleFactorial. Module membership records where a declaration’s winning realization landed, not a reference-locality boundary; tooling that assumes module-level acyclicity of declaration references will, at exactly one place in current Mathlib, be wrong.

Reproduction

Every figure above is recomputable from the query outputs deposited with this paper. The measurement is pinned to Mathlib commit 8f9d9cff6bd728b17a24e163c9402775d9e6a365 on toolchain leanprover/lean4:v4.28.0. The outputs are produced by extracting every declaration’s elaborated terms into a content-addressed store — certified against the Lean kernel as described above — and running three query passes over the derived views: the axiom profile, the choice-inheritance topology, and the dependency structure. The store is identified by the content hash bbc45318d876958ae2e7a21f12c1b33ca78b5cb621b40849f4b5d7b632cc8f26 over 180,211,645 nodes, and the deposited outputs are a deterministic function of it.

Availability

This paper and the certified query outputs its figures derive from are deposited together at Zenodo: https://doi.org/10.5281/zenodo.20710921. The deposit contains the per-declaration axiom-skeleton, choice-inheritance, and dependency-structure outputs, a record of the Mathlib commit, toolchain, and store identity that produced them, and a script that recomputes every headline figure in this paper from those outputs.

References

de Moura, Leonardo, and Sebastian Ullrich. 2021. “The Lean 4 Theorem Prover and Programming Language.” In Automated Deduction — CADE 28, Lecture Notes in Computer Science 12699, 625–635. Springer. https://doi.org/10.1007/978-3-030-79876-5_37

The mathlib Community. 2020. “The Lean Mathematical Library.” In Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), 367–381. ACM. https://doi.org/10.1145/3372885.3373824

Footnotes

  1. The kernel also grants commitments it never turns into a proof obligation — definitional eta, proof irrelevance, and the conversion rules by which it judges two terms equal. These are substantive (coherent type theories omit them) yet appear in no axiom profile, because the profile tracks dependencies and a definitional grant is never depended upon. That stratum — and the assumptions implicit in how a domain is encoded, which become definitions or theorems rather than axioms — is a distinct measurement, taken up in separate work.

Text of the version published 2026-06-16 (DOI: 10.5281/zenodo.20710921). The archival version of record is on Zenodo.