zeropoint-node 1.0.4 → 1.0.6
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/CHANGELOG.md +176 -0
- package/CITATION.cff +1 -1
- package/README.md +1 -1
- package/dist/legacy-BEa7tljT.js.map +1 -1
- package/dist/legacy-CV8oTnKM.cjs.map +1 -1
- package/package.json +12 -3
- package/src/0/3/6/9/1/2/4/8/7/5/1/a432.math.ts +14 -6
- package/src/0/3/6/9/1/2/4/8/7/5/1/a432.vbm.path.ts +6 -2
- package/src/0/index.ts +16 -0
- package/src/crypto/ml-kem-768-acvp.json +492 -0
- package/src/crypto/ml-kem.test.ts +140 -0
- package/src/crypto/ml-kem.ts +554 -0
- package/src/quantum/error-correction.ts +69 -16
- package/src/quantum/hybrid.ts +2 -2
- package/src/quantum/simulator.ts +19 -0
- package/src/quantum/superposition-execution.ts +9 -4
- package/src/quantum/tomography.ts +4 -4
- package/src/thermo/free-energy.ts +279 -0
- package/src/thermo/wastewater-energy.ts +204 -0
- package/src/verification/lean-bridge.test.ts +109 -228
- package/src/verification/lean-bridge.ts +748 -153
- package/src/crypto/kyber-real.test.ts +0 -198
- package/src/crypto/kyber-real.ts +0 -489
|
@@ -1,27 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lean
|
|
2
|
+
* Lean bridge — what is actually checked, and what is only written down.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
4
|
+
* This module used to report "Verified: 2/2", "Confidence: 100.0%" and
|
|
5
|
+
* "Production Grade (Formally Verified)". None of it was measured. The hash
|
|
6
|
+
* covered the theorem's NAME rather than its proof; `verifyProofCertificate`
|
|
7
|
+
* tested that some strings were non-empty and that a hash was 16 characters,
|
|
8
|
+
* which is true of every certificate this file can construct; `lean_version`
|
|
9
|
+
* was asserted although no Lean has ever run here; and seven of the thirteen
|
|
10
|
+
* Lean scripts below end in `sorry`, which is Lean for "not proved".
|
|
9
11
|
*
|
|
10
|
-
*
|
|
12
|
+
* The scripts are kept verbatim — they were never the problem. What changed is
|
|
13
|
+
* that a certificate now carries two independent, separately reported facts:
|
|
14
|
+
*
|
|
15
|
+
* lean_status what the Lean source actually is: a script, a `sorry`
|
|
16
|
+
* placeholder, an axiom, or absent. Derived by reading the
|
|
17
|
+
* script, not declared.
|
|
18
|
+
* seal whether a RECOMPUTABLE predicate for that theorem ran and
|
|
19
|
+
* held, against the simulator in `src/quantum/`. Not a proof of
|
|
20
|
+
* the general theorem — a decision on a concrete instance.
|
|
21
|
+
*
|
|
22
|
+
* A theorem counts as verified here only when its seal holds. `sorry` scripts
|
|
23
|
+
* with a passing seal are reported as sealed-but-not-proved, because a checked
|
|
24
|
+
* instance is not a proof, and an unchecked proof script is not evidence.
|
|
25
|
+
* Nothing in this file claims Lean was invoked, because it was not.
|
|
26
|
+
*
|
|
27
|
+
* To make this honest at the Lean level someone must build the Lean
|
|
28
|
+
* development these scripts gesture at and run `lake build` in CI. Until then
|
|
29
|
+
* the seals are the real content and the scripts are documentation.
|
|
11
30
|
*/
|
|
12
31
|
|
|
13
32
|
import { createHash } from 'node:crypto'
|
|
33
|
+
import { digitalRoot, throughVoid, bearingForDigit, VORTEX_SEQUENCE, VORTEX_ORBIT, VORTEX_AXIS } from '../0/index.ts'
|
|
34
|
+
import { angleForDigit } from '../0/3/6/9/1/2/4/8/7/5/1/a432.math.ts'
|
|
35
|
+
import {
|
|
36
|
+
GIBBS_FORMATION,
|
|
37
|
+
GIBBS_SPLITTING,
|
|
38
|
+
ENTHALPY_FORMATION,
|
|
39
|
+
ENTHALPY_SPLITTING,
|
|
40
|
+
reversiblePotentialMicrovolts,
|
|
41
|
+
thermoneutralPotentialMicrovolts,
|
|
42
|
+
roundTrip,
|
|
43
|
+
selfTest as thermoSelfTest,
|
|
44
|
+
SCALE,
|
|
45
|
+
ELECTRONS,
|
|
46
|
+
FARADAY,
|
|
47
|
+
reversiblePotentialExact,
|
|
48
|
+
thermoneutralPotentialExact,
|
|
49
|
+
energyFromPotential,
|
|
50
|
+
} from '../thermo/free-energy.ts'
|
|
51
|
+
import {
|
|
52
|
+
balanceFor,
|
|
53
|
+
breakEvenCod,
|
|
54
|
+
TYPICAL_LOADS,
|
|
55
|
+
TREATMENT_DEMAND_DECIJOULES_PER_LITRE,
|
|
56
|
+
selfTest as wastewaterSelfTest,
|
|
57
|
+
} from '../thermo/wastewater-energy.ts'
|
|
58
|
+
import {
|
|
59
|
+
zeroState,
|
|
60
|
+
applyGate1,
|
|
61
|
+
isNormalized,
|
|
62
|
+
qft,
|
|
63
|
+
iqft,
|
|
64
|
+
grover,
|
|
65
|
+
groverIterations,
|
|
66
|
+
shor,
|
|
67
|
+
measureSyndromeRepetition,
|
|
68
|
+
STEANE_CODE,
|
|
69
|
+
symplecticProduct,
|
|
70
|
+
estimateSurfaceCodeThreshold,
|
|
71
|
+
executeInSuperposition,
|
|
72
|
+
computeInterferencePattern,
|
|
73
|
+
describeQuantumExecution,
|
|
74
|
+
} from '../quantum/index.ts'
|
|
75
|
+
import { ML_KEM_768 } from '../crypto/ml-kem.ts'
|
|
76
|
+
import { sqrt } from '../0/algebra.ts'
|
|
14
77
|
|
|
15
78
|
// ============================================================================
|
|
16
79
|
// PROOF CERTIFICATE TYPES
|
|
17
80
|
// ============================================================================
|
|
18
81
|
|
|
82
|
+
/** What the Lean source for a theorem actually is. Read, never declared. */
|
|
83
|
+
export type LeanStatus = 'script' | 'sorry' | 'axiom' | 'absent'
|
|
84
|
+
|
|
85
|
+
/** Whether a recomputable predicate ran and held for this theorem. */
|
|
86
|
+
export type SealStatus = 'held' | 'failed' | 'none'
|
|
87
|
+
|
|
19
88
|
export interface ProofCertificate {
|
|
20
89
|
readonly theorem_name: string
|
|
21
90
|
readonly statement: string
|
|
22
91
|
readonly proof_script: string
|
|
23
92
|
readonly verified_at: string
|
|
24
|
-
|
|
93
|
+
/** Derived from proof_script — 'sorry' means Lean would reject it. */
|
|
94
|
+
readonly lean_status: LeanStatus
|
|
95
|
+
/** 'none' when no executable predicate exists for this theorem. */
|
|
96
|
+
readonly seal: SealStatus
|
|
97
|
+
/** What the seal actually computes, so a reader can judge its weight. */
|
|
98
|
+
readonly seal_basis: string
|
|
99
|
+
/** Content address of statement + script. Changing either changes this. */
|
|
25
100
|
readonly hash: string
|
|
26
101
|
}
|
|
27
102
|
|
|
@@ -137,225 +212,745 @@ export const LEAN_PROOFS = {
|
|
|
137
212
|
axiom lwe_hardness : ¬ (polynomial_time_solves_lwe 768 3329)
|
|
138
213
|
`,
|
|
139
214
|
} as const
|
|
140
|
-
|
|
141
215
|
// ============================================================================
|
|
142
|
-
//
|
|
216
|
+
// SEALS - recomputable predicates, the only thing here that counts as checked
|
|
143
217
|
// ============================================================================
|
|
144
218
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
statement: 'IsUnitary hadamard',
|
|
150
|
-
property: 'unitary' as const,
|
|
151
|
-
},
|
|
152
|
-
PauliX: {
|
|
153
|
-
theorem_name: 'pauliX_unitary',
|
|
154
|
-
statement: 'IsUnitary pauliX',
|
|
155
|
-
property: 'unitary' as const,
|
|
156
|
-
},
|
|
157
|
-
}
|
|
219
|
+
// 1/sqrt(2) via the repo's algebra, not ambient Math.
|
|
220
|
+
const SQRT1_2 = 1 / sqrt(2)
|
|
221
|
+
type C = { re: number; im: number }
|
|
222
|
+
const c = (re: number, im = 0): C => ({ re, im })
|
|
158
223
|
|
|
159
|
-
|
|
224
|
+
const H: [C, C, C, C] = [c(SQRT1_2), c(SQRT1_2), c(SQRT1_2), c(-SQRT1_2)]
|
|
225
|
+
const X: [C, C, C, C] = [c(0), c(1), c(1), c(0)]
|
|
226
|
+
const Y: [C, C, C, C] = [c(0), c(0, -1), c(0, 1), c(0)]
|
|
160
227
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
hash: computeProofHash(info.theorem_name),
|
|
170
|
-
}
|
|
228
|
+
const CLOSE = 1e-9
|
|
229
|
+
const near = (a: number, b: number): boolean => a - b < CLOSE && b - a < CLOSE
|
|
230
|
+
|
|
231
|
+
interface Seal {
|
|
232
|
+
/** One line a reader can check the predicate against. */
|
|
233
|
+
readonly basis: string
|
|
234
|
+
/** Decides a concrete instance. Must be able to return false. */
|
|
235
|
+
readonly decide: () => boolean
|
|
171
236
|
}
|
|
172
237
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
238
|
+
/**
|
|
239
|
+
* Every seal decides an INSTANCE, never the universally quantified theorem.
|
|
240
|
+
* hadamard_squared checks H^2 = I on both computational basis states of one
|
|
241
|
+
* qubit, which for a linear map is the whole story; grover_speedup checks a
|
|
242
|
+
* success probability at one problem size, which is NOT the asymptotic claim.
|
|
243
|
+
* The basis string says which is which so the distinction cannot be lost.
|
|
244
|
+
*/
|
|
245
|
+
export const SEALS: Record<string, Seal> = {
|
|
246
|
+
hadamard_squared: {
|
|
247
|
+
basis: 'H applied twice to each basis state of one qubit returns the input amplitudes (linearity makes 2 states exhaustive)',
|
|
248
|
+
decide: () => {
|
|
249
|
+
for (const start of [0, 1]) {
|
|
250
|
+
let reg = zeroState(1)
|
|
251
|
+
if (start === 1) reg = applyGate1(reg, 0, X)
|
|
252
|
+
const twice = applyGate1(applyGate1(reg, 0, H), 0, H)
|
|
253
|
+
for (let i = 0; i < 2; i++) {
|
|
254
|
+
if (!near(twice.amps[i]!.re, reg.amps[i]!.re)) return false
|
|
255
|
+
if (!near(twice.amps[i]!.im, reg.amps[i]!.im)) return false
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return true
|
|
180
259
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
hadamard_unitary: {
|
|
263
|
+
basis: 'H preserves the norm of a 3-qubit register (unitary maps are exactly the norm-preserving ones)',
|
|
264
|
+
decide: () => {
|
|
265
|
+
let reg = zeroState(3)
|
|
266
|
+
for (const q of [0, 1, 2]) reg = applyGate1(reg, q, H)
|
|
267
|
+
return isNormalized(reg)
|
|
186
268
|
},
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
pauliX_unitary: {
|
|
272
|
+
basis: 'X applied twice is the identity, and X preserves the norm',
|
|
273
|
+
decide: () => {
|
|
274
|
+
const reg = zeroState(2)
|
|
275
|
+
const twice = applyGate1(applyGate1(reg, 0, X), 0, X)
|
|
276
|
+
return isNormalized(twice) && near(twice.amps[0]!.re, 1)
|
|
192
277
|
},
|
|
193
|
-
}
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
pauli_anticomm: {
|
|
281
|
+
basis: 'XY and YX differ by an overall sign on both basis states of one qubit',
|
|
282
|
+
decide: () => {
|
|
283
|
+
for (const start of [0, 1]) {
|
|
284
|
+
let reg = zeroState(1)
|
|
285
|
+
if (start === 1) reg = applyGate1(reg, 0, X)
|
|
286
|
+
const xy = applyGate1(applyGate1(reg, 0, Y), 0, X)
|
|
287
|
+
const yx = applyGate1(applyGate1(reg, 0, X), 0, Y)
|
|
288
|
+
for (let i = 0; i < 2; i++) {
|
|
289
|
+
if (!near(xy.amps[i]!.re, -yx.amps[i]!.re)) return false
|
|
290
|
+
if (!near(xy.amps[i]!.im, -yx.amps[i]!.im)) return false
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return true
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
born_rule_sum: {
|
|
298
|
+
basis: 'squared amplitudes sum to 1 after a Hadamard layer on 4 qubits',
|
|
299
|
+
decide: () => {
|
|
300
|
+
let reg = zeroState(4)
|
|
301
|
+
for (const q of [0, 1, 2, 3]) reg = applyGate1(reg, q, H)
|
|
302
|
+
const total = reg.amps.reduce((s, a) => s + a.re * a.re + a.im * a.im, 0)
|
|
303
|
+
return near(total, 1)
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
qft_unitary: {
|
|
308
|
+
basis: 'inverse QFT undoes QFT on a 3-qubit register, amplitude by amplitude',
|
|
309
|
+
decide: () => {
|
|
310
|
+
let reg = zeroState(3)
|
|
311
|
+
reg = applyGate1(reg, 0, H)
|
|
312
|
+
reg = applyGate1(reg, 2, X)
|
|
313
|
+
const back = iqft(qft(reg))
|
|
314
|
+
for (let i = 0; i < back.amps.length; i++) {
|
|
315
|
+
if (!near(back.amps[i]!.re, reg.amps[i]!.re)) return false
|
|
316
|
+
if (!near(back.amps[i]!.im, reg.amps[i]!.im)) return false
|
|
317
|
+
}
|
|
318
|
+
return true
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
|
|
322
|
+
grover_amplification: {
|
|
323
|
+
basis: 'Grover leaves the marked state with probability above the 1/N a random guess gets (n=4, N=16)',
|
|
324
|
+
decide: () => {
|
|
325
|
+
const n = 4
|
|
326
|
+
const target = 11
|
|
327
|
+
const out = grover(n, target, groverIterations(1 << n))
|
|
328
|
+
const p = out.amps[target]!.re ** 2 + out.amps[target]!.im ** 2
|
|
329
|
+
return p > 1 / (1 << n)
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
grover_speedup: {
|
|
334
|
+
basis: 'INSTANCE ONLY, not the asymptotic bound: round((pi/4)*sqrt(N)) iterations reach probability above 0.9 at N=16',
|
|
335
|
+
decide: () => {
|
|
336
|
+
const n = 4
|
|
337
|
+
const target = 6
|
|
338
|
+
const out = grover(n, target, groverIterations(1 << n))
|
|
339
|
+
const p = out.amps[target]!.re ** 2 + out.amps[target]!.im ** 2
|
|
340
|
+
return p > 9 / 10
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
shor_period_finding: {
|
|
345
|
+
basis: 'INSTANCE ONLY: shor(15, 7) returns non-trivial factors whose product is 15',
|
|
346
|
+
decide: () => {
|
|
347
|
+
const factors = shor(15, 7)
|
|
348
|
+
if (!Array.isArray(factors) || factors.length !== 2) return false
|
|
349
|
+
const [p, q] = factors as [number, number]
|
|
350
|
+
if (p <= 1 || q <= 1 || p >= 15 || q >= 15) return false
|
|
351
|
+
return p * q === 15
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
|
|
355
|
+
repetition_detects_error: {
|
|
356
|
+
basis: 'a clean 3-qubit codeword gives the zero syndrome and a single X error gives a non-zero one, so the syndrome distinguishes them',
|
|
357
|
+
decide: () => {
|
|
358
|
+
// |000> is the logical zero of the repetition code: no error, so the
|
|
359
|
+
// syndrome must be all zero. One X on qubit 0 must show up.
|
|
360
|
+
const clean = measureSyndromeRepetition(zeroState(3))
|
|
361
|
+
if (clean.detected || clean.syndrome.some((b) => b !== 0)) return false
|
|
362
|
+
const flipped = measureSyndromeRepetition(applyGate1(zeroState(3), 0, X))
|
|
363
|
+
return flipped.detected && flipped.syndrome.some((b) => b !== 0)
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
steane_corrects_error: {
|
|
368
|
+
basis: 'Steane [[7,1,3]] is a stabiliser group: exactly n-k = 6 generators, symplectically independent (rank 6), pairwise commuting, and distance 3 corrects floor((d-1)/2) = 1 arbitrary error',
|
|
369
|
+
decide: () => {
|
|
370
|
+
const code = STEANE_CODE
|
|
371
|
+
const n = code.physicalQubits
|
|
372
|
+
const k = code.logicalQubits
|
|
373
|
+
if (n !== 7 || k !== 1 || code.distance !== 3) return false
|
|
374
|
+
if ((code.distance - 1) / 2 < 1) return false
|
|
375
|
+
|
|
376
|
+
const g = code.generators
|
|
377
|
+
// A stabiliser group for [[n,k,d]] needs exactly n - k generators.
|
|
378
|
+
if (g.length !== n - k) return false
|
|
379
|
+
// Every pair must commute, i.e. have symplectic product zero.
|
|
380
|
+
for (let i = 0; i < g.length; i++) {
|
|
381
|
+
for (let j = i + 1; j < g.length; j++) {
|
|
382
|
+
if (symplecticProduct(g[i]!, g[j]!) !== 0) return false
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
// And they must be independent over GF(2), or they fix fewer qubits than
|
|
386
|
+
// claimed. Gaussian elimination on the 2n-bit rows.
|
|
387
|
+
const M = g.map((r) => [...r])
|
|
388
|
+
let rank = 0
|
|
389
|
+
for (let col = 0; col < 2 * n && rank < M.length; col++) {
|
|
390
|
+
let pivot = -1
|
|
391
|
+
for (let r = rank; r < M.length; r++) if (M[r]![col] === 1) { pivot = r; break }
|
|
392
|
+
if (pivot < 0) continue
|
|
393
|
+
const tmp = M[rank]!; M[rank] = M[pivot]!; M[pivot] = tmp
|
|
394
|
+
for (let r = 0; r < M.length; r++) {
|
|
395
|
+
if (r !== rank && M[r]![col] === 1) {
|
|
396
|
+
for (let b = 0; b < 2 * n; b++) M[r]![b] = M[r]![b]! ^ M[rank]![b]!
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
rank++
|
|
400
|
+
}
|
|
401
|
+
return rank === n - k
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
|
|
405
|
+
surface_code_threshold: {
|
|
406
|
+
basis: 'estimateSurfaceCodeThreshold separates the two sides of the 1% threshold: below it reports below, above it does not',
|
|
407
|
+
decide: () => {
|
|
408
|
+
const below = estimateSurfaceCodeThreshold(3, 1 / 1000)
|
|
409
|
+
const above = estimateSurfaceCodeThreshold(3, 1 / 10)
|
|
410
|
+
return below.isBelowThreshold === true && above.isBelowThreshold === false
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
kyber_security: {
|
|
415
|
+
basis: 'the shipped ML-KEM parameters are ML-KEM-768 (ek 1184, dk 2400, ct 1088). NIST puts that at category 3, NOT the 128 the Lean script states.',
|
|
416
|
+
decide: () =>
|
|
417
|
+
ML_KEM_768.encapsulationKeyBytes === 1184 &&
|
|
418
|
+
ML_KEM_768.decapsulationKeyBytes === 2400 &&
|
|
419
|
+
ML_KEM_768.ciphertextBytes === 1088,
|
|
420
|
+
},
|
|
421
|
+
doubling_avoids_the_triad: {
|
|
422
|
+
basis: 'VORTEX_ORBIT and VORTEX_AXIS are pinned to computation, not trusted. gcd(2,9) = 1, so every power of 2 is a unit mod 9 and can never be a multiple of 3; 2 is a primitive root, so its orbit is all six units {1,2,4,5,7,8}; 2^6 = 64 = 1 mod 9 gives period 6, which makes six cases exhaustive rather than sampled. Reflection through the void carries {1,4,7} onto {9,6,3}, so the triad is reachable only by reflecting.',
|
|
423
|
+
decide: () => {
|
|
424
|
+
// Bound to the kernel's own constants, not retyped here. VORTEX_AXIS had
|
|
425
|
+
// no reader anywhere in the repository before this seal, so nothing
|
|
426
|
+
// checked it was the triad at all.
|
|
427
|
+
const TRIAD: readonly number[] = VORTEX_AXIS
|
|
428
|
+
|
|
429
|
+
// Period 6, from 2^6 = 64 = 1 (mod 9). Without this the six cases below
|
|
430
|
+
// would be a sample; with it they are the whole sequence.
|
|
431
|
+
if (digitalRoot(64) !== digitalRoot(1)) return false
|
|
432
|
+
|
|
433
|
+
// The orbit of 2, generated by doubling and folded each step.
|
|
434
|
+
const orbit: number[] = []
|
|
435
|
+
let d = 1
|
|
436
|
+
for (let i = 0; i < 6; i++) {
|
|
437
|
+
orbit.push(d)
|
|
438
|
+
if (TRIAD.includes(d)) return false // a power of two landed on 3, 6 or 9
|
|
439
|
+
d = digitalRoot(d * 2)
|
|
440
|
+
}
|
|
441
|
+
// Six distinct values, and doubling returns to the start: a full cycle.
|
|
442
|
+
if (new Set(orbit).size !== 6 || d !== 1) return false
|
|
443
|
+
|
|
444
|
+
// Those six are exactly the units mod 9 — the residues coprime to 9.
|
|
445
|
+
// Everything else mod 9 is a multiple of 3, which is the triad.
|
|
446
|
+
const units = [1, 2, 4, 5, 7, 8]
|
|
447
|
+
if (orbit.slice().sort((a, b) => a - b).join() !== units.join()) return false
|
|
448
|
+
|
|
449
|
+
// VORTEX_ORBIT must BE the computed orbit, in doubling order — the
|
|
450
|
+
// constant is pinned to the computation rather than trusted.
|
|
451
|
+
if (VORTEX_ORBIT.join() !== orbit.join()) return false
|
|
452
|
+
|
|
453
|
+
// And VORTEX_AXIS must be exactly what the orbit cannot reach: the
|
|
454
|
+
// complement of the orbit in 1..9, in ascending order.
|
|
455
|
+
const complement = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter((n) => !orbit.includes(n))
|
|
456
|
+
if (TRIAD.join() !== complement.join()) return false
|
|
457
|
+
|
|
458
|
+
// VORTEX_SEQUENCE reads orbit then axis, so it is not an arbitrary order.
|
|
459
|
+
if (VORTEX_SEQUENCE.slice(0, orbit.length).join() !== orbit.join()) return false
|
|
460
|
+
if (VORTEX_SEQUENCE.slice(orbit.length).join() !== TRIAD.join()) return false
|
|
461
|
+
|
|
462
|
+
// Reflection is where the triad enters: 1 -> 9, 4 -> 6, 7 -> 3.
|
|
463
|
+
if (throughVoid(1) !== 9 || throughVoid(4) !== 6 || throughVoid(7) !== 3) return false
|
|
464
|
+
|
|
465
|
+
// And it is an involution, so the reading is reversible, not a relabel.
|
|
466
|
+
for (let n = 0; n <= 9; n++) if (throughVoid(throughVoid(n)) !== n) return false
|
|
467
|
+
|
|
468
|
+
// Reflecting the orbit reaches every member of the triad.
|
|
469
|
+
const reflected = orbit.map(throughVoid)
|
|
470
|
+
return TRIAD.every((t) => reflected.includes(t))
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
superposition_reports_its_own_state: {
|
|
474
|
+
basis: "the superposition model's prose must follow its measurement, not assert simultaneity regardless. Collapse is decided by one comparison — interference against the threshold — and the description must claim 'all at once' exactly when that comparison says so. While anything is still open the sequence has not computed all at once, and the text must say that.",
|
|
475
|
+
decide: () => {
|
|
476
|
+
const execution = executeInSuperposition()
|
|
477
|
+
const interference = computeInterferencePattern()
|
|
478
|
+
const text = describeQuantumExecution()
|
|
479
|
+
|
|
480
|
+
// The reported verdict must be the comparison, not a stored string.
|
|
481
|
+
const collapsedByNumbers = interference.working_solution_probability > 85 / 100
|
|
482
|
+
const collapsedByReport = execution.system_correctness === 'collapsed_to_valid'
|
|
483
|
+
if (collapsedByReport !== collapsedByNumbers) return false
|
|
484
|
+
|
|
485
|
+
// The prose takes exactly one of the two branches — never both, never
|
|
486
|
+
// neither, which is what an unconditional closing slogan would do.
|
|
487
|
+
const claimsCollapse = text.includes('COLLAPSED.')
|
|
488
|
+
const admitsOpen = text.includes('STILL SUPERPOSED')
|
|
489
|
+
if (claimsCollapse === admitsOpen) return false
|
|
490
|
+
|
|
491
|
+
// And the branch it takes is the one the measurement licenses.
|
|
492
|
+
if (claimsCollapse !== collapsedByNumbers) return false
|
|
493
|
+
|
|
494
|
+
// When open, it must publish the shortfall rather than only naming it.
|
|
495
|
+
if (admitsOpen && !text.includes('NOT ALL AT ONCE')) return false
|
|
496
|
+
return true
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
merkaba_is_two_mirrored_tetrahedra: {
|
|
500
|
+
basis: "the residues mod 3 cut 1..9 into three triangles, each equilateral on the enneagram (120 degrees apart). Reflection through the void SWAPS {1,4,7} with {3,6,9} and fixes {2,5,8} setwise, with the void root 0 fixed throughout. So {3,6,9,0} and {1,4,7,0} are two tetrahedra sharing exactly the void and carried onto each other by the mirror — a merkaba, of which one tetrahedron is half. From 3 the four vertices are 3 with its two triangle partners and the void.",
|
|
501
|
+
decide: () => {
|
|
502
|
+
const RING = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
503
|
+
const cls = (r: number) => RING.filter((d) => d % 3 === r)
|
|
504
|
+
const up = cls(1) // 1,4,7
|
|
505
|
+
const equator = cls(2) // 2,5,8
|
|
506
|
+
const down = cls(0) // 3,6,9
|
|
507
|
+
const key = (a: readonly number[]) => [...a].sort((x, y) => x - y).join(',')
|
|
508
|
+
|
|
509
|
+
// Three classes of three, partitioning the ring.
|
|
510
|
+
if (up.length !== 3 || equator.length !== 3 || down.length !== 3) return false
|
|
511
|
+
if (key([...up, ...equator, ...down]) !== key(RING)) return false
|
|
512
|
+
|
|
513
|
+
// Each is equilateral on the enneagram: three gaps of 120 degrees.
|
|
514
|
+
for (const t of [up, equator, down]) {
|
|
515
|
+
const b = t.map(bearingForDigit).sort((x, y) => x - y)
|
|
516
|
+
const gaps = [b[1]! - b[0]!, b[2]! - b[1]!, 360 - (b[2]! - b[0]!)]
|
|
517
|
+
if (!gaps.every((g) => g === 120)) return false
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// The mirror swaps the two tetrahedral bases and fixes the equator.
|
|
521
|
+
if (key(up.map(throughVoid)) !== key(down)) return false
|
|
522
|
+
if (key(down.map(throughVoid)) !== key(up)) return false
|
|
523
|
+
if (key(equator.map(throughVoid)) !== key(equator)) return false
|
|
524
|
+
|
|
525
|
+
// The void is the shared apex, and it is the mirror's fixed point.
|
|
526
|
+
if (throughVoid(0) !== 0) return false
|
|
527
|
+
const tetraDown = [...down, 0]
|
|
528
|
+
const tetraUp = [...up, 0]
|
|
529
|
+
if (tetraDown.length !== 4 || tetraUp.length !== 4) return false
|
|
530
|
+
const shared = tetraDown.filter((v) => tetraUp.includes(v))
|
|
531
|
+
if (key(shared) !== '0') return false
|
|
532
|
+
|
|
533
|
+
// The gateway triangle is the axis the kernel already declares, so this
|
|
534
|
+
// is the same structure the vortex constants describe, not a new one.
|
|
535
|
+
if (key(down) !== key(VORTEX_AXIS)) return false
|
|
536
|
+
|
|
537
|
+
// From 3: itself, its two triangle partners, and the void. Four keys.
|
|
538
|
+
const fromThree = [3, ...down.filter((d) => d !== 3), 0]
|
|
539
|
+
return fromThree.length === 4 && key(fromThree) === key(tetraDown)
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
agl_acts_on_the_three_triangles: {
|
|
543
|
+
basis: "AGL(1,Z/9) has order 54 and acts on the three triangles — the cosets of {0,3,6} in Z/9, which are the residue classes the merkaba seal uses. The action is transitive with stabiliser 18 and kernel 9, and the induced permutation group is AGL(1,Z/3) of order 6. So the count three is the index of {0,3,6}, derived from the group rather than assumed: orbit x stabiliser = 3 x 18 = 54.",
|
|
544
|
+
decide: () => {
|
|
545
|
+
const units = [1, 2, 4, 5, 7, 8] // the residues coprime to 9
|
|
546
|
+
const maps: ((x: number) => number)[] = []
|
|
547
|
+
for (const a of units) for (let b = 0; b < 9; b++) maps.push((x) => ((a * x + b) % 9 + 9) % 9)
|
|
548
|
+
if (maps.length !== 54) return false
|
|
549
|
+
|
|
550
|
+
// The three cosets of {0,3,6}. Written as residues, so 9 appears as 0.
|
|
551
|
+
const T = [[1, 4, 7], [2, 5, 8], [3, 6, 0]]
|
|
552
|
+
const key = (xs: readonly number[]) => [...new Set(xs)].sort((x, y) => x - y).join(',')
|
|
553
|
+
if (key([...T[0]!, ...T[1]!, ...T[2]!]) !== '0,1,2,3,4,5,6,7,8') return false
|
|
554
|
+
|
|
555
|
+
// The gateway triangle must be the axis the kernel declares, reduced mod 9.
|
|
556
|
+
if (key(T[2]!) !== key(VORTEX_AXIS.map((d) => d % 9))) return false
|
|
557
|
+
|
|
558
|
+
const index = new Map(T.map((t, i) => [key(t), i]))
|
|
559
|
+
const induced = new Set<string>()
|
|
560
|
+
let fixesAll = 0
|
|
561
|
+
let stabilisesFirst = 0
|
|
562
|
+
for (const f of maps) {
|
|
563
|
+
const image = T.map((t) => index.get(key(t.map(f))))
|
|
564
|
+
// Closure: an affine map must send a coset to a coset.
|
|
565
|
+
if (image.some((v) => v === undefined)) return false
|
|
566
|
+
const word = image.join('')
|
|
567
|
+
induced.add(word)
|
|
568
|
+
if (word === '012') fixesAll++
|
|
569
|
+
if (image[0] === 0) stabilisesFirst++
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Induced group is AGL(1,Z/3); kernel and stabiliser follow from it.
|
|
573
|
+
if (induced.size !== 6) return false
|
|
574
|
+
if (fixesAll !== 9) return false
|
|
575
|
+
if (stabilisesFirst !== 18) return false
|
|
576
|
+
// Transitive on three, so orbit x stabiliser recovers the whole group.
|
|
577
|
+
return 3 * stabilisesFirst === maps.length
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
digit_geometry_is_single_valued: {
|
|
581
|
+
basis: "the two independent digit geometries agree and are injective. a432.math.ts angleForDigit and the kernel's bearingForDigit are written separately — the a432 tree does not import the kernel — so this checks they place all nine digits identically and never put two digits at one bearing. angleForDigit used to map nine digits onto six angles, colliding 3 with 5, 2 with 6 and 8 with 9.",
|
|
582
|
+
decide: () => {
|
|
583
|
+
const RING = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
584
|
+
|
|
585
|
+
// Injective: nine digits, nine distinct bearings, all whole degrees.
|
|
586
|
+
const kernel = RING.map(bearingForDigit)
|
|
587
|
+
if (new Set(kernel).size !== RING.length) return false
|
|
588
|
+
if (!kernel.every((b) => Number.isInteger(b) && b >= 0 && b < 360)) return false
|
|
589
|
+
|
|
590
|
+
// The two definitions must agree digit for digit.
|
|
591
|
+
if (!RING.every((d) => angleForDigit(d) === bearingForDigit(d))) return false
|
|
592
|
+
|
|
593
|
+
// Evenly spaced: consecutive bearings differ by one ninth of a turn.
|
|
594
|
+
const sorted = [...kernel].sort((a, b) => a - b)
|
|
595
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
596
|
+
if (sorted[i]! - sorted[i - 1]! !== 40) return false
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// 9 at the top is what fixes the ring's phase; without it any rotation
|
|
600
|
+
// would satisfy the spacing check above.
|
|
601
|
+
return bearingForDigit(9) === 270 && bearingForDigit(3) === 30
|
|
602
|
+
},
|
|
603
|
+
},
|
|
604
|
+
free_energy_of_splitting_is_positive: {
|
|
605
|
+
basis: "ΔG = ΔH − TΔS for water, from tabulated standard-state values. Formation is −237 kJ/mol and splitting is +237, so splitting must be paid for; the reversible cell potential ΔG/(nF) is 1229 mV and the thermoneutral ΔH/(nF) is 1481 mV, the gap being TΔS. A split-then-burn cycle breaks even at perfect efficiency and loses otherwise — checked exhaustively over the efficiency grid, not sampled. This is the sign of ΔG, not an engineering limit.",
|
|
606
|
+
decide: () => {
|
|
607
|
+
if (thermoSelfTest().length > 0) return false
|
|
608
|
+
|
|
609
|
+
// The sign is the claim. Formation releases work; splitting costs it.
|
|
610
|
+
if (!(GIBBS_FORMATION < 0)) return false
|
|
611
|
+
if (!(GIBBS_SPLITTING > 0)) return false
|
|
612
|
+
|
|
613
|
+
// One ledger, read in two directions — so what splitting costs is
|
|
614
|
+
// exactly what burning returns, before any device takes its cut.
|
|
615
|
+
if (ENTHALPY_SPLITTING !== -ENTHALPY_FORMATION) return false
|
|
616
|
+
if (GIBBS_SPLITTING !== -GIBBS_FORMATION) return false
|
|
617
|
+
|
|
618
|
+
// Free energy is strictly less than enthalpy: TΔS is real and is owed.
|
|
619
|
+
if (!(GIBBS_SPLITTING < ENTHALPY_SPLITTING)) return false
|
|
620
|
+
const rev = reversiblePotentialMicrovolts()
|
|
621
|
+
const thermo = thermoneutralPotentialMicrovolts()
|
|
622
|
+
if (!(thermo > rev)) return false
|
|
623
|
+
|
|
624
|
+
// The perfect cycle breaks even EXACTLY — the boundary case, and the one
|
|
625
|
+
// most favourable to a closed loop.
|
|
626
|
+
const ideal = roundTrip(100, 100, 100)
|
|
627
|
+
if (ideal.net !== 0) return false
|
|
628
|
+
|
|
629
|
+
// And no cycle anywhere on the grid gains. Exhaustive over 5% steps in
|
|
630
|
+
// all three efficiencies: 8000 combinations, none of them sampled.
|
|
631
|
+
//
|
|
632
|
+
// The verdict is recomputed from the two energies rather than read off
|
|
633
|
+
// `gainsEnergy`. Trusting that flag let a mutant hardcode it to false and
|
|
634
|
+
// still pass — a seal must not accept the answer from the thing it is
|
|
635
|
+
// judging. `net` is cross-checked against its own definition for the same
|
|
636
|
+
// reason.
|
|
637
|
+
let checked = 0
|
|
638
|
+
for (let e = 5; e <= 100; e += 5) {
|
|
639
|
+
for (let m = 5; m <= 100; m += 5) {
|
|
640
|
+
for (let g = 5; g <= 100; g += 5) {
|
|
641
|
+
checked++
|
|
642
|
+
const r = roundTrip(e, m, g)
|
|
643
|
+
if (r.net !== r.outputRecovered - r.inputRequired) return false
|
|
644
|
+
if (r.outputRecovered > r.inputRequired) return false
|
|
645
|
+
if (r.gainsEnergy !== r.net > 0) return false
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return checked === 8000
|
|
650
|
+
},
|
|
651
|
+
},
|
|
652
|
+
polluted_water_powers_its_own_cleaning_above_a_threshold: {
|
|
653
|
+
basis: "the described machine works, and the fuel is the pollution rather than the water. Clean water carries zero recoverable energy, so it can only owe the treatment demand; organic load carries 13.9 J per mg COD, and above a threshold of about 4200 mg/L the electricity generated exceeds what membrane treatment consumes. Municipal sewage sits below that line and dairy or manure effluent well above it. The threshold is found by scanning, so it is the same quantity the balance reports.",
|
|
654
|
+
decide: () => {
|
|
655
|
+
if (wastewaterSelfTest().length > 0) return false
|
|
656
|
+
|
|
657
|
+
// The water itself is not the fuel. At zero load there is nothing to
|
|
658
|
+
// burn, and the plant owes exactly the cost of cleaning.
|
|
659
|
+
const clean = balanceFor(0)
|
|
660
|
+
if (clean.energyInLoad !== 0) return false
|
|
661
|
+
if (clean.electricityGenerated !== 0) return false
|
|
662
|
+
if (clean.netElectricity !== -TREATMENT_DEMAND_DECIJOULES_PER_LITRE) return false
|
|
663
|
+
|
|
664
|
+
// A threshold exists and is a genuine boundary: it exports, and one
|
|
665
|
+
// milligram less does not.
|
|
666
|
+
const t = breakEvenCod()
|
|
667
|
+
if (!(t > 0)) return false
|
|
668
|
+
if (!(balanceFor(t).netElectricity > 0)) return false
|
|
669
|
+
if (balanceFor(t - 1).netElectricity > 0) return false
|
|
670
|
+
|
|
671
|
+
// Monotone in the load — more pollution never yields less electricity.
|
|
672
|
+
let previous = -1
|
|
673
|
+
for (let cod = 0; cod <= 20000; cod += 100) {
|
|
674
|
+
const e = balanceFor(cod).electricityGenerated
|
|
675
|
+
if (e < previous) return false
|
|
676
|
+
previous = e
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Conservation still binds: recovery is strictly below the energy the
|
|
680
|
+
// load contains, because capture and engine efficiency are each < 100%.
|
|
681
|
+
for (const { cod } of TYPICAL_LOADS) {
|
|
682
|
+
if (cod === 0) continue
|
|
683
|
+
const b = balanceFor(cod)
|
|
684
|
+
if (b.electricityGenerated >= b.energyInLoad) return false
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// And the model must still place real streams where they actually fall.
|
|
688
|
+
const strongSewage = TYPICAL_LOADS.find((l) => l.name === 'municipal sewage, strong')
|
|
689
|
+
const dairy = TYPICAL_LOADS.find((l) => l.name === 'dairy processing')
|
|
690
|
+
if (!strongSewage || !dairy) return false
|
|
691
|
+
if (balanceFor(strongSewage.cod).selfPowering) return false
|
|
692
|
+
return balanceFor(dairy.cod).selfPowering
|
|
693
|
+
},
|
|
694
|
+
},
|
|
695
|
+
every_model_inverts: {
|
|
696
|
+
basis: "each quantitative result recomputes a second, independent way and the two agree. Entropy recovered from (ΔH − ΔG)/T must equal the tabulated ΔS exactly; ΔG recovered from the EXACT rational potential must return with zero drift, while the rounded microvolt form is separately held to half a microvolt's worth of energy; and the break-even COD found by SCANNING must equal the one obtained by INVERTING the arithmetic, which is a different computation reaching the same integer. Reflection through the void inverts too, being its own inverse.",
|
|
697
|
+
decide: () => {
|
|
698
|
+
// --- free energy: invert ΔG = ΔH − TΔS to recover the entropy --------
|
|
699
|
+
// The forward pass multiplied T by ΔS; dividing it back out must land on
|
|
700
|
+
// the tabulated figure exactly, with no rounding introduced anywhere.
|
|
701
|
+
const T_CENTIKELVIN = 29815
|
|
702
|
+
const TABULATED_ENTROPY_MILLI = -163305
|
|
703
|
+
const recovered =
|
|
704
|
+
((ENTHALPY_FORMATION - GIBBS_FORMATION) * 1000 * 100) / (T_CENTIKELVIN * SCALE)
|
|
705
|
+
if (recovered !== TABULATED_ENTROPY_MILLI) return false
|
|
706
|
+
|
|
707
|
+
// --- cell potential: invert E = ΔG/(nF) to recover ΔG ----------------
|
|
708
|
+
// Exactly, from the rational form. This used to be a bounded check
|
|
709
|
+
// because the microvolt rounding made an exact inverse impossible; the
|
|
710
|
+
// exact potentials exist so that the demand can be equality.
|
|
711
|
+
if (energyFromPotential(reversiblePotentialExact()) !== GIBBS_SPLITTING) return false
|
|
712
|
+
if (energyFromPotential(thermoneutralPotentialExact()) !== ENTHALPY_SPLITTING) return false
|
|
713
|
+
|
|
714
|
+
// The ROUNDED form still cannot invert exactly, and must not pretend to.
|
|
715
|
+
// Its drift is held to half a microvolt's worth of energy — nF/20 in
|
|
716
|
+
// these units, a derived bound rather than an eyeballed tolerance.
|
|
717
|
+
const microvolts = reversiblePotentialMicrovolts()
|
|
718
|
+
const backToGibbs = (microvolts * ELECTRONS * FARADAY) / 10
|
|
719
|
+
const drift = backToGibbs - GIBBS_SPLITTING
|
|
720
|
+
const magnitude = drift < 0 ? -drift : drift
|
|
721
|
+
if (!(2 * magnitude <= (ELECTRONS * FARADAY) / 10)) return false
|
|
722
|
+
if (!(magnitude * 1000000 < GIBBS_SPLITTING)) return false
|
|
723
|
+
|
|
724
|
+
// --- break-even COD: scanning versus inverting ------------------------
|
|
725
|
+
// balanceFor rounds twice on the way up, so a closed form agreeing with
|
|
726
|
+
// the scan is a real check on both, not a restatement of one.
|
|
727
|
+
const scanned = breakEvenCod()
|
|
728
|
+
const numerator = TREATMENT_DEMAND_DECIJOULES_PER_LITRE * 10000
|
|
729
|
+
const denominator = 139 * 65 * 38
|
|
730
|
+
const exact = numerator / denominator
|
|
731
|
+
const inverted = exact % 1 === 0 ? exact + 1 : exact - (exact % 1) + 1
|
|
732
|
+
if (scanned !== inverted) return false
|
|
733
|
+
|
|
734
|
+
// --- reflection is its own inverse ------------------------------------
|
|
735
|
+
for (let d = 0; d <= 9; d++) if (throughVoid(throughVoid(d)) !== d) return false
|
|
736
|
+
|
|
737
|
+
return true
|
|
738
|
+
},
|
|
739
|
+
},
|
|
740
|
+
}
|
|
194
741
|
|
|
195
|
-
|
|
742
|
+
// ============================================================================
|
|
743
|
+
// PROOF GENERATION
|
|
744
|
+
// ============================================================================
|
|
745
|
+
|
|
746
|
+
/** Read what the Lean source is. A sorry anywhere means Lean would reject it. */
|
|
747
|
+
export function readLeanStatus(script: string): LeanStatus {
|
|
748
|
+
const s = script.trim()
|
|
749
|
+
if (s.length === 0) return 'absent'
|
|
750
|
+
if (/\bsorry\b/.test(s)) return 'sorry'
|
|
751
|
+
if (/^axiom\b/m.test(s)) return 'axiom'
|
|
752
|
+
return 'script'
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Content address of the claim. Covers the statement and the proof script, so
|
|
757
|
+
* editing either changes the hash. The previous version hashed the theorem's
|
|
758
|
+
* NAME, which stayed constant no matter what the proof said.
|
|
759
|
+
*/
|
|
760
|
+
export function computeProofHash(statement: string, proof_script: string): string {
|
|
761
|
+
return createHash('sha256').update(statement).update(' ').update(proof_script).digest('hex').slice(0, 16)
|
|
762
|
+
}
|
|
196
763
|
|
|
764
|
+
/** Run the seal for a theorem, if one exists. */
|
|
765
|
+
export function runSeal(theorem_name: string): { seal: SealStatus; basis: string } {
|
|
766
|
+
const s = SEALS[theorem_name]
|
|
767
|
+
if (s === undefined) return { seal: 'none', basis: 'no executable predicate for this theorem' }
|
|
768
|
+
// A predicate that throws has not held. Letting it escape would turn a failed
|
|
769
|
+
// seal into a crashed process, which reads like an infrastructure problem
|
|
770
|
+
// rather than the negative result it is.
|
|
771
|
+
try {
|
|
772
|
+
return { seal: s.decide() ? 'held' : 'failed', basis: s.basis }
|
|
773
|
+
} catch {
|
|
774
|
+
return { seal: 'failed', basis: s.basis }
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
function baseCertificate(theorem_name: string, statement: string): ProofCertificate {
|
|
779
|
+
const proof_script = LEAN_PROOFS[theorem_name as keyof typeof LEAN_PROOFS] ?? ''
|
|
780
|
+
const { seal, basis } = runSeal(theorem_name)
|
|
197
781
|
return {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
complexity_bound: props.complexity_bound,
|
|
202
|
-
speedup_factor: props.speedup_factor,
|
|
203
|
-
proof_script: LEAN_PROOFS[props.theorem_name as keyof typeof LEAN_PROOFS] || '',
|
|
782
|
+
theorem_name,
|
|
783
|
+
statement,
|
|
784
|
+
proof_script,
|
|
204
785
|
verified_at: new Date().toISOString(),
|
|
205
|
-
|
|
206
|
-
|
|
786
|
+
lean_status: readLeanStatus(proof_script),
|
|
787
|
+
seal,
|
|
788
|
+
seal_basis: basis,
|
|
789
|
+
hash: computeProofHash(statement, proof_script),
|
|
207
790
|
}
|
|
208
791
|
}
|
|
209
792
|
|
|
210
|
-
export function
|
|
211
|
-
const
|
|
212
|
-
'
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
threshold: 0.01,
|
|
222
|
-
min_distance: 3,
|
|
223
|
-
},
|
|
224
|
-
Surface: {
|
|
225
|
-
theorem_name: 'surface_code_threshold',
|
|
226
|
-
statement: 'Surface code corrects arbitrary errors below 1% threshold',
|
|
227
|
-
threshold: 0.01,
|
|
228
|
-
min_distance: 3,
|
|
229
|
-
},
|
|
793
|
+
export function generateGateCertificate(gate: 'Hadamard' | 'PauliX'): GateCertificate {
|
|
794
|
+
const info = {
|
|
795
|
+
Hadamard: { theorem_name: 'hadamard_unitary', statement: 'IsUnitary hadamard', property: 'unitary' as const },
|
|
796
|
+
PauliX: { theorem_name: 'pauliX_unitary', statement: 'IsUnitary pauliX', property: 'unitary' as const },
|
|
797
|
+
}[gate]
|
|
798
|
+
const base = baseCertificate(info.theorem_name, info.statement)
|
|
799
|
+
return {
|
|
800
|
+
...base,
|
|
801
|
+
gate_name: gate,
|
|
802
|
+
property: info.property,
|
|
803
|
+
proof_lines: base.proof_script.split('\n').filter((l) => l.trim().length > 0).length,
|
|
230
804
|
}
|
|
805
|
+
}
|
|
231
806
|
|
|
232
|
-
|
|
233
|
-
|
|
807
|
+
export function generateAlgorithmCertificate(algo: 'Grover' | 'Shor' | 'QFT'): AlgorithmCertificate {
|
|
808
|
+
const info = {
|
|
809
|
+
Grover: { theorem_name: 'grover_speedup', statement: 'Grover search runs in O(sqrt N) time', complexity_bound: 'O(sqrt N)', speedup_factor: 4 },
|
|
810
|
+
// Unsealed: no predicate exists, so no speedup factor is claimed.
|
|
811
|
+
Shor: { theorem_name: 'shor_period_finding', statement: 'Shor finds period r in O(log^3 N) gates', complexity_bound: 'O(log^3 N)', speedup_factor: 0 },
|
|
812
|
+
QFT: { theorem_name: 'qft_unitary', statement: 'QFT is unitary and computable in O(n^2) gates', complexity_bound: 'O(n^2)', speedup_factor: 1 },
|
|
813
|
+
}[algo]
|
|
234
814
|
return {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
min_distance: props.min_distance,
|
|
240
|
-
proof_script: LEAN_PROOFS[props.theorem_name as keyof typeof LEAN_PROOFS] || '',
|
|
241
|
-
verified_at: new Date().toISOString(),
|
|
242
|
-
lean_version: 'v4.8.0',
|
|
243
|
-
hash: computeProofHash(props.theorem_name),
|
|
815
|
+
...baseCertificate(info.theorem_name, info.statement),
|
|
816
|
+
algorithm: algo,
|
|
817
|
+
complexity_bound: info.complexity_bound,
|
|
818
|
+
speedup_factor: info.speedup_factor,
|
|
244
819
|
}
|
|
245
820
|
}
|
|
246
821
|
|
|
822
|
+
export function generateECCertificate(code: 'Repetition[3,1,1]' | 'Steane[7,1,3]' | 'Surface'): ECCertificate {
|
|
823
|
+
const info = {
|
|
824
|
+
'Repetition[3,1,1]': { theorem_name: 'repetition_detects_error', statement: 'Repetition code detects single-qubit errors', threshold: 5 / 100, min_distance: 3 },
|
|
825
|
+
'Steane[7,1,3]': { theorem_name: 'steane_corrects_error', statement: 'Steane code corrects arbitrary single-qubit errors', threshold: 1 / 100, min_distance: 3 },
|
|
826
|
+
Surface: { theorem_name: 'surface_code_threshold', statement: 'Surface code corrects arbitrary errors below 1% threshold', threshold: 1 / 100, min_distance: 3 },
|
|
827
|
+
}[code]
|
|
828
|
+
return { ...baseCertificate(info.theorem_name, info.statement), code, threshold: info.threshold, min_distance: info.min_distance }
|
|
829
|
+
}
|
|
830
|
+
|
|
247
831
|
// ============================================================================
|
|
248
|
-
//
|
|
832
|
+
// VERIFICATION
|
|
249
833
|
// ============================================================================
|
|
250
834
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
835
|
+
/**
|
|
836
|
+
* A certificate is verified when its seal HELD - a predicate ran and could
|
|
837
|
+
* have said no. Structural well-formedness is not verification; the previous
|
|
838
|
+
* implementation returned true for every certificate this file can build.
|
|
839
|
+
*/
|
|
257
840
|
export function verifyProofCertificate(cert: ProofCertificate): boolean {
|
|
258
|
-
|
|
259
|
-
return (
|
|
260
|
-
cert.theorem_name.length > 0 &&
|
|
261
|
-
cert.statement.length > 0 &&
|
|
262
|
-
cert.verified_at.length > 0 &&
|
|
263
|
-
cert.lean_version.startsWith('v4') &&
|
|
264
|
-
cert.hash.length === 16
|
|
265
|
-
)
|
|
841
|
+
return cert.seal === 'held'
|
|
266
842
|
}
|
|
267
843
|
|
|
268
844
|
export function verifyProofChain(certs: ProofCertificate[]): boolean {
|
|
269
|
-
|
|
270
|
-
return certs.every(verifyProofCertificate)
|
|
845
|
+
return certs.length > 0 && certs.every(verifyProofCertificate)
|
|
271
846
|
}
|
|
272
847
|
|
|
273
848
|
// ============================================================================
|
|
274
|
-
//
|
|
849
|
+
// TRANSCRIPT
|
|
275
850
|
// ============================================================================
|
|
276
851
|
|
|
277
852
|
export interface ProofTranscript {
|
|
278
853
|
readonly title: string
|
|
279
854
|
readonly theorems: readonly string[]
|
|
280
855
|
readonly total_lines: number
|
|
281
|
-
readonly
|
|
282
|
-
readonly
|
|
856
|
+
readonly sealed_count: number
|
|
857
|
+
readonly unsealed: readonly string[]
|
|
858
|
+
readonly lean_sorry: readonly string[]
|
|
859
|
+
readonly confidence: number
|
|
283
860
|
readonly timestamp: string
|
|
284
861
|
readonly certificates: ProofCertificate[]
|
|
285
862
|
}
|
|
286
863
|
|
|
287
864
|
export function generateProofTranscript(certs: ProofCertificate[]): ProofTranscript {
|
|
288
|
-
const
|
|
289
|
-
const verified_count = certs.filter(verifyProofCertificate).length
|
|
290
|
-
|
|
865
|
+
const sealed = certs.filter(verifyProofCertificate)
|
|
291
866
|
return {
|
|
292
|
-
title: 'Quantum
|
|
867
|
+
title: 'Quantum system: computational seals (Lean scripts NOT machine-checked)',
|
|
293
868
|
theorems: certs.map((c) => c.theorem_name),
|
|
294
|
-
total_lines,
|
|
295
|
-
|
|
296
|
-
|
|
869
|
+
total_lines: certs.reduce((sum, c) => sum + c.proof_script.split('\n').length, 0),
|
|
870
|
+
sealed_count: sealed.length,
|
|
871
|
+
unsealed: certs.filter((c) => c.seal !== 'held').map((c) => c.theorem_name),
|
|
872
|
+
lean_sorry: certs.filter((c) => c.lean_status === 'sorry').map((c) => c.theorem_name),
|
|
873
|
+
confidence: certs.length === 0 ? 0 : sealed.length / certs.length,
|
|
297
874
|
timestamp: new Date().toISOString(),
|
|
298
875
|
certificates: certs,
|
|
299
876
|
}
|
|
300
877
|
}
|
|
301
878
|
|
|
302
879
|
// ============================================================================
|
|
303
|
-
// SYSTEM
|
|
880
|
+
// SYSTEM REPORT
|
|
304
881
|
// ============================================================================
|
|
305
882
|
|
|
306
883
|
export interface VerificationReport {
|
|
307
|
-
readonly
|
|
308
|
-
readonly
|
|
309
|
-
readonly
|
|
310
|
-
readonly
|
|
884
|
+
readonly gates_sealed: readonly string[]
|
|
885
|
+
readonly algorithms_sealed: readonly string[]
|
|
886
|
+
readonly error_correction_sealed: readonly string[]
|
|
887
|
+
readonly unsealed: readonly string[]
|
|
888
|
+
readonly security_assumptions_stated: readonly string[]
|
|
311
889
|
readonly total_theorems: number
|
|
312
890
|
readonly total_lines_of_proof: number
|
|
313
|
-
readonly
|
|
891
|
+
readonly sealed_fraction: number
|
|
892
|
+
readonly lean_machine_checked: false
|
|
314
893
|
}
|
|
315
894
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
895
|
+
function allCertificates(): ProofCertificate[] {
|
|
896
|
+
return [
|
|
897
|
+
...(['Hadamard', 'PauliX'] as const).map(generateGateCertificate),
|
|
898
|
+
...(['Grover', 'Shor', 'QFT'] as const).map(generateAlgorithmCertificate),
|
|
899
|
+
...(['Repetition[3,1,1]', 'Steane[7,1,3]', 'Surface'] as const).map(generateECCertificate),
|
|
900
|
+
]
|
|
901
|
+
}
|
|
322
902
|
|
|
323
|
-
|
|
324
|
-
const
|
|
903
|
+
export function verifyQuantumSystem(): VerificationReport {
|
|
904
|
+
const gates = (['Hadamard', 'PauliX'] as const).map(generateGateCertificate)
|
|
905
|
+
const algos = (['Grover', 'Shor', 'QFT'] as const).map(generateAlgorithmCertificate)
|
|
906
|
+
const ecs = (['Repetition[3,1,1]', 'Steane[7,1,3]', 'Surface'] as const).map(generateECCertificate)
|
|
907
|
+
const all = [...gates, ...algos, ...ecs]
|
|
908
|
+
const held = (x: ProofCertificate): boolean => x.seal === 'held'
|
|
325
909
|
|
|
326
910
|
return {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
911
|
+
gates_sealed: gates.filter(held).map((x) => x.gate_name),
|
|
912
|
+
algorithms_sealed: algos.filter(held).map((x) => x.algorithm),
|
|
913
|
+
error_correction_sealed: ecs.filter(held).map((x) => x.code),
|
|
914
|
+
unsealed: all.filter((x) => !held(x)).map((x) => x.theorem_name),
|
|
915
|
+
// "stated", not "formalized": lwe_hardness is an axiom, and Kyber's level
|
|
916
|
+
// is a NIST categorisation (ML-KEM-768 is category 3), not a result proved
|
|
917
|
+
// anywhere in this repository.
|
|
918
|
+
security_assumptions_stated: [
|
|
919
|
+
'LWE_hardness (axiom, assumed)',
|
|
920
|
+
'ML-KEM-768 = NIST category 3',
|
|
921
|
+
'SPHINCS_EUF_CMA (not implemented)',
|
|
922
|
+
],
|
|
923
|
+
total_theorems: all.length,
|
|
924
|
+
total_lines_of_proof: all.reduce((s, x) => s + x.proof_script.split('\n').length, 0),
|
|
925
|
+
sealed_fraction: all.filter(held).length / all.length,
|
|
926
|
+
lean_machine_checked: false,
|
|
334
927
|
}
|
|
335
928
|
}
|
|
336
929
|
|
|
337
930
|
// ============================================================================
|
|
338
|
-
//
|
|
931
|
+
// EXPORT FOR PUBLICATION
|
|
339
932
|
// ============================================================================
|
|
340
933
|
|
|
341
934
|
export function exportProofsForZenodo(): object {
|
|
342
935
|
const report = verifyQuantumSystem()
|
|
343
|
-
|
|
344
|
-
const
|
|
345
|
-
const algo_proofs = ['Grover', 'Shor', 'QFT'].map((a) => generateAlgorithmCertificate(a as any))
|
|
346
|
-
const ec_proofs = ['Repetition[3,1,1]', 'Steane[7,1,3]', 'Surface'].map((c) =>
|
|
347
|
-
generateECCertificate(c as any),
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
const transcript = generateProofTranscript([...gate_proofs, ...algo_proofs, ...ec_proofs])
|
|
936
|
+
const transcript = generateProofTranscript(allCertificates())
|
|
937
|
+
const sealed = report.total_theorems - report.unsealed.length
|
|
351
938
|
|
|
352
939
|
return {
|
|
353
940
|
system: 'Quantum Computing System',
|
|
354
|
-
verification_framework:
|
|
355
|
-
|
|
941
|
+
verification_framework:
|
|
942
|
+
'Computational seals in TypeScript. Lean scripts are included as documentation and are NOT machine-checked.',
|
|
943
|
+
seal_report: report,
|
|
356
944
|
proof_transcript: transcript,
|
|
357
|
-
|
|
358
|
-
ready_for_publication: true,
|
|
945
|
+
// This previously read 'Production Grade (Formally Verified)' with
|
|
946
|
+
// ready_for_publication: true, regardless of what had been checked.
|
|
947
|
+
confidence_level: sealed + '/' + report.total_theorems + ' theorems carry a passing computational seal; 0/' + report.total_theorems + ' are machine-checked in Lean',
|
|
948
|
+
ready_for_publication: report.unsealed.length === 0 && report.lean_machine_checked,
|
|
949
|
+
caveats: [
|
|
950
|
+
'Seals decide concrete instances, not universally quantified statements.',
|
|
951
|
+
'No Lean toolchain runs in this repository; lean_status is read from the script text.',
|
|
952
|
+
report.unsealed.length + ' of ' + report.total_theorems + ' theorems have no executable predicate.',
|
|
953
|
+
],
|
|
359
954
|
timestamp: new Date().toISOString(),
|
|
360
955
|
}
|
|
361
956
|
}
|