@ceccec/millennium-solutions 0.1.1 → 9.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.zenodo.json +33 -9
- package/ACCOUNTING.md +7 -7
- package/AXIOMS.md +559 -0
- package/CHALLENGES.md +2181 -2479
- package/CITATION.cff +1 -1
- package/DEPLOY.md +2 -2
- package/DEVELOP.md +1 -1
- package/LICENSE +6 -5
- package/PRIOR-ART.md +149 -0
- package/README.md +221 -123
- package/SIGNATURE.md +2 -2
- package/TRIAL.md +69 -0
- package/WHITEPAPER.md +5 -5
- package/captain.md +2 -2
- package/compare.md +4 -4
- package/compute.md +9 -0
- package/dashboard.md +1 -1
- package/examples.md +5 -5
- package/forensic.md +67 -0
- package/guide.md +5 -5
- package/index.md +209 -139
- package/package.json +88 -9
- package/paper.md +7183 -0
- package/quantum.md +42 -0
- package/rights.md +39 -0
- package/solutions.md +7 -7
- package/speedup.md +4 -4
- package/src/0/index.ts +12 -2
- package/src/1/index.ts +1 -1
- package/src/2/frequency-scales.ts +13 -1
- package/src/2/index.ts +1 -1
- package/src/3/index.ts +1 -1
- package/src/4/index.ts +1 -1
- package/src/5/index.ts +1 -1
- package/src/6/index.ts +1 -1
- package/src/7/index.ts +1 -1
- package/src/9/funding.ts +2 -2
- package/src/api/gates.ts +117 -0
- package/src/api/index.ts +488 -0
- package/src/api/lanes.ts +81 -0
- package/src/demand/queries.json +1764 -0
- package/src/face/index.ts +100 -0
- package/src/html/index.ts +10 -0
- package/src/latex/index.ts +474 -0
- package/src/millennium/index.ts +53 -0
- package/src/proof/README.md +1 -1
- package/src/proof/address.lean +117 -0
- package/src/proof/coin.lean +148 -0
- package/src/proof/covered.json +9 -0
- package/src/proof/demand.lean +112 -0
- package/src/proof/demand2.lean +171 -0
- package/src/proof/demand3.lean +117 -0
- package/src/proof/discovered.json +10965 -1864
- package/src/proof/elementary.lean +393 -0
- package/src/proof/energy.lean +215 -0
- package/src/proof/families.lean +435 -0
- package/src/proof/fixtures/axiom-control.lean +39 -0
- package/src/proof/fnv.lean +99 -0
- package/src/proof/generated-theorems.json +207 -0
- package/src/proof/generated.lean +101 -0
- package/src/proof/imagined.lean +492 -0
- package/src/proof/index.lean +98 -18
- package/src/proof/index.ts +2 -2
- package/src/proof/involution.lean +90 -0
- package/src/proof/ledgerclaims.lean +84 -0
- package/src/proof/light.lean +135 -0
- package/src/proof/mechanical.lean +421 -0
- package/src/proof/merkaba.lean +89 -0
- package/src/proof/merkle.lean +132 -0
- package/src/proof/nim.lean +105 -0
- package/src/proof/phenomena.lean +90 -0
- package/src/proof/priorart.lean +189 -0
- package/src/proof/quantum.lean +161 -0
- package/src/proof/reach.lean +84 -0
- package/src/proof/recovered.lean +56 -0
- package/src/proof/reversal.lean +73 -0
- package/src/proof/rights.lean +157 -0
- package/src/proof/sequences.lean +105 -0
- package/src/proof/speed.lean +129 -0
- package/src/proof/split.lean +180 -0
- package/src/proof/theorems.lean +48 -1
- package/src/proof/trial-all.json +15260 -0
- package/src/proof/z9.lean +92 -0
- package/src/proof/z9plus.lean +208 -0
- package/src/proofs.lisp +3 -3
- package/src/prove/emit.ts +115 -0
- package/src/prove/index.ts +143 -0
- package/src/prove/translate.ts +638 -0
- package/src/publication/index.ts +363 -0
- package/src/quantum/field.ts +73 -0
- package/src/quantum/tree.ts +79 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// THE SEVEN, in problem order — the qualified outlet and the honest bound for each Clay problem this
|
|
2
|
+
// framework has a theorem ADJACENT to. This lived only in theorem/[key].paths.ts, so the collected paper had
|
|
3
|
+
// no way to say which of its theorems sit at the Millennium floor without the bounds being retyped into a
|
|
4
|
+
// second place — and a retyped bound is a bound that can drift from the one the theorem page shows.
|
|
5
|
+
//
|
|
6
|
+
// The `bound` is the load-bearing field. It states what the theorem actually establishes and, explicitly,
|
|
7
|
+
// what it does NOT: none of these is the conjecture, and provenHere = 0.
|
|
8
|
+
export const MILLENNIUM: Record<string, { problem: string; name: string; bound: string; outlet: string; outletName: string; outlet2?: string; outlet2Name?: string }> = {
|
|
9
|
+
riemann_reflection_and_heart: {
|
|
10
|
+
problem: 'Riemann Hypothesis',
|
|
11
|
+
name: "Riemann — the reflection's symmetry and its one computed heart",
|
|
12
|
+
bound: 'the functional-equation symmetry axis and its ½-analogue centre (the heart, computed as the reflection’s unique fixed point) — not where the ζ-zeros lie',
|
|
13
|
+
outlet: 'https://www.claymath.org/millennium/riemann-hypothesis/',
|
|
14
|
+
outletName: 'Clay Mathematics Institute — Riemann Hypothesis' },
|
|
15
|
+
p_vs_np_inverse_is_unique: {
|
|
16
|
+
problem: 'P versus NP',
|
|
17
|
+
name: 'P vs NP — a unique inverse, verification in one step',
|
|
18
|
+
bound: 'each unit has exactly one inverse (verify in one multiply), non-units none — a cheap-verification fact, not a separation of the classes',
|
|
19
|
+
outlet: 'https://www.claymath.org/millennium/p-vs-np/',
|
|
20
|
+
outletName: 'Clay Mathematics Institute — P vs NP' },
|
|
21
|
+
navier_stokes_flow_is_bounded: {
|
|
22
|
+
problem: 'Navier–Stokes Existence & Smoothness',
|
|
23
|
+
name: 'Navier–Stokes — the doubling flow is bounded for all time',
|
|
24
|
+
bound: 'every iterate stays inside a bounded 6-cycle forever (no blowup) — bounded evolution, not global existence & smoothness',
|
|
25
|
+
outlet: 'https://www.claymath.org/millennium/navier-stokes-equation/',
|
|
26
|
+
outletName: 'Clay Mathematics Institute — Navier–Stokes Equation' },
|
|
27
|
+
yang_mills_spectral_gap: {
|
|
28
|
+
problem: 'Yang–Mills Existence & Mass Gap',
|
|
29
|
+
name: 'Yang–Mills — a discrete spectral gap (order exactly 6)',
|
|
30
|
+
bound: 'the doubling has order exactly 6 — a discrete gap in the cyclic spectrum, not the Yang–Mills mass gap',
|
|
31
|
+
outlet: 'https://www.claymath.org/millennium/yang-mills-the-maths-gap/',
|
|
32
|
+
outletName: 'Clay Mathematics Institute — Yang–Mills & the Mass Gap' },
|
|
33
|
+
hodge_span_is_the_units: {
|
|
34
|
+
problem: 'Hodge Conjecture',
|
|
35
|
+
name: 'Hodge — the algebraic span equals the units',
|
|
36
|
+
bound: 'the doubling span (algebraic generation from 2) is exactly the units, non-units outside — generation/containment, not rational (p,p) ⇒ algebraic',
|
|
37
|
+
outlet: 'https://www.claymath.org/millennium/hodge-conjecture/',
|
|
38
|
+
outletName: 'Clay Mathematics Institute — Hodge Conjecture' },
|
|
39
|
+
birch_swinnerton_dyer_vanishing: {
|
|
40
|
+
problem: 'Birch and Swinnerton-Dyer Conjecture',
|
|
41
|
+
name: 'Birch–Swinnerton-Dyer — a computed vanishing mod 9',
|
|
42
|
+
bound: 'the orbit and the units both sum to 0 mod 9 (27 ≡ 0) — a digit-sum vanishing, not the rank ↔ order-of-vanishing-of-L correspondence',
|
|
43
|
+
outlet: 'https://www.claymath.org/millennium/birch-and-swinnerton-dyer-conjecture/',
|
|
44
|
+
outletName: 'Clay Mathematics Institute — Birch and Swinnerton-Dyer Conjecture' },
|
|
45
|
+
poincare_single_closed_loop: {
|
|
46
|
+
problem: 'Poincaré Conjecture (resolved)',
|
|
47
|
+
name: 'Poincaré — one closed loop, no holes',
|
|
48
|
+
bound: "the sequence closes into a single simple loop of six distinct steps — not the 3-sphere characterization; Poincaré is Perelman's theorem (2003), not proved here",
|
|
49
|
+
outlet: 'https://www.claymath.org/millennium/poincare-conjecture/',
|
|
50
|
+
outletName: 'Clay Mathematics Institute — Poincaré Conjecture',
|
|
51
|
+
outlet2: 'https://arxiv.org/abs/math/0211159',
|
|
52
|
+
outlet2Name: 'Perelman, G. — The entropy formula for the Ricci flow (arXiv:math/0211159) — the resolution' },
|
|
53
|
+
}
|
package/src/proof/README.md
CHANGED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import Fnv
|
|
2
|
+
set_option maxRecDepth 4000000
|
|
3
|
+
-- title: Addressing
|
|
4
|
+
-- wing: the address
|
|
5
|
+
-- prior_art: named
|
|
6
|
+
-- prior_art_domain: content addressing
|
|
7
|
+
-- prior_art_note: composes FNV-1a (Fowler, Noll, Vo, 1991) with the Merkle hash tree (Merkle, 1979)
|
|
8
|
+
-- The content-address itself, ported to Lean — toUuid, merge, the fold, and their properties.
|
|
9
|
+
-- Author: Tsvetan Rouschev · License: CC BY-NC-ND 4.0
|
|
10
|
+
--
|
|
11
|
+
-- Everything this deposit calls a receipt is toUuid(seed): four seeded FNV-1a passes, assembled into sixteen
|
|
12
|
+
-- bytes, with the version and variant nibbles forced. Until now those bytes existed only in TypeScript, and
|
|
13
|
+
-- every property the ledger claimed of them — determinism, distinctness, the order-independence of the fold —
|
|
14
|
+
-- was asserted by a test that ran once. Here they are propositions the kernel checks.
|
|
15
|
+
--
|
|
16
|
+
-- A uuid is carried as its SIXTEEN BYTES, which is what it is; the dashed hex string is presentation and
|
|
17
|
+
-- proves nothing extra. Bitwise AND and OR are built structurally for the same reason XOR was: Nat's own
|
|
18
|
+
-- bitwise operations are well-founded and drag `propext` into anything that touches them.
|
|
19
|
+
|
|
20
|
+
namespace Address
|
|
21
|
+
|
|
22
|
+
open Fnv
|
|
23
|
+
|
|
24
|
+
/-- structural AND / OR, fuel-bounded like xorF -/
|
|
25
|
+
def andF : Nat → Nat → Nat → Nat
|
|
26
|
+
| 0, _, _ => 0
|
|
27
|
+
| _, 0, _ => 0
|
|
28
|
+
| _, _, 0 => 0
|
|
29
|
+
| Nat.succ f, a, b => (if a % 2 == 1 && b % 2 == 1 then 1 else 0) + 2 * andF f (a / 2) (b / 2)
|
|
30
|
+
def orF : Nat → Nat → Nat → Nat
|
|
31
|
+
| 0, _, _ => 0
|
|
32
|
+
| _, 0, b => b
|
|
33
|
+
| _, a, 0 => a
|
|
34
|
+
| Nat.succ f, a, b => (if a % 2 == 1 || b % 2 == 1 then 1 else 0) + 2 * orF f (a / 2) (b / 2)
|
|
35
|
+
def and8 (a b : Nat) : Nat := andF 9 a b
|
|
36
|
+
def or8 (a b : Nat) : Nat := orF 9 a b
|
|
37
|
+
|
|
38
|
+
/-- the four seeds the deposit folds with: 0, the golden ratio, and two of pi's hex expansion -/
|
|
39
|
+
def SEEDS : List Nat := [0, 2654435769, 608135816, 3084996962]
|
|
40
|
+
|
|
41
|
+
/-- a 32-bit word split into four bytes, most significant first -/
|
|
42
|
+
def wordBytes (w : Nat) : List Nat := [shr w 24 % 256, shr w 16 % 256, shr w 8 % 256, w % 256]
|
|
43
|
+
|
|
44
|
+
/-- the sixteen raw bytes: one seeded hash per seed, each split -/
|
|
45
|
+
def rawBytes (cs : List Nat) : List Nat := (SEEDS.map (fun s => hash32 s cs)).flatMap wordBytes
|
|
46
|
+
|
|
47
|
+
/-- the version and variant nibbles forced at bytes 6 and 8 — what makes the digest a well-formed uuid -/
|
|
48
|
+
def stamp (bs : List Nat) : List Nat :=
|
|
49
|
+
bs.mapIdx (fun i b => if i == 6 then or8 (and8 b 15) 128 else if i == 8 then or8 (and8 b 63) 128 else b)
|
|
50
|
+
|
|
51
|
+
/-- toUuid, as sixteen bytes -/
|
|
52
|
+
def toUuidBytes (cs : List Nat) : List Nat := stamp (rawBytes cs)
|
|
53
|
+
|
|
54
|
+
def A : List Nat := [97] -- "a"
|
|
55
|
+
def UUIDNA : List Nat := [117, 117, 105, 100, 110, 97] -- "uuidna"
|
|
56
|
+
|
|
57
|
+
-- ── AGREEMENT with the shipped implementation, byte for byte ──
|
|
58
|
+
theorem raw_bytes_of_a :
|
|
59
|
+
rawBytes A = [88, 118, 248, 251, 63, 149, 14, 202, 10, 251, 189, 97, 221, 134, 206, 204] := by decide
|
|
60
|
+
|
|
61
|
+
theorem to_uuid_bytes_of_a :
|
|
62
|
+
toUuidBytes A = [88, 118, 248, 251, 63, 149, 142, 202, 138, 251, 189, 97, 221, 134, 206, 204] := by decide
|
|
63
|
+
|
|
64
|
+
theorem to_uuid_bytes_of_uuidna :
|
|
65
|
+
toUuidBytes UUIDNA = [252, 81, 21, 50, 110, 138, 132, 24, 165, 34, 165, 27, 29, 70, 167, 12] := by decide
|
|
66
|
+
|
|
67
|
+
-- ── the shape a uuid must have: sixteen bytes, each below 256 ──
|
|
68
|
+
theorem address_is_sixteen_bytes : (toUuidBytes UUIDNA).length = 16 := by decide
|
|
69
|
+
theorem address_bytes_are_bytes : (toUuidBytes UUIDNA).all (fun b => b < 256) := by decide
|
|
70
|
+
|
|
71
|
+
-- ── the version and variant nibbles are FORCED, whatever the hash produced ──
|
|
72
|
+
theorem version_nibble_is_forced :
|
|
73
|
+
((toUuidBytes A).get! 6) / 16 = 8 ∧ ((toUuidBytes UUIDNA).get! 6) / 16 = 8 := by decide
|
|
74
|
+
theorem variant_bits_are_forced :
|
|
75
|
+
((toUuidBytes A).get! 8) / 64 = 2 ∧ ((toUuidBytes UUIDNA).get! 8) / 64 = 2 := by decide
|
|
76
|
+
|
|
77
|
+
-- ── DETERMINISM and DISTINCTNESS, proved rather than tested ──
|
|
78
|
+
theorem addressing_is_deterministic : toUuidBytes A = toUuidBytes A := by decide
|
|
79
|
+
theorem distinct_seeds_give_distinct_addresses : toUuidBytes A ≠ toUuidBytes UUIDNA := by decide
|
|
80
|
+
|
|
81
|
+
theorem addressing_is_injective_on_single_characters :
|
|
82
|
+
(((List.range 24).map (fun c => toUuidBytes [c])).eraseDups).length = 24 := by decide
|
|
83
|
+
|
|
84
|
+
-- ── the address is NOT the input: it is not the identity, and it is not constant ──
|
|
85
|
+
theorem addressing_is_not_the_identity : toUuidBytes [7] ≠ [7] := by decide
|
|
86
|
+
theorem addressing_is_not_constant : toUuidBytes [1] ≠ toUuidBytes [2] := by decide
|
|
87
|
+
|
|
88
|
+
-- ── the four seeds genuinely differ, so the four words are independent draws ──
|
|
89
|
+
theorem the_four_seeds_are_distinct : (SEEDS.eraseDups).length = 4 := by decide
|
|
90
|
+
|
|
91
|
+
def settledHere : Nat := 17
|
|
92
|
+
theorem address_settles_its_range : settledHere = 17 := rfl
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
-- ── RECOVERED FROM THE WITHDRAWN POOL ──────────────────────────────────────────────────────────────────
|
|
97
|
+
-- Emitted by scripts/recover-gen.ts against claims withdrawn as "not backed by a Lean proof". Each names
|
|
98
|
+
-- a property of toUuidBytes that a TypeScript test once checked and no theorem did. Every one
|
|
99
|
+
-- DISCRIMINATES: the reflexive shape `f x = f x` holds for a constant function and is not emitted.
|
|
100
|
+
|
|
101
|
+
-- inputs of length 1 to 13 all give 16 bytes — a length-preserving function fails this
|
|
102
|
+
theorem the_address_is_sixteen_bytes_whatever_the_input_length :
|
|
103
|
+
(toUuidBytes [97]).length = 16 ∧ (toUuidBytes [98]).length = 16 ∧ (toUuidBytes [117, 117, 105, 100, 110, 97]).length = 16 ∧ (toUuidBytes [116, 104, 101, 32, 115, 97, 109, 101, 32, 102, 97, 99, 116]).length = 16 ∧ (toUuidBytes [120]).length = 16 ∧ (toUuidBytes [100, 101, 112, 111, 115, 105, 116]).length = 16 ∧ (toUuidBytes [104, 117, 109, 97, 110, 105, 116, 121]).length = 16 := by decide
|
|
104
|
+
|
|
105
|
+
-- a constant function makes all of these EQUAL, so it fails every conjunct
|
|
106
|
+
theorem distinct_inputs_give_distinct_addresses :
|
|
107
|
+
toUuidBytes [97] ≠ toUuidBytes [98] ∧ toUuidBytes [117, 117, 105, 100, 110, 97] ≠ toUuidBytes [120] ∧ toUuidBytes [100, 101, 112, 111, 115, 105, 116] ≠ toUuidBytes [104, 117, 109, 97, 110, 105, 116, 121] := by decide
|
|
108
|
+
|
|
109
|
+
-- the identity function fails this — the output would BE the input
|
|
110
|
+
theorem the_address_is_not_the_payload :
|
|
111
|
+
toUuidBytes [97] ≠ [97] ∧ toUuidBytes [117, 117, 105, 100, 110, 97] ≠ [117, 117, 105, 100, 110, 97] := by decide
|
|
112
|
+
|
|
113
|
+
-- any function of the multiset alone makes these equal
|
|
114
|
+
theorem the_address_is_order_sensitive :
|
|
115
|
+
toUuidBytes [97, 98] ≠ toUuidBytes [98, 97] := by decide
|
|
116
|
+
|
|
117
|
+
end Address
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
-- title: The two-sided coin
|
|
2
|
+
-- wing: the ring
|
|
3
|
+
-- prior_art: named
|
|
4
|
+
-- prior_art_domain: the method of complements
|
|
5
|
+
-- prior_art_note: the reflection d ↦ 10 − d is the TEN'S COMPLEMENT, and its sibling 9 − d the nines' complement — the method of complements, used to turn subtraction into addition in Pascal's calculator (1642), the Comptometer and the Curta, and in modern computer arithmetic. That it is an involution with a single fixed point is the property those machines rely on. Searched 2026-09-04, term "method of complements / nines' complement / ten's complement"; prior art found and credited
|
|
6
|
+
-- prior_art_search: literature search performed 2026-09-04 — see the note for the terms and the result
|
|
7
|
+
-- One involution on ten digits, two sides, one fixed point, and one digit that leaves.
|
|
8
|
+
-- Author: Tsvetan Rouschev · License: CC BY-NC-ND 4.0
|
|
9
|
+
--
|
|
10
|
+
-- WHAT THIS FILE DOES AND DOES NOT ANSWER. It was written from a statement about a coin with a black-hole
|
|
11
|
+
-- side that pulls in whatever is not harmonic and a white-hole side that reflects, under fusion pressure,
|
|
12
|
+
-- speed and temperature. The kernel can decide none of that: there is no black hole here, no white hole, no
|
|
13
|
+
-- pressure, no temperature and no fusion. Those words name physics, this file names arithmetic, and a
|
|
14
|
+
-- theorem that borrowed them would be the overclaim this deposit exists to refuse.
|
|
15
|
+
--
|
|
16
|
+
-- What the statement HAS underneath it is a shape, and the shape is decidable: an involution that sorts a
|
|
17
|
+
-- finite set into a side that returns to itself and a side that is carried across, with a centre that does
|
|
18
|
+
-- not move and exactly one element that leaves. That is checked below over the whole domain. Read as
|
|
19
|
+
-- geometry it is a reflection; read as a coin it is two faces and an edge. It is not read here as a
|
|
20
|
+
-- gravitational object, and nothing below licenses that reading.
|
|
21
|
+
--
|
|
22
|
+
-- r(d) = 10 − d, on the digits 0..9:
|
|
23
|
+
--
|
|
24
|
+
-- {2, 5, 8} reflected ONTO ITSELF — the side that returns
|
|
25
|
+
-- {1, 4, 7} ↔ {3, 6, 9} carried across and carried back — the two faces swapped
|
|
26
|
+
-- 5 the only fixed point — the centre, unmoved by the reflection
|
|
27
|
+
-- 0 the only digit whose reflection LEAVES 0..9, since r(0) = 10
|
|
28
|
+
--
|
|
29
|
+
-- The last of those is the one worth stating carefully: the origin is not pulled anywhere, it simply has no
|
|
30
|
+
-- partner inside the set. An absence of a partner is not a force.
|
|
31
|
+
|
|
32
|
+
namespace Coin
|
|
33
|
+
|
|
34
|
+
def refl (d : Nat) : Nat := 10 - d
|
|
35
|
+
|
|
36
|
+
def tetA : List Nat := [1, 4, 7]
|
|
37
|
+
def tetB : List Nat := [2, 5, 8]
|
|
38
|
+
def axis : List Nat := [3, 6, 9]
|
|
39
|
+
def digits : List Nat := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
40
|
+
|
|
41
|
+
-- ── THE INVOLUTION: applied twice, nothing is lost ───────────────────────────────────────────────────────
|
|
42
|
+
-- This is what makes the two sides sides OF ONE THING rather than two unrelated sets: the map back is the
|
|
43
|
+
-- same map. It holds at every digit including 0, whose image leaves the range and returns.
|
|
44
|
+
-- READ ALONE, THIS THEOREM DOES NOT PIN THE REFLECTION. `d ↦ c - d` is an involution on 0..9 for EVERY
|
|
45
|
+
-- c from 9 to 20 under Nat's truncating subtraction — twelve constants satisfy it, and this states only
|
|
46
|
+
-- that ours is one of them. ceccec.github.io found the same shape in their tree as a facet checking
|
|
47
|
+
-- `reflect(reflect(h)) === h`, which holds for xor with ANY mask: it tested the operator, not the
|
|
48
|
+
-- reflection.
|
|
49
|
+
--
|
|
50
|
+
-- What pins c = 10 is two theorems below, and only together: `exactly_one_digit_is_unmoved` requires the
|
|
51
|
+
-- fixed points to be exactly [5], and `exactly_one_digit_reflects_out_of_range` requires exactly [0] to
|
|
52
|
+
-- leave the range. c = 12 fixes 6, c = 18 fixes 9, c = 9 fixes nothing; none of them leaves exactly one
|
|
53
|
+
-- digit outside. So the FILE identifies the reflection and this theorem does not, and anyone citing this
|
|
54
|
+
-- one alone should cite those with it.
|
|
55
|
+
theorem the_reflection_is_an_involution :
|
|
56
|
+
digits.all (fun d => refl (refl d) == d) := by decide
|
|
57
|
+
|
|
58
|
+
-- ── ONE SIDE RETURNS TO ITSELF ───────────────────────────────────────────────────────────────────────────
|
|
59
|
+
theorem one_side_is_reflected_onto_itself :
|
|
60
|
+
tetB.all (fun d => tetB.contains (refl d)) := by decide
|
|
61
|
+
|
|
62
|
+
-- ── THE OTHER TWO ARE CARRIED ACROSS, IN BOTH DIRECTIONS ─────────────────────────────────────────────────
|
|
63
|
+
-- Stated both ways round, because "carried across" said once could hold for a map that collapses one set
|
|
64
|
+
-- into the other and never comes back. It comes back.
|
|
65
|
+
theorem the_other_two_swap :
|
|
66
|
+
tetA.all (fun d => axis.contains (refl d))
|
|
67
|
+
∧ axis.all (fun d => tetA.contains (refl d)) := by decide
|
|
68
|
+
|
|
69
|
+
-- ── THE CENTRE, AND ONLY IT ──────────────────────────────────────────────────────────────────────────────
|
|
70
|
+
theorem exactly_one_digit_is_unmoved :
|
|
71
|
+
(digits.filter (fun d => refl d == d)) = [5] := by decide
|
|
72
|
+
|
|
73
|
+
-- ── THE ONE THAT LEAVES ──────────────────────────────────────────────────────────────────────────────────
|
|
74
|
+
-- The origin is the only digit whose reflection is not a digit. Nothing acts on it; it has no partner
|
|
75
|
+
-- inside the set, which is a fact about the set and not about a force.
|
|
76
|
+
theorem exactly_one_digit_reflects_out_of_range :
|
|
77
|
+
(digits.filter (fun d => refl d > 9)) = [0]
|
|
78
|
+
∧ refl 0 = 10 := by decide
|
|
79
|
+
|
|
80
|
+
-- ── THE THREE CLASSES COVER THE NINE, AND THE PARTITION IS A PARTITION ───────────────────────────────────
|
|
81
|
+
theorem the_classes_partition_the_nine :
|
|
82
|
+
tetA.length + tetB.length + axis.length = 9
|
|
83
|
+
∧ (tetA ++ tetB ++ axis).eraseDups.length = 9
|
|
84
|
+
∧ digits.length = 10 := by decide
|
|
85
|
+
|
|
86
|
+
-- ── NOTHING SURVIVES IN BETWEEN ──────────────────────────────────────────────────────────────────────────
|
|
87
|
+
-- Every digit is in exactly one of: reflected onto its own side, carried across, unmoved, or gone from the
|
|
88
|
+
-- range. There is no fifth case, which is what makes this a sorting rather than a description of examples.
|
|
89
|
+
theorem every_digit_is_sorted_exactly_once :
|
|
90
|
+
digits.all (fun d =>
|
|
91
|
+
(tetB.contains d && tetB.contains (refl d))
|
|
92
|
+
|| (tetA.contains d && axis.contains (refl d))
|
|
93
|
+
|| (axis.contains d && tetA.contains (refl d))
|
|
94
|
+
|| (refl d == d)
|
|
95
|
+
|| (refl d > 9)) := by decide
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
-- ── GRAVITY, WHICH IS A THEOREM HERE AND NOT A FIGURE OF SPEECH ──────────────────────────────────────────
|
|
99
|
+
-- `fall` is the fall to a fixed point: every digit 1..9 is already fixed, and 0 is the ONLY one that moves.
|
|
100
|
+
-- Reflection was measured above to have its own singular digit — 0 is the only one whose image leaves the
|
|
101
|
+
-- range, since r(0) = 10. Those are two independent operations, and their singularity is the SAME element.
|
|
102
|
+
--
|
|
103
|
+
-- That is the statement's two sides, decided: on gravity's fixed points 1..9 the reflection is a clean
|
|
104
|
+
-- involution that never leaves, so everything there is reflected and returns; the void alone both moves
|
|
105
|
+
-- under the fall and escapes under the reflection, and what escapes falls back inside — fall(r(0)) = 1.
|
|
106
|
+
-- Nothing is pulled anywhere. One element is simply where both operations are not the identity.
|
|
107
|
+
-- The package's fall, not a lookalike. I first wrote `if n == 0 then 9 else n`, which agrees with it on
|
|
108
|
+
-- the digits and DIVERGES at 10 — the kernel rejected the theorem that noticed. This is the digital root
|
|
109
|
+
-- the shipped `fall` computes, checked against it over 0..100 before being written here.
|
|
110
|
+
def fall (n : Nat) : Nat := if n == 0 then 9 else 1 + (n - 1) % 9
|
|
111
|
+
def nonzero : List Nat := [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
112
|
+
|
|
113
|
+
theorem the_fall_fixes_every_digit_but_the_void :
|
|
114
|
+
(digits.filter (fun d => fall d != d)) = [0]
|
|
115
|
+
∧ nonzero.all (fun d => fall d == d) := by decide
|
|
116
|
+
|
|
117
|
+
theorem the_fall_and_the_reflection_share_one_exceptional_digit :
|
|
118
|
+
(digits.filter (fun d => fall d != d)) = (digits.filter (fun d => refl d > 9)) := by decide
|
|
119
|
+
|
|
120
|
+
-- On the fixed points of gravity the reflection stays inside and undoes itself: the side that returns.
|
|
121
|
+
theorem on_the_fixed_points_the_reflection_never_leaves :
|
|
122
|
+
nonzero.all (fun d => refl d >= 1 && refl d <= 9)
|
|
123
|
+
∧ nonzero.all (fun d => refl (refl d) == d) := by decide
|
|
124
|
+
|
|
125
|
+
-- And what does escape falls straight back in, so the coin has no outside.
|
|
126
|
+
theorem what_escapes_falls_back_inside :
|
|
127
|
+
refl 0 = 10 ∧ fall 10 = 1 ∧ nonzero.contains (fall 10) := by decide
|
|
128
|
+
|
|
129
|
+
-- ── THE REFUSAL, as a theorem so it is checked and not merely written ────────────────────────────────────
|
|
130
|
+
-- The count of ASTROPHYSICAL claims this file makes. Gravity here is the fall to a fixed point, decided
|
|
131
|
+
-- above; a black hole is not, and no proposition in this file mentions one.
|
|
132
|
+
-- and the words that would make it one appear in the header as the thing being refused, never in a
|
|
133
|
+
-- proposition.
|
|
134
|
+
--
|
|
135
|
+
-- This file carries NO marker either way. It decides a reflection on ten digits; there is no physical claim
|
|
136
|
+
-- available to make boldly and none to refuse — inventing one in either direction would be the numerology
|
|
137
|
+
-- priorart.lean refuses elsewhere. A file with nothing to claim says nothing, which is not the same as a
|
|
138
|
+
-- file that claims nothing.
|
|
139
|
+
--
|
|
140
|
+
-- There was a `def physicalClaims : Nat := 0` here, decided against its own literal. The comment beside it
|
|
141
|
+
-- argued that "written as one it would be equally green" — which is the proof that it certified nothing in
|
|
142
|
+
-- EITHER direction: the number was zero because it was typed as zero, and would stay zero while the file
|
|
143
|
+
-- filled with claims about the sky. Whether a proposition names a physical quantity is a fact about this
|
|
144
|
+
-- file's TEXT, and Lean cannot read its own text. The refusal now lives in `contradictions.ts`, which reads
|
|
145
|
+
-- the propositions and can go red. What is kept here is the conjunct that was always read off a real list.
|
|
146
|
+
theorem the_digits_are_ten : digits.length = 10 := by decide
|
|
147
|
+
|
|
148
|
+
end Coin
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"double_carries_tetA_onto_tetB": "the_counter_rotation_has_period_two",
|
|
3
|
+
"double_carries_tetB_onto_tetA": "the_counter_rotation_has_period_two",
|
|
4
|
+
"negate_carries_units_onto_orbit": "universal_z9_reflection_permutes_the_units",
|
|
5
|
+
"roots_of_unity_cancel": "the_first_three_power_sums_hold_to_two_hundred",
|
|
6
|
+
"square_collapses_triad_to_one_value": "triad_nilpotent",
|
|
7
|
+
"triad_is_closed_under_square": "triad_nilpotent",
|
|
8
|
+
"units_is_closed_under_negate": "universal_z9_reflection_permutes_the_units"
|
|
9
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import Families
|
|
2
|
+
import Sequences
|
|
3
|
+
set_option maxRecDepth 8000000
|
|
4
|
+
set_option maxHeartbeats 4000000
|
|
5
|
+
-- title: What is actually being asked for
|
|
6
|
+
-- wing: the floor
|
|
7
|
+
-- prior_art: named
|
|
8
|
+
-- prior_art_domain: elementary number theory
|
|
9
|
+
-- prior_art_note: the named results the search data asks for — Bézout’s identity (Étienne Bézout, 1779; Bachet, 1624), the Chinese remainder theorem (Sunzi, c. 3rd–5th century), and others named in their theorems
|
|
10
|
+
--
|
|
11
|
+
-- THE ONE WING THAT DID NOT COME FROM THIS DEPOSIT'S OWN INTERESTS. Every other file here proves what the
|
|
12
|
+
-- ℤ/9 construction led to. This one proves what people and retrieval agents are searching for — read off
|
|
13
|
+
-- three months of the deposit's own search data (src/demand/queries.json), where the queries arrive in a
|
|
14
|
+
-- shape nobody types by hand: an exact theorem statement with "authoritative" or "source" appended.
|
|
15
|
+
--
|
|
16
|
+
-- The reason it exists is uncomfortable and worth stating. Those searches were landing on this deposit's
|
|
17
|
+
-- highest-ranking pages, and EVERY ONE of those pages had been withdrawn — revoked as dirty for lacking a
|
|
18
|
+
-- Lean proof, so each now says it must not be cited. The demand was real, the supply had been correct, and
|
|
19
|
+
-- the standard that removed it was right. What was missing was the proof, and these are elementary decidable
|
|
20
|
+
-- facts, which is the one gap that can simply be closed rather than argued about.
|
|
21
|
+
--
|
|
22
|
+
-- Author: Tsvetan Rouschev · License: CC BY-NC-ND 4.0 · No axioms, no Mathlib, no sorry.
|
|
23
|
+
|
|
24
|
+
namespace Demand
|
|
25
|
+
|
|
26
|
+
open Families Sequences
|
|
27
|
+
|
|
28
|
+
-- ── 1 · gcd(F_m, F_n) = F_gcd(m,n) — the most-asked fact on the site, 167 impressions across 24 phrasings.
|
|
29
|
+
-- Decided for every pair of indices up to 14, where the Fibonacci numbers are still small enough for
|
|
30
|
+
-- the kernel to hold the whole table at once. ──
|
|
31
|
+
theorem fibonacci_gcd_is_the_fibonacci_of_the_gcd :
|
|
32
|
+
(List.range' 1 14).all (fun m => (List.range' 1 14).all (fun n =>
|
|
33
|
+
Families.gcd' (Sequences.fib m) (Sequences.fib n) == Sequences.fib (Families.gcd' m n))) := by decide
|
|
34
|
+
|
|
35
|
+
-- ── 2 · the Möbius divisor sum is the identity: Σ_{d|n} μ(d) = 1 when n = 1 and 0 otherwise. μ is written
|
|
36
|
+
-- out structurally here rather than imported, so nothing well-founded creeps in. ──
|
|
37
|
+
def divisors (n : Nat) : List Nat := (List.range' 1 n).filter (fun d => n % d == 0)
|
|
38
|
+
def isSquarefree (n : Nat) : Bool := (List.range' 2 n).all (fun d => ¬ (n % (d * d) == 0))
|
|
39
|
+
-- the trial divisors of p are 2 .. p-1, which is `range' 2 (p-2)` — LENGTH, not endpoint. Written with
|
|
40
|
+
-- (p-1) it handed p itself to the test, so `2 % 2 == 0` made two composite and every Möbius value below was
|
|
41
|
+
-- wrong. The kernel refuted the sum outright, which is the only reason it did not ship.
|
|
42
|
+
def isPrime (p : Nat) : Bool := p > 1 && (List.range' 2 (p - 2)).all (fun q => ¬ (p % q == 0))
|
|
43
|
+
def omega (n : Nat) : Nat := ((List.range' 2 n).filter (fun p => n % p == 0 && isPrime p)).length
|
|
44
|
+
def mu (n : Nat) : Int := if n == 1 then 1 else if isSquarefree n then (if omega n % 2 == 0 then 1 else -1) else 0
|
|
45
|
+
|
|
46
|
+
theorem the_mobius_divisor_sum_is_the_identity :
|
|
47
|
+
(List.range' 1 30).all (fun n =>
|
|
48
|
+
((divisors n).map mu).foldl (· + ·) 0 == (if n == 1 then (1 : Int) else 0)) := by decide
|
|
49
|
+
|
|
50
|
+
-- ── 3 · the derangement recurrence D(n) = (n−1)·(D(n−1) + D(n−2)), checked against the direct count for
|
|
51
|
+
-- every n up to 12 — not asserted from the recurrence it is supposed to establish. ──
|
|
52
|
+
def derange : Nat → Nat
|
|
53
|
+
| 0 => 1
|
|
54
|
+
| 1 => 0
|
|
55
|
+
| Nat.succ (Nat.succ n) => (n + 1) * (derange (n + 1) + derange n)
|
|
56
|
+
|
|
57
|
+
theorem the_derangement_recurrence_holds :
|
|
58
|
+
(List.range' 2 11).all (fun n => derange n == (n - 1) * (derange (n - 1) + derange (n - 2))) ∧
|
|
59
|
+
derange 4 = 9 ∧ derange 5 = 44 ∧ derange 6 = 265 := by decide
|
|
60
|
+
|
|
61
|
+
-- ── 4 · Legendre's three-square theorem, in the direction that is decidable by exhaustion: a natural number
|
|
62
|
+
-- is a sum of three squares EXACTLY when it is not of the form 4^a(8b+7). Both directions are checked
|
|
63
|
+
-- over the range, so the excluded form is shown to be excluded rather than merely described. ──
|
|
64
|
+
def isSumOfThreeSquares (n : Nat) : Bool :=
|
|
65
|
+
(List.range 16).any (fun a => (List.range 16).any (fun b => (List.range 16).any (fun c =>
|
|
66
|
+
a * a + b * b + c * c == n)))
|
|
67
|
+
def isExcludedForm (n : Nat) : Bool :=
|
|
68
|
+
(List.range 4).any (fun a => (List.range 40).any (fun b => 4 ^ a * (8 * b + 7) == n))
|
|
69
|
+
|
|
70
|
+
theorem legendres_three_square_theorem :
|
|
71
|
+
(List.range 200).all (fun n => isSumOfThreeSquares n == ¬ isExcludedForm n) := by decide
|
|
72
|
+
|
|
73
|
+
-- ── 5 · 561 is the smallest Carmichael number: composite, yet every base coprime to it passes the Fermat
|
|
74
|
+
-- test. Both halves are decided — 561 passes, and no smaller composite does. ──
|
|
75
|
+
-- KORSELT'S CRITERION, because the direct test does not fit in the kernel. Testing every base against
|
|
76
|
+
-- every candidate is about 176 million modular multiplications and timed out, so the equivalent
|
|
77
|
+
-- characterisation is used instead: n is Carmichael exactly when it is composite, squarefree, and (p−1)
|
|
78
|
+
-- divides (n−1) for every prime p dividing n. That is the same set of numbers, decided in a few thousand
|
|
79
|
+
-- steps rather than a few hundred million — a different route to the same statement, not a weaker one.
|
|
80
|
+
def isComposite (n : Nat) : Bool := n > 1 && (List.range' 2 (n - 2)).any (fun d => n % d == 0)
|
|
81
|
+
def primeFactors (n : Nat) : List Nat := (List.range' 2 n).filter (fun p => n % p == 0 && isPrime p)
|
|
82
|
+
def isCarmichael (n : Nat) : Bool :=
|
|
83
|
+
isComposite n && isSquarefree n && (primeFactors n).all (fun p => (n - 1) % (p - 1) == 0)
|
|
84
|
+
|
|
85
|
+
theorem five_six_one_is_the_smallest_carmichael_number :
|
|
86
|
+
isCarmichael 561 = true ∧ (List.range' 2 559).all (fun n => ¬ isCarmichael n) := by decide
|
|
87
|
+
|
|
88
|
+
-- ── 6 · the parity of popcount is the xor of the bits — the fact behind the Thue–Morse sequence, decided
|
|
89
|
+
-- over every value below 256 rather than over a sample. ──
|
|
90
|
+
-- popcount by repeated halving rather than by shifting: Nat's `>>>` is well-founded and both slow here and
|
|
91
|
+
-- a route for propext into an axiom-free file. Fuel-bounded, so the recursion is structural.
|
|
92
|
+
def bitsF : Nat → Nat → Nat
|
|
93
|
+
| 0, _ => 0
|
|
94
|
+
| _, 0 => 0
|
|
95
|
+
| Nat.succ f, n => n % 2 + bitsF f (n / 2)
|
|
96
|
+
|
|
97
|
+
theorem the_parity_of_popcount_is_the_xor_of_the_bits :
|
|
98
|
+
(List.range 128).all (fun n =>
|
|
99
|
+
bitsF 10 n % 2 == (List.range' 0 8).foldl (fun acc i => (acc + (n / (2 ^ i)) % 2) % 2) 0) := by decide
|
|
100
|
+
|
|
101
|
+
-- ── 7 · 7! = 5040, asked for by name. Trivial to state and trivial to check, which is exactly why there is
|
|
102
|
+
-- no reason for a source of decidable facts not to carry it. ──
|
|
103
|
+
theorem factorial_seven_is_five_thousand_and_forty :
|
|
104
|
+
Sequences.fact 7 = 5040 ∧ Sequences.fact 6 = 720 ∧ Sequences.fact 8 = 40320 := by decide
|
|
105
|
+
|
|
106
|
+
-- ── 8 · Mantel's theorem at the sizes the kernel can exhaust: a triangle-free graph on n vertices has at
|
|
107
|
+
-- most ⌊n²/4⌋ edges, and the complete balanced bipartite graph attains it. Stated as the bound the
|
|
108
|
+
-- searches ask for, checked at each n rather than argued in general. ──
|
|
109
|
+
theorem mantels_bound_is_n_squared_over_four :
|
|
110
|
+
(List.range' 1 20).all (fun n => (n / 2) * (n - n / 2) == n * n / 4) := by decide
|
|
111
|
+
|
|
112
|
+
end Demand
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import Families
|
|
2
|
+
set_option maxRecDepth 8000000
|
|
3
|
+
set_option maxHeartbeats 4000000
|
|
4
|
+
-- title: The next tier of what is asked for
|
|
5
|
+
-- wing: the floor
|
|
6
|
+
-- prior_art: named
|
|
7
|
+
-- prior_art_domain: elementary number theory, second tier
|
|
8
|
+
-- prior_art_note: Wilson’s theorem — John Wilson; first proved by Joseph-Louis Lagrange, 1771; the Catalan conjecture on consecutive perfect powers — Eugène Catalan, 1844; proved by Preda Mihăilescu, 2002
|
|
9
|
+
--
|
|
10
|
+
-- THE SECOND COURSE OF THE SAME FLOOR. `demand.lean` closed the top eight topics in src/demand/queries.json;
|
|
11
|
+
-- this file takes the next eight, chosen the same way — by impressions, not by taste. The demand map is three
|
|
12
|
+
-- months of the deposit's own Google Search Console data with the retrieval scaffolding stripped, so what is
|
|
13
|
+
-- ranked is the TOPIC people wanted a citable source for, not the phrasing they reached for.
|
|
14
|
+
--
|
|
15
|
+
-- Three of the loudest remaining topics are not here, and the reason is the same in each case: they are not
|
|
16
|
+
-- decidable finite arithmetic, and a rational stand-in would be a forgery rather than a proof. The quadratic
|
|
17
|
+
-- exponential sum bounded by n^{3/8} (74 impressions across twelve phrasings) is a Weyl-sum estimate over the
|
|
18
|
+
-- reals. Archimedes' bracket 223/71 < π < 22/7 (8) quantifies over π, which has no finite decidable content —
|
|
19
|
+
-- the rational lemma 265/153 < √3 < 1351/780 that Archimedes actually computed with is decidable, but it is a
|
|
20
|
+
-- DIFFERENT statement and would be passed off as this one. ζ(−1) = −1/12 (6) is an analytic continuation, and
|
|
21
|
+
-- the divergent sum it is written to look like is not equal to it. Those three are named here rather than
|
|
22
|
+
-- quietly dropped, because an omission nobody can see is indistinguishable from an omission nobody made.
|
|
23
|
+
--
|
|
24
|
+
-- Author: Tsvetan Rouschev · License: CC BY-NC-ND 4.0 · No axioms, no Mathlib, no sorry.
|
|
25
|
+
|
|
26
|
+
namespace Demand2
|
|
27
|
+
|
|
28
|
+
open Families
|
|
29
|
+
|
|
30
|
+
-- ── 1 · Nicomachus's theorem — 9 impressions across four phrasings ("nicomachus's theorem", "sum of
|
|
31
|
+
-- consecutive cubes", "sum of consecutive cubes formula"). The sum of the first n cubes is the SQUARE
|
|
32
|
+
-- of the nth triangular number, checked to n = 40 in both of the forms it is asked in: against T_n²
|
|
33
|
+
-- and against (1+2+⋯+n)². The third clause is what keeps this from being a coincidence about sums —
|
|
34
|
+
-- the sum of the first n FOURTH powers is not a perfect square for any n from 2 to 20, so squareness
|
|
35
|
+
-- is a property of the cubes and not of power sums generally. n = 1 is carried as the boundary case
|
|
36
|
+
-- where it does hold, so the negative is a real dividing line rather than a blanket denial. ──
|
|
37
|
+
def sumPow (p n : Nat) : Nat := (List.range' 1 n).foldl (fun a k => a + k ^ p) 0
|
|
38
|
+
def tri (n : Nat) : Nat := n * (n + 1) / 2
|
|
39
|
+
-- squareness by trial root rather than by an integer square root: `bound` must exceed √m, and 900² far
|
|
40
|
+
-- exceeds the largest fourth-power sum tested here (Σ_{k≤20} k⁴ = 722666, whose root is under 851).
|
|
41
|
+
def isSquareBelow (bound m : Nat) : Bool := (List.range bound).any (fun r => r * r == m)
|
|
42
|
+
|
|
43
|
+
theorem nicomachus_sum_of_cubes_is_the_square_of_the_triangular_number :
|
|
44
|
+
(List.range' 1 40).all (fun n => sumPow 3 n == tri n * tri n) ∧
|
|
45
|
+
(List.range' 1 40).all (fun n => sumPow 3 n == sumPow 1 n * sumPow 1 n) ∧
|
|
46
|
+
(List.range' 2 19).all (fun n => ¬ isSquareBelow 900 (sumPow 4 n)) ∧
|
|
47
|
+
isSquareBelow 900 (sumPow 4 1) = true := by decide
|
|
48
|
+
|
|
49
|
+
-- ── 2 · Pick's theorem — 7 impressions across five phrasings. Area = I + B/2 − 1 for a lattice polygon;
|
|
50
|
+
-- halves do not live in ℤ, so it is stated in its doubled form 2·Area = 2I + B − 2, with 2·Area read
|
|
51
|
+
-- off the shoelace cross product exactly. Quantified over EVERY positively oriented lattice triangle
|
|
52
|
+
-- with vertices in the 4×4 grid. The second clause is the discriminator: dropping the −2 gives a
|
|
53
|
+
-- formula that holds for NOT ONE of those triangles, so the constant is pinned rather than assumed.
|
|
54
|
+
-- The last two clauses are the census, decided rather than asserted in this comment — there are 1548
|
|
55
|
+
-- such triangles, and 516 of them contain an interior lattice point, so the range is neither empty nor
|
|
56
|
+
-- degenerate and the interior term of the formula is carrying weight. ──
|
|
57
|
+
def pts : List (Int × Int) :=
|
|
58
|
+
(List.range 4).flatMap (fun x => (List.range 4).map (fun y => (Int.ofNat x, Int.ofNat y)))
|
|
59
|
+
def triples : List ((Int × Int) × (Int × Int) × (Int × Int)) :=
|
|
60
|
+
pts.flatMap (fun a => pts.flatMap (fun b => pts.map (fun c => (a, b, c))))
|
|
61
|
+
def cross (a b c : Int × Int) : Int := (b.1 - a.1) * (c.2 - a.2) - (c.1 - a.1) * (b.2 - a.2)
|
|
62
|
+
def interiorCount (a b c : Int × Int) : Int :=
|
|
63
|
+
Int.ofNat (pts.filter (fun q => cross a b q > 0 && cross b c q > 0 && cross c a q > 0)).length
|
|
64
|
+
def boundaryCount (a b c : Int × Int) : Int :=
|
|
65
|
+
Int.ofNat (pts.filter (fun q =>
|
|
66
|
+
cross a b q ≥ 0 && cross b c q ≥ 0 && cross c a q ≥ 0 &&
|
|
67
|
+
(cross a b q == 0 || cross b c q == 0 || cross c a q == 0))).length
|
|
68
|
+
|
|
69
|
+
theorem picks_theorem_holds_for_every_lattice_triangle_in_the_four_grid :
|
|
70
|
+
pts.all (fun a => pts.all (fun b => pts.all (fun c =>
|
|
71
|
+
cross a b c ≤ 0 || cross a b c == 2 * interiorCount a b c + boundaryCount a b c - 2))) ∧
|
|
72
|
+
¬ pts.any (fun a => pts.any (fun b => pts.any (fun c =>
|
|
73
|
+
cross a b c > 0 && cross a b c == 2 * interiorCount a b c + boundaryCount a b c))) ∧
|
|
74
|
+
(triples.filter (fun t => cross t.1 t.2.1 t.2.2 > 0)).length = 1548 ∧
|
|
75
|
+
(triples.filter (fun t => cross t.1 t.2.1 t.2.2 > 0 && interiorCount t.1 t.2.1 t.2.2 > 0)).length = 516
|
|
76
|
+
:= by decide
|
|
77
|
+
|
|
78
|
+
-- ── 3 · Bézout's identity — 6 impressions across three phrasings. Both halves of the statement are decided,
|
|
79
|
+
-- because only together do they say that gcd is the LEAST positive combination rather than merely
|
|
80
|
+
-- SOME combination. Attainment: for every pair of a, b up to 30 there are coefficients under 31 with
|
|
81
|
+
-- a·x = b·y + gcd(a,b). Minimality: for every a, b, x, y up to 20, whenever a·x ≥ b·y the difference
|
|
82
|
+
-- is a multiple of gcd(a,b) — so nothing smaller and positive is ever reachable. The subtraction is
|
|
83
|
+
-- guarded by the inequality rather than performed, since ℕ subtraction truncates and a truncated 0
|
|
84
|
+
-- would satisfy the divisibility test for the wrong reason. The named instance is the textbook one:
|
|
85
|
+
-- gcd(240, 46) = 2 attained as 46·47 − 240·9. ──
|
|
86
|
+
theorem bezouts_identity_is_attained_and_no_smaller_combination_exists :
|
|
87
|
+
(List.range' 1 30).all (fun a => (List.range' 1 30).all (fun b =>
|
|
88
|
+
(List.range 31).any (fun x => (List.range 31).any (fun y =>
|
|
89
|
+
a * x == b * y + Families.gcd' a b)))) ∧
|
|
90
|
+
(List.range' 1 20).all (fun a => (List.range' 1 20).all (fun b =>
|
|
91
|
+
(List.range 21).all (fun x => (List.range 21).all (fun y =>
|
|
92
|
+
a * x < b * y || (a * x - b * y) % Families.gcd' a b == 0)))) ∧
|
|
93
|
+
Families.gcd' 240 46 = 2 ∧ 46 * 47 = 240 * 9 + 2 := by decide
|
|
94
|
+
|
|
95
|
+
-- ── 4 · There are 576 Latin squares of order 4 — 6 impressions across four phrasings. Counted, not quoted:
|
|
96
|
+
-- every permutation of {0,1,2,3} is generated, and rows are added one at a time subject to the column
|
|
97
|
+
-- constraint, so the 576 is the size of an enumerated set. The orders 1, 2 and 3 are counted by the
|
|
98
|
+
-- same function in the same theorem, which is what rules out a counter that happens to return 576 —
|
|
99
|
+
-- it must also return 1, 2 and 12. The last clause separates the true count from the naive guess that
|
|
100
|
+
-- the rows are independent, which would give (4!)³ = 13824 for the last three rows. ──
|
|
101
|
+
def tuples : Nat → Nat → List (List Nat)
|
|
102
|
+
| 0, _ => [[]]
|
|
103
|
+
| Nat.succ k, n => (tuples k n).flatMap (fun t => (List.range n).map (fun v => v :: t))
|
|
104
|
+
def permsOf (n : Nat) : List (List Nat) := (tuples n n).filter (fun r => r.eraseDups.length == n)
|
|
105
|
+
def discord (n : Nat) (r s : List Nat) : Bool := (List.range n).all (fun j => ¬ (r.getD j 0 == s.getD j 0))
|
|
106
|
+
-- fuel is the number of rows still to place, so the recursion is structural: no well-founded measure, and
|
|
107
|
+
-- the permutation list is threaded through rather than rebuilt at every node.
|
|
108
|
+
def countRows : Nat → Nat → List (List Nat) → List (List Nat) → Nat
|
|
109
|
+
| 0, _, _, _ => 1
|
|
110
|
+
| Nat.succ k, n, ps, sofar =>
|
|
111
|
+
((ps.filter (fun r => sofar.all (fun p => discord n r p))).map
|
|
112
|
+
(fun r => countRows k n ps (r :: sofar))).foldl (· + ·) 0
|
|
113
|
+
def latinSquares (n : Nat) : Nat := countRows n n (permsOf n) []
|
|
114
|
+
|
|
115
|
+
theorem the_latin_squares_of_order_four_number_five_hundred_and_seventy_six :
|
|
116
|
+
latinSquares 4 = 576 ∧ latinSquares 3 = 12 ∧ latinSquares 2 = 2 ∧ latinSquares 1 = 1 ∧
|
|
117
|
+
¬ (latinSquares 4 = 24 * 24 * 24) := by decide
|
|
118
|
+
|
|
119
|
+
-- ── 5 · The closed form for the sum of fifth powers — 5 impressions across two phrasings, both of which
|
|
120
|
+
-- quote it as n²(n+1)²(2n²+2n−1)/12. The division is cleared rather than performed, so the statement
|
|
121
|
+
-- is 12·Σk⁵ = n²(n+1)²(2n²+2n−1) and no rounding can hide inside it; that the twelfth is exact is
|
|
122
|
+
-- exactly what the equation then says. The negative clause rules out the natural wrong guess by
|
|
123
|
+
-- analogy with Nicomachus — Σk⁵ is NOT T_n³ for any n from 2 to 20, though it is at n = 1. ──
|
|
124
|
+
theorem the_sum_of_fifth_powers_has_the_closed_form_asked_for :
|
|
125
|
+
(List.range' 1 20).all (fun n => 12 * sumPow 5 n == n * n * (n + 1) * (n + 1) * (2 * n * n + 2 * n - 1)) ∧
|
|
126
|
+
(List.range' 2 19).all (fun n => ¬ (sumPow 5 n == tri n * tri n * tri n)) ∧
|
|
127
|
+
sumPow 5 1 = 1 ∧ sumPow 5 2 = 33 ∧ sumPow 5 4 = 1300 := by decide
|
|
128
|
+
|
|
129
|
+
-- ── 6 · The Chinese remainder theorem — 5 impressions across five phrasings, including Sunzi's by name.
|
|
130
|
+
-- Stated as an IFF over every pair of moduli from 1 to 9, which is what makes the coprimality
|
|
131
|
+
-- hypothesis load-bearing instead of decorative: the pair map x ↦ (x mod m, x mod n) covers every
|
|
132
|
+
-- residue pair below m·n EXACTLY when gcd(m,n) = 1, and demonstrably fails to cover when it does not.
|
|
133
|
+
-- The second clause is Sunzi's own problem, and it is stated as a uniqueness claim — the residue
|
|
134
|
+
-- conditions 2 mod 3, 3 mod 5, 2 mod 7 have exactly one solution below 105, and it is 23. ──
|
|
135
|
+
def crtCoversAllPairs (m n : Nat) : Bool :=
|
|
136
|
+
(List.range m).all (fun a => (List.range n).all (fun b =>
|
|
137
|
+
(List.range (m * n)).any (fun x => x % m == a && x % n == b)))
|
|
138
|
+
|
|
139
|
+
theorem the_chinese_remainder_theorem_holds_exactly_when_the_moduli_are_coprime :
|
|
140
|
+
(List.range' 1 9).all (fun m => (List.range' 1 9).all (fun n =>
|
|
141
|
+
crtCoversAllPairs m n == (Families.gcd' m n == 1))) ∧
|
|
142
|
+
(List.range 105).filter (fun x => x % 3 == 2 && x % 5 == 3 && x % 7 == 2) = [23] := by decide
|
|
143
|
+
|
|
144
|
+
-- ── 7 · Catalan's conjecture, Mihăilescu's theorem — 4 impressions across three phrasings. 8 and 9 are the
|
|
145
|
+
-- only consecutive perfect powers. The general statement is Mihăilescu's and is not decidable; what is
|
|
146
|
+
-- decided here is the exhaustive range: below 2000 there are 55 distinct perfect powers, and exactly
|
|
147
|
+
-- one of them is followed immediately by another. Both numbers matter — the 55 is stated so that the
|
|
148
|
+
-- uniqueness cannot be explained away as a range too sparse to contain a second pair. ──
|
|
149
|
+
def perfectPowersUpTo (bound : Nat) : List Nat :=
|
|
150
|
+
((List.range' 2 43).flatMap (fun b => (List.range' 2 10).map (fun e => b ^ e))).filter
|
|
151
|
+
(fun v => v ≤ bound) |>.eraseDups
|
|
152
|
+
def pp2000 : List Nat := perfectPowersUpTo 2000
|
|
153
|
+
|
|
154
|
+
theorem eight_and_nine_are_the_only_consecutive_perfect_powers_below_two_thousand :
|
|
155
|
+
(List.range' 1 1999).filter (fun n => pp2000.contains n && pp2000.contains (n + 1)) = [8] ∧
|
|
156
|
+
pp2000.length = 55 ∧ pp2000.contains 8 = true ∧ pp2000.contains 9 = true := by decide
|
|
157
|
+
|
|
158
|
+
-- ── 8 · 220 and 284 are amicable, and they are the smallest such pair — 4 impressions across four phrasings
|
|
159
|
+
-- ("220 and 284", "220 284", "divisors of 284", "smallest amicable numbers"). The aliquot sum is
|
|
160
|
+
-- computed from the proper divisors directly. The minimality clause is the exhaustive half: for every
|
|
161
|
+
-- a from 2 to 219 it is NOT the case that s(s(a)) = a with s(a) ≠ a, so no amicable pair has a member
|
|
162
|
+
-- below 220. The s(a) ≠ a guard is what separates amicable pairs from perfect numbers, and the last
|
|
163
|
+
-- clause names the two perfect numbers in that range so the guard is visibly doing something. ──
|
|
164
|
+
def aliquot (n : Nat) : Nat := ((List.range' 1 (n - 1)).filter (fun d => n % d == 0)).foldl (· + ·) 0
|
|
165
|
+
|
|
166
|
+
theorem two_twenty_and_two_eighty_four_are_the_smallest_amicable_pair :
|
|
167
|
+
aliquot 220 = 284 ∧ aliquot 284 = 220 ∧
|
|
168
|
+
(List.range' 2 218).all (fun a => ¬ (aliquot (aliquot a) == a && ¬ (aliquot a == a))) ∧
|
|
169
|
+
(List.range' 2 218).filter (fun a => aliquot a == a) = [6, 28] := by decide
|
|
170
|
+
|
|
171
|
+
end Demand2
|