@ceccec/millennium-solutions 9.3.2 → 9.3.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.
Files changed (259) hide show
  1. package/README.md +54 -40
  2. package/dist/mod.core.d.ts +9 -0
  3. package/dist/mod.core.js +9 -0
  4. package/dist/src/0/index.d.ts +47 -0
  5. package/dist/src/0/index.js +189 -0
  6. package/dist/src/0/ledger.d.ts +1 -0
  7. package/dist/src/0/ledger.js +25 -0
  8. package/dist/src/0/trinity-matrix.d.ts +1 -0
  9. package/dist/src/0/trinity-matrix.js +16 -0
  10. package/dist/src/5/aspects.d.ts +1 -0
  11. package/dist/src/5/aspects.js +22 -0
  12. package/dist/src/5/reflection.d.ts +1 -0
  13. package/dist/src/5/reflection.js +25 -0
  14. package/dist/src/7/rosetta.d.ts +1 -0
  15. package/dist/src/7/rosetta.js +24 -0
  16. package/dist/src/9/enumeration.d.ts +1 -0
  17. package/dist/src/9/enumeration.js +14 -0
  18. package/dist/src/honesty/index.d.ts +16 -0
  19. package/dist/src/honesty/index.js +69 -0
  20. package/package.json +27 -10
  21. package/.zenodo.json +0 -51
  22. package/ABSTRACT.md +0 -155
  23. package/ACCOUNTING.md +0 -27
  24. package/AXIOMS.md +0 -574
  25. package/CHALLENGES.md +0 -2434
  26. package/DEPLOY.md +0 -39
  27. package/DEVELOP.md +0 -34
  28. package/HEART.md +0 -112
  29. package/PHYSICS-SCALES.md +0 -80
  30. package/PRIOR-ART.md +0 -151
  31. package/PROOF-OF-CONCEPT.md +0 -81
  32. package/REALISATIONS.md +0 -87
  33. package/RESEARCH.md +0 -188
  34. package/RULES.md +0 -57
  35. package/SEQUENCE-DECODE.md +0 -196
  36. package/SIGNATURE.md +0 -34
  37. package/THEOREMS.md +0 -97
  38. package/WHITEPAPER.md +0 -40
  39. package/WORKFLOWS.md +0 -47
  40. package/boundaries.md +0 -23
  41. package/captain.md +0 -85
  42. package/compare.md +0 -42
  43. package/compute.md +0 -543
  44. package/cryptography.md +0 -55
  45. package/dashboard.md +0 -50
  46. package/examples.md +0 -47
  47. package/folds.md +0 -65
  48. package/forensic.md +0 -67
  49. package/guide.md +0 -126
  50. package/harness.md +0 -20
  51. package/index.md +0 -217
  52. package/mod.core.ts +0 -10
  53. package/nature.md +0 -58
  54. package/organism.md +0 -30
  55. package/paper.md +0 -8100
  56. package/proofs.md +0 -26
  57. package/quantum.md +0 -40
  58. package/rights.md +0 -39
  59. package/solutions.md +0 -28
  60. package/speedup.md +0 -41
  61. package/src/0/chacha.ts +0 -3
  62. package/src/0/crypt.ts +0 -4
  63. package/src/0/csp.ts +0 -10
  64. package/src/0/entanglement.ts +0 -31
  65. package/src/0/fusion.ts +0 -28
  66. package/src/0/holographic.ts +0 -57
  67. package/src/0/impossible.ts +0 -30
  68. package/src/0/imprint.ts +0 -160
  69. package/src/0/index.ts +0 -263
  70. package/src/0/ledger.ts +0 -25
  71. package/src/0/legible.ts +0 -29
  72. package/src/0/limit.ts +0 -29
  73. package/src/0/merkle-proof.ts +0 -3
  74. package/src/0/null-token.ts +0 -24
  75. package/src/0/sha256.ts +0 -3
  76. package/src/0/singularity.ts +0 -20
  77. package/src/0/stream.ts +0 -47
  78. package/src/0/trinities.ts +0 -37
  79. package/src/0/trinity-matrix.ts +0 -20
  80. package/src/0/version-matrix.ts +0 -70
  81. package/src/1/acceptance.ts +0 -26
  82. package/src/1/index.ts +0 -80
  83. package/src/1/paradox.ts +0 -28
  84. package/src/1/vortex.lean +0 -6
  85. package/src/2/frequency-scales.ts +0 -28
  86. package/src/2/iching.ts +0 -34
  87. package/src/2/index.ts +0 -78
  88. package/src/2/primes-vortex.ts +0 -12
  89. package/src/2/quantum.ts +0 -48
  90. package/src/2/string-scale.ts +0 -14
  91. package/src/2/vortex.lean +0 -10
  92. package/src/3/index.ts +0 -63
  93. package/src/3/pi-bbp.ts +0 -13
  94. package/src/3/trinity.ts +0 -39
  95. package/src/3/vortex.lean +0 -7
  96. package/src/4/git.ts +0 -30
  97. package/src/4/index.ts +0 -63
  98. package/src/4/vortex.lean +0 -6
  99. package/src/5/aspects.ts +0 -27
  100. package/src/5/center.ts +0 -35
  101. package/src/5/development.ts +0 -45
  102. package/src/5/diamond.ts +0 -35
  103. package/src/5/folds.ts +0 -12
  104. package/src/5/index.ts +0 -63
  105. package/src/5/reflection.lean +0 -14
  106. package/src/5/reflection.ts +0 -14
  107. package/src/5/vortex.lean +0 -10
  108. package/src/6/dna.ts +0 -27
  109. package/src/6/index.ts +0 -63
  110. package/src/6/vortex.lean +0 -7
  111. package/src/7/cross.ts +0 -31
  112. package/src/7/glagolitic.ts +0 -51
  113. package/src/7/index.ts +0 -67
  114. package/src/7/language-lens.ts +0 -41
  115. package/src/7/lens.ts +0 -41
  116. package/src/7/locale.ts +0 -105
  117. package/src/7/rbac.ts +0 -31
  118. package/src/7/rosetta-clay.ts +0 -15
  119. package/src/7/rosetta.lean +0 -11
  120. package/src/7/rosetta.ts +0 -11
  121. package/src/7/string-dimensions.ts +0 -14
  122. package/src/7/vortex.lean +0 -6
  123. package/src/8/infinite.ts +0 -26
  124. package/src/8/merkaba/field.ts +0 -27
  125. package/src/8/merkaba/geometry.ts +0 -16
  126. package/src/8/merkaba/touch.ts +0 -26
  127. package/src/8/nucleus/magic.lean +0 -15
  128. package/src/8/nucleus/proton-mass-fit.ts +0 -9
  129. package/src/8/nucleus/proton-mass.lean +0 -10
  130. package/src/8/nucleus/shell-model-magic.ts +0 -10
  131. package/src/8/vortex.lean +0 -7
  132. package/src/9/access.ts +0 -34
  133. package/src/9/aura-funding.ts +0 -25
  134. package/src/9/coins.ts +0 -25
  135. package/src/9/enumeration.ts +0 -13
  136. package/src/9/funding.ts +0 -85
  137. package/src/9/security.ts +0 -36
  138. package/src/9/society.ts +0 -32
  139. package/src/9/vortex.lean +0 -11
  140. package/src/api/gates.ts +0 -122
  141. package/src/api/index.ts +0 -447
  142. package/src/api/lanes.ts +0 -81
  143. package/src/claims/index.ts +0 -81
  144. package/src/demand/queries.json +0 -1764
  145. package/src/face/index.ts +0 -100
  146. package/src/from/the/heart/index.ts +0 -11
  147. package/src/honesty/boundaries.ts +0 -29
  148. package/src/honesty/index.ts +0 -63
  149. package/src/html/index.ts +0 -10
  150. package/src/latex/index.ts +0 -474
  151. package/src/millennium/index.ts +0 -53
  152. package/src/play/the/game/index.ts +0 -12
  153. package/src/proof/README.md +0 -118
  154. package/src/proof/address.lean +0 -147
  155. package/src/proof/coin.lean +0 -152
  156. package/src/proof/covered.json +0 -9
  157. package/src/proof/demand.lean +0 -134
  158. package/src/proof/demand2.lean +0 -207
  159. package/src/proof/demand3.lean +0 -183
  160. package/src/proof/discovered.json +0 -19125
  161. package/src/proof/elementary.lean +0 -446
  162. package/src/proof/energy.lean +0 -291
  163. package/src/proof/families.lean +0 -648
  164. package/src/proof/fixtures/axiom-control.lean +0 -39
  165. package/src/proof/flow.lean +0 -54
  166. package/src/proof/fnv.lean +0 -116
  167. package/src/proof/generated-theorems.json +0 -207
  168. package/src/proof/generated.lean +0 -101
  169. package/src/proof/imagined.lean +0 -492
  170. package/src/proof/index.lean +0 -156
  171. package/src/proof/index.ts +0 -916
  172. package/src/proof/involution.lean +0 -90
  173. package/src/proof/ledgerclaims.lean +0 -84
  174. package/src/proof/light.lean +0 -158
  175. package/src/proof/mechanical.lean +0 -524
  176. package/src/proof/merkaba.lean +0 -89
  177. package/src/proof/merkle.lean +0 -132
  178. package/src/proof/nim.lean +0 -311
  179. package/src/proof/novelty.json +0 -751
  180. package/src/proof/phenomena.lean +0 -90
  181. package/src/proof/priorart.lean +0 -190
  182. package/src/proof/quantum.lean +0 -159
  183. package/src/proof/reach.lean +0 -105
  184. package/src/proof/recovered.lean +0 -56
  185. package/src/proof/reversal.lean +0 -148
  186. package/src/proof/revoked.json +0 -317
  187. package/src/proof/rights.lean +0 -155
  188. package/src/proof/sequences.lean +0 -219
  189. package/src/proof/speed.lean +0 -152
  190. package/src/proof/split.lean +0 -199
  191. package/src/proof/theorems.lean +0 -67
  192. package/src/proof/trial-all.json +0 -16046
  193. package/src/proof/z9.lean +0 -99
  194. package/src/proof/z9plus.lean +0 -300
  195. package/src/proofs.lisp +0 -170
  196. package/src/prove/emit.ts +0 -115
  197. package/src/prove/index.ts +0 -143
  198. package/src/prove/translate.ts +0 -638
  199. package/src/publication/index.ts +0 -362
  200. package/src/quantum/field.ts +0 -73
  201. package/src/quantum/tree.ts +0 -79
  202. package/src/receipts/1431b4c4-7950-8d7b-88d1-b633219692f8.json +0 -7
  203. package/src/receipts/171e09c0-4cfd-8ce0-a6ed-cd33d5553da3.json +0 -7
  204. package/src/receipts/1a1f16c9-3491-8050-b221-e2a362439be4.json +0 -12
  205. package/src/receipts/1da15f83-83a6-8d04-b1ac-334c2dd6abb3.json +0 -7
  206. package/src/receipts/375a57ed-ef99-855e-8f34-b77d08010f3c.json +0 -6
  207. package/src/receipts/3dcbbf9e-0e49-8ba7-921e-17e478dbafaf.json +0 -6
  208. package/src/receipts/43a24136-5ad9-81ef-97c9-17be1c05bb5f.json +0 -11
  209. package/src/receipts/4991be51-74ba-8f66-9534-e6dba52fb569.json +0 -10
  210. package/src/receipts/52375d8f-232b-8c01-9d82-a824ffa7b2b7.json +0 -6
  211. package/src/receipts/593b546a-36b4-8553-941a-0e03b7053a64.json +0 -7
  212. package/src/receipts/7f75c989-96c9-8a24-8d0d-7e690861ccb4.json +0 -6
  213. package/src/receipts/80f80b59-81d8-866d-9a14-f469729d3dc8.json +0 -6
  214. package/src/receipts/85ac8585-9dc1-8964-9848-ae0f49cc82fb.json +0 -7
  215. package/src/receipts/85db092e-f2c0-88e5-bf75-61c4a65d84e7.json +0 -7
  216. package/src/receipts/95bacad3-9e56-8741-b0f8-def2c6ecb050.json +0 -7
  217. package/src/receipts/a1d33966-7bbd-84ca-902b-49e315af60e0.json +0 -6
  218. package/src/receipts/b20ced61-24ad-8123-adee-56031ab734dd.json +0 -11
  219. package/src/receipts/ba0447cd-f489-841a-a70f-a39b18ec2946.json +0 -11
  220. package/src/receipts/bcddbe66-06cf-8f31-a261-98b836938947.json +0 -7
  221. package/src/receipts/c1bac0d8-d906-8196-a4f0-3d8270b2e944.json +0 -6
  222. package/src/receipts/ce851ea3-3cf8-8646-a5d6-c0c6281210fe.json +0 -10
  223. package/src/receipts/cf43a122-c880-8d86-9e25-6f22f92d6b0a.json +0 -7
  224. package/src/receipts/daad8cd4-d4db-8dca-9c97-9a838cbce528.json +0 -7
  225. package/src/receipts/dc8bdb82-599f-8020-9eb2-cb016b408ec1.json +0 -6
  226. package/src/receipts/df77c265-d1a8-8354-8a9e-769fa5c676e2.json +0 -6
  227. package/src/receipts/e96686da-a411-8838-a5c8-ee7472bce048.json +0 -10
  228. package/src/receipts/f073c46f-7b67-83d0-aca5-db11fac4b5ec.json +0 -7
  229. package/src/receipts/f946d99d-a1c2-89f7-9426-a367c5b04191.json +0 -6
  230. package/src/receipts/fc069e45-115d-8983-ad25-fb9f735da84b.json +0 -6
  231. package/src/the/abstract/index.ts +0 -21
  232. package/src/the/abundance/index.ts +0 -20
  233. package/src/the/apple/earth/index.ts +0 -23
  234. package/src/the/apple/earth/navigation/index.ts +0 -28
  235. package/src/the/apple/earth/truth/index.ts +0 -19
  236. package/src/the/apple/index.ts +0 -27
  237. package/src/the/cancer/index.ts +0 -26
  238. package/src/the/clown/index.ts +0 -25
  239. package/src/the/creation/index.ts +0 -16
  240. package/src/the/crystal/index.ts +0 -23
  241. package/src/the/domain/index.ts +0 -16
  242. package/src/the/game/index.ts +0 -11
  243. package/src/the/gold/compass/index.ts +0 -26
  244. package/src/the/gold/index.ts +0 -35
  245. package/src/the/heart/index.ts +0 -15
  246. package/src/the/index.ts +0 -23
  247. package/src/the/law/index.ts +0 -20
  248. package/src/the/path/index.ts +0 -19
  249. package/src/the/rosetta/index.ts +0 -33
  250. package/src/the/sequence/index.ts +0 -12
  251. package/src/the/solids/index.ts +0 -25
  252. package/src/the/state/index.ts +0 -20
  253. package/src/the/superposition/state/index.ts +0 -22
  254. package/src/the/surface/index.ts +0 -26
  255. package/src/the/theorem/index.ts +0 -14
  256. package/src/the/torus/index.ts +0 -23
  257. package/src/the/waves/index.ts +0 -23
  258. package/the.md +0 -20
  259. package/verify.md +0 -67
