Primes and unique factorization#
Prime numbers are a major destination of the library, but they are not a primitive. Their useful theory rests on divisibility, order, induction, division, and gcd.
A first-order prime definition#
Writing \(d\mid p\) for its existential expansion, define
This factor-pair definition is stateable in Peano Lab now and is equivalent
over the naturals to the usual divisor formulation. A readable Prime p
surface form would be only a macro; the stored theorem and final checker target
contain the expanded quantifiers and multiplication equality.
The first concrete instance is already checked:
prime_two : ~(2 = 1) /\ forall a b. 2 = a * b -> a = 1 \/ b = 1
Its proof depends on two_large_factors_impossible; neither theorem adds a
trusted primality oracle or a primitive Prime atom.
The checked division layer now supplies constructive quotient-remainder
existence and uniqueness. The checked prime_divisor_eq_one_or_self theorem
says every divisor of a prime is one or the prime itself. The runtime also
contains euclid_prime_dvd_product: a prime dividing \(a b\) divides \(a\) or
\(b\). The complementary constructive search branch is now checked as well.
The checked constructive prime-search DAG#
The new milestone contains twelve entries. It is a dependency DAG rather than one linear proof:
factor_nonzero_left is an independently reusable product boundary lemma;
the current optimized proper_factor_lt certificate proves the needed
nonzero-factor subclaim locally instead of importing that whole certificate.
The exact admitted metrics are:
Checked theorem |
Constructive role |
Nodes/depth |
Cuts |
|---|---|---|---|
|
decide equality by nested induction |
48 / 20 |
0 |
|
decide whether a nonzero divisor divides a number by testing the unique remainder |
1,242 / 61 |
32 |
|
add the explicit zero-divisor case |
1,352 / 64 |
35 |
|
extend a bounded factor property across one new endpoint |
150 / 20 |
5 |
|
verify all bounded factor pairs or return a nontrivial pair |
1,925 / 69 |
56 |
|
instantiate bounded search at the number itself |
2,038 / 71 |
59 |
|
derive nonzeroness from the expanded prime formula |
49 / 11 |
2 |
|
decide the expanded prime formula, including zero and one |
2,194 / 73 |
64 |
|
refute a zero left factor of a nonzero product |
37 / 12 |
1 |
|
turn a nonunit cofactor into strict factor descent |
468 / 26 |
16 |
|
perform strong descent by ordinary induction on an explicit bound |
2,931 / 78 |
91 |
|
specialize that bound to the number itself |
2,977 / 80 |
94 |
In particular, the public endpoint proves, in fully expanded syntax, that
every \(n\ne0,1\) has a prime \(p\) and a witness \(k\) with \(n=pk\).
prime_divisor_exists_up_to does not invoke a polymorphic strong-induction
principle: its concrete motive is proved by ordinary induction on \(B\), and a
nontrivial factor is shown smaller before the induction hypothesis is used.
All twelve certificates check in the default intuitionistic kernel and contain
no DNE node. The successor client is now checked too. For any bound n,
prime_unbounded chooses a nonzero c divisible by every positive value at
most n, then takes a prime divisor p of S c. If p <= n, bounded common
divisibility gives p | c; together with p | S c, divides_remainder
gives p | 1, and divisor_one contradicts the prime premise p != 1.
Therefore n < p.
The exact certificate has 4,595 nodes, depth 82, 146 self-contained Cuts, and
SHA-256
8a44fb2d207c2a41684de6d6630674f3f3b951cd036f733b3dd493321099d37b.
It uses PA1–PA6 only, contains no DNE, and passes exact-statement replay, every
dependency-slot mutation, PA-leaf and authored-hypothesis mutations, and the
live use/exact/qed path. No factorial symbol, FTA dependency, or classical
existence extraction is hidden in the proof.
GCD without a gcd function#
Use the relational specification
to say that \(g\) divides \(a\) and \(b\), and every common divisor divides \(g\).
The checked API now provides symmetry, both divisibility projections, the
greatest-common-divisor projection, a constructor when one input divides the
other, is_gcd_unique, and constructive existence for every pair. The
bounded gcd_exists_up_to proof performs formula-specific Euclidean descent;
gcd_exists_relational specializes its bound to the second input. Both check
from the empty context. The uniqueness proof uses the checked
multiple_antisymm. The unit bridge proves mul_eq_one_components, divisors of one,
coprimality with one on both sides, and both directions between expanded
coprimality and IsGCD(1,a,b).
A balanced four-natural Bézout equation now supplies the checked bridge from gcd existence to Gauss cancellation without extending the kernel language. The runtime simultaneously constructs a relational gcd and balanced coefficients, specializes the result to coprime inputs, and proves
as gauss_coprime_cancel.
The exact checked statements, certificate metrics, bounded-induction construction, and balanced coefficient transport are developed in GCD and balanced Bézout construction.
The checked proof of Euclid’s lemma takes a relational gcd \(g\) of \(p\) and
\(a\). Since \(g\mid p\), prime_divisor_eq_one_or_self gives \(g=1\) or \(p=g\):
The first branch is Gauss cancellation; the second uses the gcd’s checked divisibility projection. This proof is constructive and its closed shared certificate has 5,382 nodes and depth 55.
Existence and uniqueness are different theorems#
The checked prime_or_composite, proper_factor_lt, and
prime_divisor_exists theorems supply the basic arithmetic descent needed for
factorization existence. The completed sorted route constructs a greatest
prime divisor, recursively factors the complementary quotient, and appends
that greatest factor while preserving sortedness. The completed uniqueness
route uses Euclid’s lemma to locate a prime in the other Product, matches the
sorted last factors, cancels the common nonzero prime, and continues by length.
That familiar paper proof quietly quantifies over finite products. An honest formal statement needs a representation and theorems for:
finite collections of natural numbers;
the product of a collection;
“every entry is prime”;
permutation or multiplicity equality;
deletion of a matched prime and product cancellation.
Peano Lab still has no primitive data interface for these objects. The project has two deliberately separate checked results:
a native conservative PA theorem using sorted Gödel β-coded factor sequences, a β-coded prefix-product trace, and extensional decoded-entry equality; and
an independently checked Lean companion proving the conventional finite-list theorem, including uniqueness up to permutation.
The companion is a mathematical cross-check, not Peano authority. The native β-coded existence, uniqueness, and combined FTA certificates are independently checked and synchronized in the 432-theorem runtime.
The representation milestone#
Three designs were compared:
Design |
Advantage |
Cost |
|---|---|---|
Gödel-coded sequences inside first-order arithmetic |
No kernel-language extension |
Long, opaque interfaces poorly suited to everyday reuse |
Conservative sequence predicate over encoded naturals |
Keeps the term grammar fixed |
Still requires a substantial coding library and bounded-index relations |
Reviewed finite-list/multiset layer |
Natural theorem statements and permutation reasoning |
Adds data syntax and needs a separate soundness review |
The selected Peano design is the first row: natural codes preserve the kernel unchanged. For codes \(b,c\), index \(i\), and value \(x\), define
The stored theorems keep this relation fully expanded and use the prefix
beta_at. The first checked decoding chain is:
Checked theorem |
Role |
Nodes/depth |
Cuts |
|---|---|---|---|
|
the modulus \(M(c,i)\) is a successor |
9 / 6 |
1 |
|
a value below \(M(c,i)\) decodes from itself with quotient zero |
62 / 16 |
2 |
|
every code and index has a bounded decoded residue |
479 / 31 |
15 |
|
two decoded residues at one code and index are equal |
1,121 / 59 |
30 |
|
package decoded-value totality and functionality |
1,625 / 61 |
47 |
|
project an |
358 / 27 |
11 |
|
recover |
1,839 / 66 |
53 |
All seven certificates are intuitionistic and contain no DNE. The forward bridge
forgets the bound component of At and feeds its quotient-remainder equation
to remainder_decomposition_to_mod_eq, proving the readable relation
At(b,c,i,x) -> b ≡ x (mod S ((S i) * c)).
Here At and the displayed congruence are documentation abbreviations. The
stored theorem contains only their existential PA expansions:
forall b c i x.
((exists h. h + S x = S ((S i) * c)) /\
exists q. b = q * S ((S i) * c) + x) ->
exists u v.
b + S ((S i) * c) * u = x + S ((S i) * c) * v
Conversely, beta_at_of_mod_eq_bound supplies the same strict bound and a
balanced-congruence witness to the checked reverse remainder bridge. Its exact
expanded statement is:
forall b c i x.
(exists h. h + S x = S ((S i) * c)) ->
(exists u v.
b + S ((S i) * c) * u = x + S ((S i) * c) * v) ->
((exists h. h + S x = S ((S i) * c)) /\
exists q. b = q * S ((S i) * c) + x)
Thus the native library now checks the bidirectional characterization
This establishes single-position decoding as a bounded congruence interface. By itself it does not construct one code realizing an arbitrary finite prefix; the later exclusive-prefix recoding layer does.
Constructive binary CRT and a conditional two-position β code#
The next checked tranche proves binary CRT without subtraction or classical
choice. In readable notation, binary_crt states
Balanced Bézout supplies four natural coefficients. bezout_mod_left and
bezout_mod_right extract the two modular coefficient identities, while
mod_eq_predecessor_cancel implements the needed negative contribution modulo
a successor without introducing subtraction. The resulting witness is an
ordinary natural-number term, and every final target remains fully expanded
first-order PA.
Checked theorem |
Role |
Nodes/depth |
Cuts |
|---|---|---|---|
|
select the right Bézout coefficient modulo the left modulus |
134 / 19 |
4 |
|
select the left Bézout coefficient modulo the right modulus |
50 / 16 |
1 |
|
realize predecessor cancellation modulo a successor |
315 / 25 |
9 |
|
combine arbitrary residues for nonzero coprime natural moduli |
5,044 / 51 |
144 |
|
expose bounded solutions as two directed remainder equations |
6,890 / 66 |
196 |
|
realize two bounded β values in one code |
6,941 / 69 |
201 |
|
prove \(M(c,i)\) coprime to the shared base \(c\) |
874 / 30 |
24 |
|
force a common modulus divisor into \(\mathit{gap}\,c\) |
855 / 30 |
24 |
|
discharge pairwise coprimality from \(j=i+\mathit{gap}\) and \(\mathit{gap}\mid c\) |
6,007 / 56 |
175 |
|
realize the two beta values under that gap condition |
12,980 / 71 |
378 |
|
derive ordered bounded-modulus coprimality from one common-multiple invariant |
6,227 / 57 |
181 |
|
orient every distinct bounded pair and prove its moduli coprime |
6,348 / 59 |
183 |
|
choose one nonzero base for a pairwise-coprime bounded family |
7,019 / 61 |
207 |
|
fold pairwise coprimality into an accumulated product |
3,975 / 53 |
115 |
|
symmetric product-coprimality closure |
4,017 / 54 |
117 |
|
descend an accumulated-modulus congruence to a divisor modulus |
157 / 23 |
3 |
|
preserve every old divisor-modulus congruence and add one new congruence |
5,501 / 52 |
156 |
|
expose the newly multiplied right factor as a divisor |
229 / 25 |
7 |
|
preserve nonzero, prefix-divisibility, and future-coprimality product invariants |
11,174 / 69 |
330 |
|
extend congruence to the next value decoded from the supplied code |
7,352 / 64 |
213 |
|
combine both successor invariants |
18,613 / 70 |
545 |
|
carry the four-part prefix invariant by ordinary induction |
25,496 / 78 |
752 |
|
project full-bound congruences for residues already decoded from the input code |
25,545 / 79 |
755 |
The bounded client strengthens the readable conclusion to
Specializing the moduli to \(M(c,i)\) and \(M(c,j)\) then gives
The coprimality hypothesis in this formula cannot be discharged unconditionally. For example, \(c=1\) gives
so the beta-modulus family is not pairwise coprime for an arbitrary shared \(c\). The checked replacement carries the honest sufficient conditions
A common divisor of the two moduli divides \(\mathit{gap}\,c\); each modulus is
coprime to \(c\); Gauss cancellation therefore makes that common divisor divide
the gap. Since the gap divides \(c\), it must be one. The wrapper
binary_crt_beta_pair_of_gap_dvd feeds this result to the original binary
client.
The same checkpoint adds the finite common-multiple surrogate needed to make many gap hypotheses available from one parameter:
Checked theorem |
Role |
Nodes/depth |
Cuts |
|---|---|---|---|
|
extend a nonzero common multiple across the next positive endpoint |
483 / 29 |
15 |
|
construct a nonzero \(c\) divisible by every positive natural at most \(B\) |
640 / 30 |
22 |
The next three checked theorems now expose every required bounded gap and
prove that all distinct moduli in the prefix are pairwise coprime. Product
coprimality, modulus descent, and binary_crt_fold_step then check the
algebraic extension invariant: one new CRT solution preserves every old
congruence whose modulus divides the accumulated product. The six newest
theorems now iterate that step by ordinary induction. For every \(k\le N\),
bounded_beta_crt_prefix_invariant constructs \(P,z\) such that \(P\) is nonzero,
every prefix beta modulus divides \(P\), \(z\) is congruent to each prefix value
already decoded from the supplied code \(b\), and \(P\) is coprime to every future
bounded beta modulus.
Its wrapper bounded_beta_crt_for_existing_code is intentionally weaker than
finite-prefix recoding. It projects the congruence component at \(k=N\), but all
residues in its premise already come from \(b\); extensionally, choosing \(z=b\)
proves the same conclusion. The later checked chain adds the missing exclusive
recoding invariant, beta_prefix_extend, exact prefix-product trace
construction, Product functionality, prefix transport, and canonical append.
A second code stores the prefix products, beginning at one and multiplying by
the decoded factor at each step. AllPrime expands the factor-pair prime
formula at every bounded index, and Sorted makes the representation
canonical by decoded values. Codes themselves are never equated because one
finite prefix can have more than one β-code.
The selected formula schemas and completed dependency spine are recorded in
research/arithmetic-library/finite-factorization-encoding.md.
The checked native PA theorem#
The final native theorem combines two independently useful endpoints:
prime_factorization_existence: every nonzero natural has a sorted β-coded prime prefix whose exact β-coded Product is the natural;prime_factorization_uniqueness: any two such canonical representations of the same natural have equal lengths and equal decoded entries at every bounded position.
The metrics at this integration checkpoint are:
Endpoint |
Nodes |
Depth |
Cuts |
|---|---|---|---|
existence |
43,973 |
98 |
1,328 |
uniqueness |
29,789 |
82 |
854 |
combined FTA |
73,767 |
99 |
2,184 |
The exact FTA certificate SHA-256 is
fd978f59bf3b0aa7b6c9ec1bc92ab5e7bbf949c25309173e098bd8f3b8de0958.
It passes independent empty-context checking and the full
prove/use/exact/QED path under the current 500,000-occurrence,
100,000-object, depth-256 cap.
Dependency, hypothesis, PA-rule, and semantic mutation audits are live. The
certificate uses only PA1–PA6 and induction and contains no DNE.
This is not raw-code uniqueness. Multiple β-code pairs can decode the same finite prefix, so the theorem intentionally compares decoded entries. Nor does it add a primitive list, multiset, Product function, or Prime predicate: all relations are fully expanded before the kernel sees them.
The checked Lean theorem#
The separate artifacts/lean-fta/FTA.lean project now proves:
theorem fundamental_theorem_of_arithmetic (n : ℕ) (hn : n ≠ 0) :
∃ factors : List ℕ,
IsPrimeFactorization n factors ∧
∀ other : List ℕ,
IsPrimeFactorization n other → other.Perm factors
The witness is n.primeFactorsList. Existence checks that its entries are
prime and its product is \(n\); uniqueness proves that any other prime list with
product \(n\) is a permutation of it. For \(n=1\), the witness is the empty list.
The project pins Lean 4.23.0 and Mathlib commit
37df177aaa770670452312393d4e84aaad56e7b6. Its audit rejects sorryAx and
requires exactly the declared standard axioms propext, Classical.choice,
and Quot.sound. This makes the dependency footprint visible rather than
calling a library import “axiom-free.”
What “include FTA” means in this release#
This integration checkpoint keeps two deliberately separate FTA tracks:
the Lean companion is a checked existence-and-uniqueness proof up to permutation, with no admission;
the conservative native Peano β-coded certificate is checked from the empty context;
source curricula document the dependency route and provenance;
no external theorem is smuggled into
pa libas a Peano certificate.
The native chain now continues beyond the early existing-code wrapper through genuine finite-prefix recoding, Product traces, greatest-prime descent, canonical existence, last-factor matching, cancellation, and extensional uniqueness. The exact combined certificate is therefore a checked native PA FTA at this integration checkpoint. Runtime integration is complete.
The boundary remains explicit: there is no primitive list type and no theorem
that distinct raw β codes must be equal. prime_unbounded is checked
independently of the factorization theorem.
Conventional integer-coefficient Bézout is unavailable in the natural-only
term language; the checked four-natural balanced relation is the native
substitute.