@@ -1,132 +0,0 @@
1
- import Address
2
- set_option maxRecDepth 8000000
3
- -- title: The fold
4
- -- wing: the address
5
- -- prior_art: named
6
- -- prior_art_domain: hash trees and membership proofs
7
- -- prior_art_note: the hash tree — Ralph Merkle, 1979 (thesis); CRYPTO 1987
8
- -- The fold, ported to Lean — merge, merkleFold, and the order-independence the deposit calls its receipt.
9
- -- Author: Tsvetan Rouschev · License: CC BY-NC-ND 4.0
10
- --
11
- -- merge(a,b) is toUuid of the two addresses joined by a colon, so the fold operates on the DASHED HEX
12
- -- RENDERING, not on the raw bytes — the rendering is therefore part of the definition and is ported here too.
13
- -- The fold sorts its leaves before pairing, and that sort is the whole reason the result does not depend on
14
- -- the order the leaves arrive in. The deposit asserted that in prose and tested it in TypeScript; below it is
15
- -- decided, over every permutation of the sets named.
16
- --
17
- -- No axioms, no Mathlib, no sorry. Address and Fnv are imported, not restated.
18
-
19
- namespace Merkle
20
-
21
- open Address Fnv
22
-
23
- def hexDigit (n : Nat) : Nat := if n < 10 then 48 + n else 87 + n
24
- def byteHex (b : Nat) : List Nat := [hexDigit (b / 16), hexDigit (b % 16)]
25
-
26
- /-- a uuid as the deposit writes it: 8-4-4-4-12 hex with dashes, as character codes -/
27
- def uuidChars (bs : List Nat) : List Nat :=
28
- let h := bs.flatMap byteHex
29
- (h.take 8) ++ [45] ++ (h.drop 8 |>.take 4) ++ [45] ++ (h.drop 12 |>.take 4) ++ [45]
30
- ++ (h.drop 16 |>.take 4) ++ [45] ++ (h.drop 20)
31
-
32
- /-- merge a b = toUuid("a:b") — the colon is 58 -/
33
- def merge (a b : List Nat) : List Nat := toUuidBytes (uuidChars a ++ [58] ++ uuidChars b)
34
-
35
- /-- lexicographic order on byte lists, which is the order the sort imposes on the rendered addresses -/
36
- def leB : List Nat → List Nat → Bool
37
- | [], _ => true
38
- | _, [] => false
39
- | x :: xs, y :: ys => if x == y then leB xs ys else x < y
40
-
41
- def insB (a : List Nat) : List (List Nat) → List (List Nat)
42
- | [] => [a]
43
- | b :: bs => if leB a b then a :: b :: bs else b :: insB a bs
44
- def sortB : List (List Nat) → List (List Nat)
45
- | [] => []
46
- | a :: as => insB a (sortB as)
47
-
48
- /-- one pairing pass: adjacent leaves merged, an odd one carried up unchanged -/
49
- def pairUp : List (List Nat) → List (List Nat)
50
- | [] => []
51
- | [a] => [a]
52
- | a :: b :: rest => merge a b :: pairUp rest
53
-
54
- /-- the fold: sort, then pair until one remains. Fuel-bounded so the recursion is structural. -/
55
- def foldF : Nat → List (List Nat) → List (List Nat)
56
- | 0, l => l
57
- | _, [a] => [a]
58
- | Nat.succ f, l => foldF f (pairUp l)
59
-
60
- def EMPTY_SEED : List Nat := [101, 109, 112, 116, 121, 45, 109, 105, 110, 100] -- "empty-mind"
61
-
62
- def merkleFold (leaves : List (List Nat)) : List Nat :=
63
- if leaves.isEmpty then toUuidBytes EMPTY_SEED
64
- else (foldF (leaves.length + 1) (sortB leaves)).getD 0 []
65
-
66
- def A : List Nat := toUuidBytes [97] -- address of "a"
67
- def C : List Nat := toUuidBytes [99] -- address of "c"
68
- def B : List Nat := toUuidBytes [98] -- address of "b"
69
-
70
- -- ── AGREEMENT with the shipped implementation ──
71
- theorem merge_agrees :
72
- merge A B = [181, 59, 237, 190, 211, 88, 129, 103, 143, 231, 158, 123, 139, 178, 38, 2] := by decide
73
-
74
- theorem empty_fold_agrees :
75
- merkleFold [] = [147, 146, 154, 45, 72, 16, 138, 198, 159, 50, 78, 208, 125, 158, 1, 108] := by decide
76
-
77
- theorem singleton_fold_is_the_leaf : merkleFold [A] = A := by decide
78
-
79
- -- ── and for more than one leaf, because "the fold of a single leaf is that leaf" is a claim about EVERY
80
- -- leaf and the line above decides it at one. A single instance reads as the general statement when the
81
- -- general statement is what the name says. ──
82
- theorem the_fold_of_any_single_leaf_is_that_leaf :
83
- [A, B, C].all (fun x => merkleFold [x] == x) := by decide
84
-
85
- theorem pair_fold_agrees :
86
- merkleFold [A, B] = [181, 59, 237, 190, 211, 88, 129, 103, 143, 231, 158, 123, 139, 178, 38, 2] := by decide
87
-
88
- -- ── THE ORDER-INDEPENDENCE: the receipt does not depend on the order the leaves arrive in ──
89
- theorem fold_is_order_independent_on_two :
90
- merkleFold [A, B] = merkleFold [B, A] := by decide
91
-
92
- -- ── and it is not vacuous: merge itself IS order-sensitive; the sort is what removes the dependence ──
93
- theorem merge_is_order_sensitive : merge A B ≠ merge B A := by decide
94
-
95
- theorem sorting_is_what_makes_the_fold_order_free :
96
- sortB [A, B] = sortB [B, A] ∧ [A, B] ≠ [B, A] := by decide
97
-
98
- def settledHere : Nat := 11
99
- theorem merkle_settles_its_range : settledHere = 11 := rfl
100
-
101
- -- ── ORDER-INDEPENDENCE ON AN ODD NUMBER OF LEAVES. Two leaves pair exactly and prove little: the interesting
102
- -- case is an odd count, where pairUp must carry the leftover leaf into the next round. All six orderings of
103
- -- three addresses are checked, so the carry cannot be order-sensitive in a way two leaves would hide.
104
- -- ── AND ON FOUR, over every permutation rather than a hand-listed few ────────────────────────────────────
105
- -- Three leaves were written out as five equations because six orderings fit on a page. Four do not:
106
- -- twenty-four orderings written by hand is where a missing case hides. `List.permutations` generates
107
- -- them, so the statement quantifies over ALL of them and cannot be short by one.
108
- -- `List.permutations` is not in Lean's core — it lives in Batteries, which this deposit does not import,
109
- -- for the same reason it does not import Mathlib. So the generator is written here, structurally.
110
- def interleave (x : List Nat) : List (List Nat) → List (List (List Nat))
111
- | [] => [[x]]
112
- | y :: ys => (x :: y :: ys) :: (interleave x ys).map (fun l => y :: l)
113
- def perms : List (List Nat) → List (List (List Nat))
114
- | [] => [[]]
115
- | x :: xs => (perms xs).flatMap (fun p => interleave x p)
116
- def D : List Nat := toUuidBytes [100] -- address of "d"
117
-
118
- -- the generator is checked before it is trusted: four leaves have 4! = 24 orderings, and if `perms` were
119
- -- short the theorem below would quantify over fewer cases while looking exactly as strong
120
- theorem the_permutation_generator_is_complete :
121
- (perms [A, B, C, D]).length = 24 ∧ (perms [A, B, C]).length = 6 := by decide
122
-
123
- set_option maxRecDepth 100000 in
124
- theorem fold_is_order_independent_on_four :
125
- (perms [A, B, C, D]).all (fun p => merkleFold p == merkleFold [A, B, C, D]) := by decide
126
-
127
- theorem fold_is_order_independent_on_three :
128
- merkleFold [A, B, C] = merkleFold [A, C, B] ∧ merkleFold [A, B, C] = merkleFold [B, A, C] ∧
129
- merkleFold [A, B, C] = merkleFold [B, C, A] ∧ merkleFold [A, B, C] = merkleFold [C, A, B] ∧
130
- merkleFold [A, B, C] = merkleFold [C, B, A] := by decide
131
-
132
- end Merkle
@@ -1,311 +0,0 @@
1
- import Fnv
2
- set_option maxRecDepth 2000000
3
- set_option maxHeartbeats 2000000
4
- -- title: Nim
5
- -- wing: the machine
6
- -- prior_art: named
7
- -- prior_art_domain: combinatorial game theory
8
- -- prior_art_note: Nim — Charles L. Bouton, 1901; the Sprague–Grundy theorem — Roland Sprague, 1935 and Patrick M. Grundy, 1939
9
- -- Nim — Bouton's theorem and Sprague–Grundy, decided.
10
- -- Author: Tsvetan Rouschev · License: CC BY-NC-ND 4.0
11
- --
12
- -- The ledger asserted these in TypeScript: that a Nim position is lost for the mover exactly when the XOR of
13
- -- the heaps is zero, and that a single heap's Grundy value is its size. Both are real theorems with real
14
- -- proofs; what is done here is to DECIDE them over a named finite board — every position with heaps up to a
15
- -- bound — which is what `decide` can honestly deliver. It is not a proof for all heap sizes, and the range is
16
- -- stated in each name rather than implied.
17
- --
18
- -- XOR is imported from Fnv rather than restated: it is the same fuel-bounded structural fold, built because
19
- -- Nat's bitwise operations are well-founded and would drag `propext` into every theorem here. Its laws are
20
- -- proved below for every a, b, c, on the standard axioms; the decided rows above stay as their instances.
21
-
22
- namespace Nim
23
-
24
- open Fnv (xorF)
25
-
26
- -- the fuel is a + b + 1, which always exceeds what the fold needs (each step halves both arguments and the fold
27
- -- stops at the first zero); the earlier fuel of 33 read XOR correctly only below 2³³ — a cap, now gone
28
- def xorN (a b : Nat) : Nat := xorF (a + b + 1) a b
29
- -- The board is SMALL and stated, because the game tree is exponential: deciding `lost` explores every play
30
- -- from every position, and at 8x8 the kernel exceeds its heartbeat budget. Six is what `decide` settles here
31
- -- in reasonable time. A larger board is not a harder theorem, it is a longer computation — and claiming the
32
- -- general case would need an induction, not a bigger range.
33
- def N : Nat := 6
34
-
35
- /-- the moves from a two-heap position: take any positive amount from either heap -/
36
- def moves (a b : Nat) : List (Nat × Nat) :=
37
- ((List.range a).map (fun x => (x, b))) ++ ((List.range b).map (fun y => (a, y)))
38
-
39
- /-- a position is LOST for the mover when every move leads to a position that is won for the opponent.
40
- Fuel-bounded: the total of the heaps strictly decreases with each move. -/
41
- def lost : Nat → Nat → Nat → Bool
42
- | 0, _, _ => true
43
- | Nat.succ f, a, b => (moves a b).all (fun p => ! lost f p.1 p.2)
44
-
45
- def isLost (a b : Nat) : Bool := lost (a + b + 1) a b
46
-
47
- -- ── BOUTON: a two-heap position is lost for the mover exactly when the heaps are equal — which is exactly
48
- -- when their XOR is zero. Decided over every position on the N×N board, N = 6. ──
49
- theorem bouton_two_heaps_lost_iff_xor_zero :
50
- (List.range N).all (fun a => (List.range N).all (fun b =>
51
- isLost a b == (xorN a b == 0))) := by decide
52
-
53
- -- ── the same statement in its familiar form: lost exactly when the heaps are equal ──
54
- theorem bouton_lost_iff_heaps_equal :
55
- (List.range N).all (fun a => (List.range N).all (fun b => isLost a b == (a == b))) := by decide
56
-
57
- -- ── NON-VACUITY: the losing positions are exactly the diagonal, so there are N of them among N² — neither
58
- -- everything nor nothing. (An earlier version fixed this count at 8 for an 8x8 board; when the board was
59
- -- reduced the kernel proved the statement FALSE rather than letting a stale constant pass. Tied to N now.) ──
60
- theorem lost_positions_are_exactly_the_diagonal :
61
- (((List.range N).flatMap (fun a => (List.range N).map (fun b => (a, b)))).filter
62
- (fun p => isLost p.1 p.2)).length = N := by decide
63
-
64
- -- ── SPRAGUE–GRUNDY for one heap: the Grundy value of a heap of size n is n ──
65
- def mex (s : List Nat) : Nat := ((List.range (s.length + 1)).filter (fun m => ! s.contains m)).headD 0
66
- def grundy1 : Nat → Nat → Nat
67
- | 0, _ => 0
68
- | Nat.succ f, n => mex ((List.range n).map (fun k => grundy1 f k))
69
-
70
- theorem grundy_of_a_single_heap_is_its_size :
71
- (List.range N).all (fun n => grundy1 (n + 1) n == n) := by decide
72
-
73
- -- ── and the two-heap Grundy value is the XOR of the parts ──
74
- theorem grundy_of_two_heaps_is_the_xor :
75
- (List.range N).all (fun a => (List.range N).all (fun b =>
76
- (xorN (grundy1 (a + 1) a) (grundy1 (b + 1) b)) == xorN a b)) := by decide
77
-
78
- -- ── XOR's algebra, which is why the theorem takes the form it does ──
79
- theorem xor_is_its_own_inverse :
80
- (List.range 16).all (fun a => (List.range 16).all (fun b => xorN (xorN a b) b == a)) := by decide
81
- theorem xor_is_commutative :
82
- (List.range 16).all (fun a => (List.range 16).all (fun b => xorN a b == xorN b a)) := by decide
83
- theorem xor_zero_is_identity : (List.range 32).all (fun a => xorN a 0 == a) := by decide
84
-
85
- -- ── THE NIM-SUM AS GF(2) VECTOR ADDITION, IN ONE PROPOSITION ─────────────────────────────────────────────
86
- -- `nim_sum_is_xor_gf2` claims the nim-sum IS GF(2) vector addition: commutative, associative and
87
- -- self-inverse. Associativity was the one property missing here — and the other three, though each
88
- -- decided above, are decided SEPARATELY. A claim is carried by a theorem that decides all of it or by
89
- -- none, and the ledger's supersededBy names exactly one key, so three quarters of a claim spread over
90
- -- three theorems carries nothing. The conjunction is the claim; the conjuncts standing alone are its
91
- -- parts, which is why both forms are here rather than one. Range 16 because the cube of it is walked.
92
- theorem the_nim_sum_is_a_gf2_vector_addition :
93
- (List.range 16).all (fun a => (List.range 16).all (fun b => xorN a b == xorN b a)) ∧
94
- (List.range 16).all (fun a => (List.range 16).all (fun b => (List.range 16).all (fun c =>
95
- xorN (xorN a b) c == xorN a (xorN b c)))) ∧
96
- (List.range 16).all (fun a => (List.range 16).all (fun b => xorN (xorN a b) b == a)) ∧
97
- (List.range 16).all (fun a => xorN a 0 == a) := by decide
98
-
99
- -- ── BOUTON WITH SEVEN HEAP SIZES, because "heaps ≤ 6" means seven of them and N = 6 gives six ─────────────
100
- -- The ledger's row says "all heaps ≤ 6, exhaustive". `bouton_two_heaps_lost_iff_xor_zero` ranges over
101
- -- List.range N with N = 6, which is 0…5 — one short. Carrying the row on it would have claimed a
102
- -- position nobody decided, over an off-by-one nobody would ever see. The board is widened here instead,
103
- -- in a theorem of its own, because N is baked into the statements already sealed above.
104
- set_option maxRecDepth 4000000 in
105
- theorem bouton_holds_at_every_heap_size_to_six :
106
- (List.range 7).all (fun a => (List.range 7).all (fun b => isLost a b == (xorN a b == 0))) := by decide
107
-
108
-
109
- -- ── XOR's algebra for every a, b, c — no bound ───────────────────────────────────────────────────────────────
110
- -- xor_is_its_own_inverse and xor_is_commutative (a, b < 16), xor_zero_is_identity (a < 32) and
111
- -- the_nim_sum_is_a_gf2_vector_addition (a, b, c < 16) were decided over a range; these prove them for every value.
112
- -- The fold's fuel is a + b + 1, which always suffices: once it exceeds either argument, more fuel changes nothing,
113
- -- so xorN reads the same at any sufficient fuel. Everything follows from one step — the low bit of a XOR is the sum
114
- -- of the low bits mod 2, and the rest is twice the XOR of the halves — by induction. Bouton's theorem itself is
115
- -- still decided over the N×N board above; a proof of it for every heap is a game-tree induction not done here.
116
- theorem the_xor_of_two_bits_is_their_sum_mod_two :
117
- ∀ x y : Nat, (if x % 2 == y % 2 then 0 else 1) = (x + y) % 2 := by
118
- intro x y
119
- split
120
- · rename_i h
121
- have := beq_iff_eq.mp h
122
- omega
123
- · rename_i h
124
- have : x % 2 ≠ y % 2 := fun e => h (beq_iff_eq.mpr e)
125
- omega
126
-
127
- theorem xor_commutes_at_every_fuel : ∀ f a b : Nat, xorF f a b = xorF f b a := by
128
- intro f
129
- induction f with
130
- | zero => intro a b; cases a <;> cases b <;> rfl
131
- | succ f ih =>
132
- intro a b
133
- cases a with
134
- | zero => cases b <;> rfl
135
- | succ a =>
136
- cases b with
137
- | zero => rfl
138
- | succ b =>
139
- show (if (a + 1) % 2 == (b + 1) % 2 then 0 else 1) + 2 * xorF f ((a + 1) / 2) ((b + 1) / 2) =
140
- (if (b + 1) % 2 == (a + 1) % 2 then 0 else 1) + 2 * xorF f ((b + 1) / 2) ((a + 1) / 2)
141
- rw [ih ((a + 1) / 2), the_xor_of_two_bits_is_their_sum_mod_two, the_xor_of_two_bits_is_their_sum_mod_two]
142
- omega
143
-
144
- theorem one_more_step_of_fuel_changes_nothing_once_it_exceeds_an_argument :
145
- ∀ f a b : Nat, (a < f ∨ b < f) → xorF (f + 1) a b = xorF f a b := by
146
- intro f
147
- induction f with
148
- | zero => intro a b h; rcases h with h | h <;> exact absurd h (Nat.not_lt_zero _)
149
- | succ f ih =>
150
- intro a b h
151
- cases a with
152
- | zero => cases b <;> rfl
153
- | succ a =>
154
- cases b with
155
- | zero => rfl
156
- | succ b =>
157
- show (if (a + 1) % 2 == (b + 1) % 2 then 0 else 1) + 2 * xorF (f + 1) ((a + 1) / 2) ((b + 1) / 2) =
158
- (if (a + 1) % 2 == (b + 1) % 2 then 0 else 1) + 2 * xorF f ((a + 1) / 2) ((b + 1) / 2)
159
- have h' : (a + 1) / 2 < f ∨ (b + 1) / 2 < f := by
160
- rcases h with h | h
161
- · exact Or.inl (by omega)
162
- · exact Or.inr (by omega)
163
- rw [ih _ _ h']
164
-
165
- theorem more_fuel_changes_nothing_once_it_exceeds_an_argument :
166
- ∀ k f a b : Nat, (a < f ∨ b < f) → xorF (f + k) a b = xorF f a b := by
167
- intro k
168
- induction k with
169
- | zero => intro f a b _; rfl
170
- | succ k ih =>
171
- intro f a b h
172
- have h' : a < f + k ∨ b < f + k := by
173
- rcases h with h | h
174
- · exact Or.inl (by omega)
175
- · exact Or.inr (by omega)
176
- rw [← Nat.add_assoc, one_more_step_of_fuel_changes_nothing_once_it_exceeds_an_argument _ _ _ h', ih f a b h]
177
-
178
- theorem xor_reads_the_same_at_every_sufficient_fuel :
179
- ∀ g a b : Nat, (a < g ∨ b < g) → xorN a b = xorF g a b := by
180
- intro g a b h
181
- unfold xorN
182
- have h1 : a < a + b + 1 ∨ b < a + b + 1 := Or.inl (by omega)
183
- rw [← more_fuel_changes_nothing_once_it_exceeds_an_argument g (a + b + 1) a b h1,
184
- ← more_fuel_changes_nothing_once_it_exceeds_an_argument (a + b + 1) g a b h, Nat.add_comm g]
185
-
186
- theorem a_number_xored_with_itself_is_zero_at_every_fuel : ∀ f b : Nat, xorF f b b = 0 := by
187
- intro f
188
- induction f with
189
- | zero => intro b; cases b <;> rfl
190
- | succ f ih =>
191
- intro b
192
- cases b with
193
- | zero => rfl
194
- | succ b =>
195
- show (if (b + 1) % 2 == (b + 1) % 2 then 0 else 1) + 2 * xorF f ((b + 1) / 2) ((b + 1) / 2) = 0
196
- rw [ih, the_xor_of_two_bits_is_their_sum_mod_two]
197
- omega
198
-
199
- theorem xor_splits_off_its_lowest_bit :
200
- ∀ g x c : Nat, 1 ≤ g → xorF (g + 1) x c = (x + c) % 2 + 2 * xorF g (x / 2) (c / 2) := by
201
- intro g x c hg
202
- obtain ⟨g', rfl⟩ : ∃ g', g = g' + 1 := ⟨g - 1, by omega⟩
203
- cases x with
204
- | zero =>
205
- rw [show xorF (g' + 1 + 1) 0 c = c by cases c <;> rfl, Nat.zero_div,
206
- show xorF (g' + 1) 0 (c / 2) = c / 2 by cases (c / 2) <;> rfl]
207
- omega
208
- | succ x =>
209
- cases c with
210
- | zero =>
211
- rw [show xorF (g' + 1 + 1) (x + 1) 0 = x + 1 from rfl, Nat.zero_div,
212
- show xorF (g' + 1) ((x + 1) / 2) 0 = (x + 1) / 2 by cases ((x + 1) / 2) <;> rfl]
213
- omega
214
- | succ c =>
215
- show (if (x + 1) % 2 == (c + 1) % 2 then 0 else 1) + 2 * xorF (g' + 1) ((x + 1) / 2) ((c + 1) / 2) = _
216
- rw [the_xor_of_two_bits_is_their_sum_mod_two]
217
-
218
- theorem xor_undoes_itself_when_the_fuel_suffices :
219
- ∀ f a b g : Nat, (a < f ∨ b < f) → b < g → xorF g (xorF f a b) b = a := by
220
- intro f
221
- induction f with
222
- | zero => intro a b g h; rcases h with h | h <;> exact absurd h (Nat.not_lt_zero _)
223
- | succ f ih =>
224
- intro a b g h hg
225
- cases a with
226
- | zero =>
227
- rw [show xorF (f + 1) 0 b = b by cases b <;> rfl]
228
- exact a_number_xored_with_itself_is_zero_at_every_fuel g b
229
- | succ a =>
230
- cases b with
231
- | zero =>
232
- obtain ⟨g', rfl⟩ : ∃ g', g = g' + 1 := ⟨g - 1, by omega⟩
233
- rfl
234
- | succ b =>
235
- obtain ⟨g', rfl⟩ : ∃ g', g = g' + 1 := ⟨g - 1, by omega⟩
236
- have hf : (a + 1) / 2 < f ∨ (b + 1) / 2 < f := by
237
- rcases h with h | h
238
- · exact Or.inl (by omega)
239
- · exact Or.inr (by omega)
240
- have ih' := ih ((a + 1) / 2) ((b + 1) / 2) g' hf (by omega)
241
- rw [xor_splits_off_its_lowest_bit g' _ _ (by omega)]
242
- rw [show xorF (f + 1) (a + 1) (b + 1) = (if (a + 1) % 2 == (b + 1) % 2 then 0 else 1) +
243
- 2 * xorF f ((a + 1) / 2) ((b + 1) / 2) from rfl, the_xor_of_two_bits_is_their_sum_mod_two]
244
- generalize xorF f ((a + 1) / 2) ((b + 1) / 2) = y at ih' ⊢
245
- have e : ((a + 1 + (b + 1)) % 2 + 2 * y) / 2 = y := by omega
246
- rw [e, ih']
247
- omega
248
-
249
- theorem xor_is_commutative_for_every_a_b : ∀ a b : Nat, xorN a b = xorN b a := by
250
- intro a b
251
- unfold xorN
252
- rw [Nat.add_comm a b, xor_commutes_at_every_fuel]
253
-
254
- theorem xor_zero_is_identity_for_every_a : ∀ a : Nat, xorN a 0 = a := by
255
- intro a
256
- unfold xorN
257
- cases a <;> rfl
258
-
259
- theorem xor_is_its_own_inverse_for_every_a_b : ∀ a b : Nat, xorN (xorN a b) b = a := by
260
- intro a b
261
- rw [xor_reads_the_same_at_every_sufficient_fuel (b + 1) (xorN a b) b (Or.inr (by omega))]
262
- unfold xorN
263
- exact xor_undoes_itself_when_the_fuel_suffices (a + b + 1) a b (b + 1) (Or.inl (by omega)) (by omega)
264
- theorem xor_is_the_sum_of_the_bits_plus_twice_the_xor_of_the_halves :
265
- ∀ a b : Nat, xorN a b = (a + b) % 2 + 2 * xorN (a / 2) (b / 2) := by
266
- intro a b
267
- rw [xor_reads_the_same_at_every_sufficient_fuel (a + b + 1 + 1) a b (Or.inl (by omega)),
268
- xor_splits_off_its_lowest_bit (a + b + 1) a b (by omega),
269
- ← xor_reads_the_same_at_every_sufficient_fuel (a + b + 1) (a / 2) (b / 2) (Or.inl (by omega))]
270
-
271
- theorem xor_is_associative_below_every_bound :
272
- ∀ n a b c : Nat, a + b + c ≤ n → xorN (xorN a b) c = xorN a (xorN b c) := by
273
- intro n
274
- induction n with
275
- | zero =>
276
- intro a b c h
277
- have ha : a = 0 := by omega
278
- have hb : b = 0 := by omega
279
- have hc : c = 0 := by omega
280
- subst ha hb hc
281
- rfl
282
- | succ n ih =>
283
- intro a b c h
284
- if hz : a + b + c = 0 then
285
- have ha : a = 0 := by omega
286
- have hb : b = 0 := by omega
287
- have hc : c = 0 := by omega
288
- subst ha hb hc
289
- rfl
290
- else
291
- have ihh := ih (a / 2) (b / 2) (c / 2) (by omega)
292
- have hab := xor_is_the_sum_of_the_bits_plus_twice_the_xor_of_the_halves a b
293
- have hbc := xor_is_the_sum_of_the_bits_plus_twice_the_xor_of_the_halves b c
294
- have hx2 : xorN a b / 2 = xorN (a / 2) (b / 2) := by omega
295
- have hy2 : xorN b c / 2 = xorN (b / 2) (c / 2) := by omega
296
- rw [xor_is_the_sum_of_the_bits_plus_twice_the_xor_of_the_halves (xorN a b) c,
297
- xor_is_the_sum_of_the_bits_plus_twice_the_xor_of_the_halves a (xorN b c), hx2, hy2, ihh]
298
- omega
299
-
300
- theorem xor_is_associative_for_every_a_b_c : ∀ a b c : Nat, xorN (xorN a b) c = xorN a (xorN b c) := by
301
- intro a b c
302
- exact xor_is_associative_below_every_bound (a + b + c) a b c (Nat.le_refl _)
303
-
304
- theorem the_nim_sum_is_a_gf2_vector_addition_for_every_a_b_c :
305
- ∀ a b c : Nat, xorN a b = xorN b a ∧ xorN (xorN a b) c = xorN a (xorN b c) ∧
306
- xorN (xorN a b) b = a ∧ xorN a 0 = a := by
307
- intro a b c
308
- exact ⟨xor_is_commutative_for_every_a_b a b, xor_is_associative_for_every_a_b_c a b c,
309
- xor_is_its_own_inverse_for_every_a_b a b, xor_zero_is_identity_for_every_a a⟩
310
-
311
- end Nim