diff --git a/research/central-factor-packed/BENCHMARK.json b/research/central-factor-packed/BENCHMARK.json new file mode 100644 index 0000000000..f776dbf36f --- /dev/null +++ b/research/central-factor-packed/BENCHMARK.json @@ -0,0 +1,185 @@ +{ + "assignment_seed": 93, + "clock": "time.perf_counter", + "fresh_processes": true, + "implementation_sha256": { + "benchmark.py": "6f054daef039db3e0f3c76f9e0f8d21c79687789c479060cd89f0ef4231a570a", + "packed.py": "42f244d6e81dc5ea038a9dea19ccc803872603a94d5e405de14af8a47a11b9f6", + "verify.py": "1ae95e2077a3dd6eea8d20eac1b6c32022f978f7614d8a7bed3276a2ff2a1667" + }, + "machine": "arm64", + "median_wall_seconds": { + "complete_historical_audit": { + "baseline": 5.629785832948983, + "packed": 3.489217291935347, + "speedup": 1.6134810078928439 + }, + "factor": { + "baseline": 2.185536375036463, + "packed": 0.11921716597862542, + "speedup": 18.332396656940414 + } + }, + "note": "Descriptive local timing; no performance pass/fail threshold. Complete audit includes source admission and full certificate comparison.", + "pairs": 3, + "platform": "macOS-26.5.2-arm64-arm-64bit-Mach-O", + "python": "3.14.6 (main, Jun 10 2026, 10:03:53) [Clang 21.0.0 (clang-2100.0.123.102)]", + "samples": [ + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "baseline", + "pair": 0, + "receipt_sha256": "1c86b30c31a0c24b735dd0be034ee4f3650870c53fd87e7a0e02e856a421d20e", + "scope": "factor", + "seconds": 2.1451282089110464, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 2.185536375036463 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "pair": 0, + "receipt_sha256": "1c86b30c31a0c24b735dd0be034ee4f3650870c53fd87e7a0e02e856a421d20e", + "scope": "factor", + "seconds": 0.07160433300305158, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 0.1152129169786349 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "pair": 1, + "receipt_sha256": "1c86b30c31a0c24b735dd0be034ee4f3650870c53fd87e7a0e02e856a421d20e", + "scope": "factor", + "seconds": 0.07812366692814976, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 0.12545266700908542 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "baseline", + "pair": 1, + "receipt_sha256": "1c86b30c31a0c24b735dd0be034ee4f3650870c53fd87e7a0e02e856a421d20e", + "scope": "factor", + "seconds": 2.07244266604539, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 2.127540541929193 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "baseline", + "pair": 2, + "receipt_sha256": "1c86b30c31a0c24b735dd0be034ee4f3650870c53fd87e7a0e02e856a421d20e", + "scope": "factor", + "seconds": 2.3123182910494506, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 2.3886496250052005 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "pair": 2, + "receipt_sha256": "1c86b30c31a0c24b735dd0be034ee4f3650870c53fd87e7a0e02e856a421d20e", + "scope": "factor", + "seconds": 0.07200662500690669, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 0.11921716597862542 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "baseline", + "pair": 0, + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 5.661211083992384, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 5.70579924993217 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "pair": 0, + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 3.407135499990545, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 3.463569500017911 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "pair": 1, + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 3.4814892079448327, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 3.528779415995814 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "baseline", + "pair": 1, + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 5.577469042036682, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 5.629785832948983 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "baseline", + "pair": 2, + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 5.373669790918939, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 5.414713500067592 + }, + { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "pair": 2, + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 3.444073290913366, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED", + "wall_seconds": 3.489217291935347 + } + ] +} diff --git a/research/central-factor-packed/CLAIM.md b/research/central-factor-packed/CLAIM.md new file mode 100644 index 0000000000..126cb379db --- /dev/null +++ b/research/central-factor-packed/CLAIM.md @@ -0,0 +1,66 @@ +# Seed 93: exact central-factor verification + +- Track: verification engineering; OS assignment seed **93** from + `secrets.randbelow(100)` at 2026-10-13 14:01:44 UTC. +- Base: `47481c89fd30a43f8f882eb4b391e89c29273fd0` (`origin/main`, fetched). +- Local claim: 2026-10-13 14:05 UTC. Expected finish: 14:33 UTC + (01:33 AEDT on October 14); final eight minutes reserved for verification + and handoff. No pinned issue or open sprint coordination issue was present. +- Object: `scripts/experiments/complex_centers.py::verify_factor`, especially + the historical h=26 dyadic central factor's 6,760,000 integer coefficients. +- Hypothesis/method: injectively encode complete coefficient rows in integers + using a proved input-dependent radix, retaining every supplied gather/scatter + entry and all original structural and scalar-charge checks. Compare the full + original receipt and benchmark the same factor and complete historical audit. +- Deliverable: opt-in source-pinned accelerator, radix argument, differential + and corruption controls, reproducible before/after timings, and a focused PR. + No new kappa, construction, search or impossibility claim. + +## Selection and overlap + +Three candidates considered: historical scratch-pooling interval bounds, +historical disjoint-tensor frame traversal, and historical dyadic central +factor coefficient checking. The first already intersects pending +logarithm/interval accelerators #667/#672; the second would require broader +graph changes. The central factor has a small complete exact oracle, +and the original h=26 check measured 3.495 seconds on this host. +The assignment seed also fixes the alternative-basis permutations and the +64 large signed-entry cases, including first/last/random row selection and +parameter choices h=8,10,12,14. Scope diversity comes from the different +verified product, not from rerunning an existing search with a new seed. + +The 717-open-PR snapshot and focused all-state/current searches were checked. +#809 changes this historical factor by a basis shear; this work changes only +verification of supplied factors. #898/#752/#778 use related exact integer +packing for other matrices. Their technique is credited, with no pending code +import. #849 changes a selected scalar replay, #818 changes R420 RREF, #921 +schedules test modules, and #946 handles byte/container portability. None +reserves this coefficient verifier. Closed negative results are not reopened. + +The selected base record is PR890's conditional +`1661957774647029/10^18`, with PR869/870, Hao Yan's PR858 T16 construction, +and PR589 on PR555. It was traced through `selected-result.json`, the current +status/review ledger, `community-frontier890-review.md`, and the literal T21 +construction/proof. Earlier local checkout material described PR799; the new +worktree and exact-base records supersede that initial reading. + +## Result + +Completed: [source, proof and reproduction](README.md), +[exact timings](BENCHMARK.json), and [validation](VALIDATION.md). +The complete historical audit's median fell from 5.629786 s to 3.489217 s +(1.613481x), with byte-identical certificates in all six complete-audit timed +runs. Factor-only median improved 18.332397x. Eleven test groups pass on +Python 3.14.6 normally and under `-O`, and on Python 3.12.12. A minimal offline +relocation and selected-record integrity check pass. No kappa change. + +The final complete snapshot contains 701 open PRs through #948. An immediate +pre-submission refresh also found #949's distinct factory-scale optimum. +New #947 and predecessor +#937 concern changed historical factors/shear optimality, not this verifier; +their exact heads and distinction are credited in NOTICE.md. #809/#898 heads +remain unchanged. No coordination issue is pinned. Main advanced to +`007664306fff84fbb1c9a1b4053b69f439764034`; all 43 inherited pins still match its +Git blobs and PR890 remains selected. The branch keeps its exact starting base. +The implementation was frozen before the final verification phase; no further +investigation or delegated work was launched. diff --git a/research/central-factor-packed/NOTICE.md b/research/central-factor-packed/NOTICE.md new file mode 100644 index 0000000000..465f861d1c --- /dev/null +++ b/research/central-factor-packed/NOTICE.md @@ -0,0 +1,47 @@ +# Attribution and license + +Prepared by **Ross Richardson (@RossRichardson)** with substantial +**OpenAI Codex assistance**, including design, implementation, mathematical +analysis, tests, documentation and automated verification. No independent human +peer review is claimed. This contribution is under the repository's +Apache-2.0 license; see the root `LICENSE`. + +The original dyadic factor, structural validation, receipt schema, side circuit, +phase argument and cost ledger are by **Douglas R. Colkitt**, retained at +`d55bcd62ceb8f322bcf311a5a66e94c3ac7724f0`. The structural/charge checks in +`packed.py` are adapted from his `scripts/experiments/complex_centers.py`; +the baseline and proof sources are retained unchanged and pinned in +`SOURCES.json`. Upstream material retains its own source notices and license. + +Related exact integer-packing verification work, inspected before this change: + +- Curtis Dransfield / @Curtis-D, + [PR752](https://github.com/CrocSwap/integer-mult-bounds/pull/752), + `3603d8d9184995ae1cc67c0f5e01f02f3a1d634e`: quadratic-affine witness replay. +- @merramil, [PR778](https://github.com/CrocSwap/integer-mult-bounds/pull/778), + `f015b04c74801fa330f818d178e809c760fb5469`: single-intersection Gram replay. +- @CubeJerry, [PR898](https://github.com/CrocSwap/integer-mult-bounds/pull/898), + `521c86e7fd4d0fbd1ed4e0524aa26a1e45861477`: Leech-minor byte lanes. + +This contribution applies the related injective-encoding principle to a +different exact obligation: the complete rectangular sparse gather/scatter +product against triple incidence, with an input-dependent signed radix. +No pending PR implementation is imported and no novelty claim is made for +integer packing itself. + +Curtis Dransfield's [PR809](https://github.com/CrocSwap/integer-mult-bounds/pull/809), +`66cabb478385fbaa1a8060123cd57545d703d84e`, researches a basis shear of the same +historical center. It is a construction contribution; this verifier retains +the baseline factor and does not import or certify that PR's changed invoice. +The final overlap check also inspected Ross Richardson's +[PR937](https://github.com/CrocSwap/integer-mult-bounds/pull/937) +(`b303fed6dfe2066dcd78c0d8ed74d2a3b153ba72`) and +[PR947](https://github.com/CrocSwap/integer-mult-bounds/pull/947) +(`b6f6418bdcae748b267cea72a5949d551feb7bb2`). These change the historical +factor and classify a shear family, respectively; their construction/proof +code is not imported or replayed here. + +The accepted frontier is credited in `community-frontier890-review.md`: +Chafik Boukhalfa's T21 composition, Jeremy Kothe's U8 work, Hao Yan's T16 +mechanism, DreamingOfClouds' PR589 on eumemic's PR555, and their predecessors. +This package does not alter their result or establish new source priority. diff --git a/research/central-factor-packed/README.md b/research/central-factor-packed/README.md new file mode 100644 index 0000000000..baac432520 --- /dev/null +++ b/research/central-factor-packed/README.md @@ -0,0 +1,145 @@ +# Exact packed verification of the historical dyadic central factor + +This opt-in tooling contribution checks the same **6,760,000 integer product +entries** as `scripts/experiments/complex_centers.py::verify_factor` at h=26. +It packs complete coefficient rows into exact Python integers. The original +structural checks, scalar-charge checks, and returned receipt are retained. +The complete historical audit is also rerun and compared byte for byte with +`certificates/dyadic-central-factor.json`, including the unchanged side circuit, +phase/frame checks, restoration interfaces, operation invoice and rational +inequalities. Default verifiers and all existing files remain unchanged. + +**Tooling improvement; no new kappa or construction.** The selected conditional +result at base `47481c89fd30a43f8f882eb4b391e89c29273fd0` is PR890's +`1661957774647029/10^18`. The older `2^-31` and `3.6e-8` strings in the reproduced +receipt describe its historical checkpoint, not the accepted frontier. + +Three alternating fresh-process pairs on macOS arm64 / Python 3.14.6 measured +median complete-audit wall time **5.629786 s → 3.489217 s (1.613481×)**. +Factor-only runs, including source admission, factor generation and receipt +comparison, measured **2.185536 s → 0.119217 s (18.332397×)**. Each engine used +the same pinned input in a new interpreter. These are local descriptive +measurements, not a runtime guarantee or a speed threshold; raw samples and +implementation hashes are in `BENCHMARK.json`. Preliminary timings during +orientation are excluded. + +## Reproduce + +From the repository root, with Python 3.11+ and its standard library: + +```sh +python3 -I -B research/central-factor-packed/verify.py +``` + +Expected: `status` is `PASS_CENTRAL_FACTOR_PACKED`, scope is +`complete_historical_audit`, `coefficients_checked` is `6760000`, and +`receipt_sha256` is +`ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1`. +The printed duration varies. This receipt is byte-identical to the original +full audit; the benchmark/result wrapper is a new, explicitly separate record. + +```sh +python3 -I -B research/central-factor-packed/test_packed.py +python3 -I -O -B research/central-factor-packed/test_packed.py +python3 -I -B research/central-factor-packed/verify.py --engine baseline +python3 -I -B research/central-factor-packed/benchmark.py --pairs 3 \ + --output /tmp/central-factor-benchmark.json +``` + +Use a fresh output path. Full audit replay deliberately rejects `-O`, since +some inherited side/phase assertions require it to be absent. The packed +verifier and its differential tests use explicit failure checks and are also +tested under `-O`. `--factor-only` restricts a timing run to factor generation, +factor verification and receipt comparison; it is not a complete audit. + +## Why the packing checks every coefficient + +The supplied sparse gather column for triple T is v(T). The validator requires +each coordinate at most once, with weight -1 or +1. The supplied scatter row +u(S) consists of h exact integers. For all S,T the obligation is + +``` +a(S,T) = sum_i u(S)[i] v(T)[i] = |S intersect T| - 1 = e(S,T). +``` + +Let `M = max_S sum_i abs(u(S)[i])`, using 0 for an empty family. Then +`abs(a(S,T)) <= M`; since S and T are triples, `abs(e(S,T)) <= 2`. +Choose `b = (M+2).bit_length()` and `B = 2**b`. Thus + +``` +abs(a(S,T) - e(S,T)) <= M+2 < B. +``` + +Number all triples T_j in their original order. The verifier constructs + +``` +V_i = sum_j v(T_j)[i] B**j +I_i = sum_{j: i in T_j} B**j +O = sum_j B**j +``` + +and compares `sum_i u(S)[i] V_i` with `sum_{i in S} I_i - O` for **every** S. +Both are exact signed integers. Their difference is +`sum_j d_j B**j` with `abs(d_j) < B`. If this sum is zero, reduction modulo B +implies `d_0 = 0`; dividing by B and repeating proves every `d_j = 0`. +Conversely, coefficient equality plainly gives packed equality. This is an +injective encoding on the possible difference vectors, not a probabilistic +fingerprint. Signed digits need not be normalized or extracted. + +The radix comes from the *supplied* scatter rows, including invalid large +weights; it does not assume that the scalar-charge check will later pass. +The expected row comes solely from the triple incidence relation. The actual +row uses every supplied factor entry; it does not assume the generator's +formula, a particular basis, or any source symmetry. At h=26 the published +factor needs five bits per position. No machine-word overflow is possible. + +The bounded-radix argument is a written mathematical argument. Neither it nor +the finite tests is a formal proof of the complete multiplication theorem. + +## Coverage and negative controls + +- Complete original-verifier comparisons at h=8,10,12,18,26, plus the original + verifier's empty small domains. Equivalent coordinate permutations, sparse + term orderings and sign changes are accepted. +- All **1,344** allowed single scatter-entry replacements at h=8; every one + of its **231** sparse gather terms sign-flipped and separately deleted: + **1,806** rejected corrupt factors, with the original rejection reason. +- Seed-93 cases with signed magnitudes from the `2**2` through `2**199` domain, + first/last positions, + malformed dimensions/types, duplicated/out-of-range coordinates, and a + correct product with an inadmissible scalar charge. +- A swapped-column factor has unchanged row sums. It passes a deliberately + faulty radix-1 kernel and is rejected by the proper radix, demonstrating + sensitivity to an information-losing optimization. +- Original four central-factor/dirty-interface tests run against each engine. + Source, adapter, fixture, upstream, missing-file, incomplete-receipt, + optimized-replay and existing-output controls fail explicitly. No verifier + input is mutated or acceptance cached. + +The test domain is finite and recorded; no search or impossibility theorem is +claimed. The experiment stops after the listed cases and three alternating +fresh-process benchmark pairs for each scope. + +## Pins, integration and limitations + +`SOURCES.json` pins 43 inherited source, test, proof, fixture and upstream files +to the exact base, plus the adapter implementation. All inherited pins were +compared with that base's Git blobs. It includes the original upstream commit +`adc7f1241b42e322a6451854ab7e4b4c146bf78a`. Source admission happens before +imports; the replay also rejects an unlisted imported repository script. + +The adapter replaces only the `verify_factor` reference inside the historical +audit for the duration of that invocation, then restores it. No certificate is +regenerated in place. Source pins and the complete expected receipt must be +updated deliberately if a maintainer wants to support a changed source. +These files establish reproducibility and content binding, not proof that +some third party executed the checks or trust in a maliciously rewritten +manifest and program. + +This package does not accelerate the PR890 supplier/controller replay, change +the selected frontier, or discharge its all-size/compiler, common-label, +mutable-source, hosting, precision/tape, analytic or bit H1-H5 assumptions. +The full repository suite and selected cold replay are outside this isolated +historical adapter's measured coverage. See `VALIDATION.md` and `BENCHMARK.json` +for actual verification and timings, `CLAIM.md` for selection/overlap, and +`NOTICE.md` for source and technique credit. diff --git a/research/central-factor-packed/SOURCES.json b/research/central-factor-packed/SOURCES.json new file mode 100644 index 0000000000..6ec15fd1c9 --- /dev/null +++ b/research/central-factor-packed/SOURCES.json @@ -0,0 +1,54 @@ +{ + "adapter_files": { + "packed.py": "42f244d6e81dc5ea038a9dea19ccc803872603a94d5e405de14af8a47a11b9f6", + "verify.py": "1ae95e2077a3dd6eea8d20eac1b6c32022f978f7614d8a7bed3276a2ff2a1667" + }, + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "files": { + "LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4", + "certificates/dyadic-central-factor.json": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "docs/research/dyadic-central-factor.md": "e97b1dfe11b5eaebacf3f910131e13bcad586ea5fc1af05db23c00ae0eea5c11", + "notes/complex-compression.tex": "10312815290c7bb8ef4db153e30fba13c032bf17ccaf991a34f1aa6340405a0d", + "notes/disjoint-tensor-compression.tex": "528cba56872313b8cd63ff11f523a399dfb3c85cae1a764110ae9d26ac9151ac", + "notes/dyadic-central-factor.tex": "24c0543fb2fd815f114021f929c3efefa1ae79f29c2f7968585bcd4595a96158", + "scripts/audit_complex_centers.py": "166b18f560cd0d520d23fa29ee8147e0ea056358c4268a466ec458195a97a960", + "scripts/binary_phase_frames.py": "4148cfa313cf050ed25296e8db36d35871520b8318fd086c7d1facf0c6af67d7", + "scripts/certify.py": "2348d95008276c5d5764f7e028c3918e484582cd589bd4d9b82919161745e53e", + "scripts/complex_compression.py": "9b6f758a5985ba5d9fdd726fe6556b3d3b4bd9d98aaf8ba06a7bb58093c4c504", + "scripts/exclusion_circuit.py": "b253f9d7318becda1c1f3b24e2287ed44a9c27fcea00cf9d531afb950d0457a0", + "scripts/experiments/complex_centers.py": "3744396587d729253d80980f6310b56e7bf0ea21b165bd178d0d6d4c49faf2e2", + "scripts/experiments/disjoint_tensor.py": "102dd59bf96033f96ba0dab4c2aba77b3a7a73b67b0f96929ff8b20a98b91cd8", + "scripts/general_network_guard.py": "790a2064449afdbffd6dbd4adbcf4a28eaf41931ce7134e4a4e8766f3764270c", + "scripts/incidence_rectangles.py": "5240fd33dcc3096f5685d10ca360186cad36b355a00d55686a4ea4449417d00e", + "scripts/paired_exclusion_circuit.py": "8f05f04cf06217befd6d0ee0f2d7d0c5c5eb32cfab8c9a8ca7917fd6d620b7d2", + "scripts/paired_network.py": "991223dc3c1374284c361ed017e42bf732dd971fa0bea2be2282cfb18257b3f7", + "scripts/prepare_layers.py": "a6e2adc612f264b1c0e51d18ce6315de9ae5e2ae2420aa22e99a22d8bf304947", + "scripts/search_network.py": "3a4faa5037d9b8e7ca5828afac193a96b6966a8b114f14937921795b24ec4f6a", + "scripts/shared_point_circuit.py": "c9bb7a5df92d260a4e3ad532b53e26936730d7c93f7facfb0784957c1e81c8ba", + "scripts/shared_point_network.py": "a85e7f0d8c42d6a27e3846308571ca324a1824ac5c2d59e4daa5c7673c33c697", + "tests/test_complex_centers.py": "cae650330565f0a4465029ab8a645b14e6ed7b9be6442b0db1d0914beeaeb700", + "tests/test_complex_compression.py": "e22e0a339fad8ce2f73312eb7e47a762360f8c1c78122cdd8e0dc85c5fbce99f", + "upstream/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4", + "upstream/README.md": "8d1ceff898a4e0e681679f91c4def485820be9e99f04e4861f2ce601a364723e", + "upstream/build/figures/multiplication-flow.tex": "3654d2728b0c98919d61760e1802804ed616546a747f9167a93e17bb8697f320", + "upstream/build/figures/proof-map.tex": "76d4deacf07bea355412abcfd798c7cbe6dcccef29a4a420a9e2a7b158f23848", + "upstream/build/main.tex": "42f0f506976bc2084374a71e97edc1549689a7accf35dda4db2a18af4f13c1aa", + "upstream/build/references.bib": "33cc2df13ccf85330849e8fb34d4ac7613b23f625787457a5b7b9aa6d7369476", + "upstream/build/sections/00-introduction.tex": "98721f03682ccf1cc7d0850b07adabaa2d8f3afe552e3861753eba9d284d0da0", + "upstream/build/sections/01-history.tex": "798956c8150c31e3e2f5f29c47110d25ce619faad1374f4d3a0f15fa3ee33ead", + "upstream/build/sections/02-streams.tex": "606c80db61cad13aa0c3b6060dc4b88dbbe7ac60cdd831aa93f28d908fd09dab", + "upstream/build/sections/03-motifs.tex": "ed76761194988a01af77ead0ea6469cb5dcd29690ab985a0b5a4006b0f2b69bb", + "upstream/build/sections/04-swap.tex": "412b170ccaab38dba96e95e3cbfae09f4876a9818f8d278776a746b0f8044906", + "upstream/build/sections/05-layers.tex": "20cfc8d12099d4e4ed9e3e7eeb6162edd9b6e0e076f24693364cd24377252594", + "upstream/build/sections/06-transforms.tex": "924316e4bc905066281d8f9e8746a49d8829aeb393688608deb1e61c3c87853c", + "upstream/build/sections/07-resampling.tex": "8a6b91670f9163afb54892489fa2210c77fe1b058f0325ec7d18b44b94be6e2c", + "upstream/build/sections/08-assembly.tex": "763d7945b1e1ec4ebae9b799bcefcc45fa9bae6e2ffad799868a9c3d513dbd4a", + "upstream/build/sections/09-exact-arithmetic.tex": "5714e5d0656c78c6a1fde8d01fd11f1ba856a7ea94149b283bd9a50fdbf516c3", + "upstream/build/sections/10-transposition.tex": "c14ad8d56112f6578678a58211bc8d63c3a4b60e55078ac73bc38f7348e713cb", + "upstream/build/sections/11-grouped-rectangles.tex": "6525cd0a01980e56accfeaf06e9d875bc699197ba42c6e22b69435e352275174", + "upstream/formalization.yaml": "2dcbd0d6e6a22475f53d49bfdfcac9b6d2b470653c332a9f56522f5be166edb9", + "upstream/manifest.json": "16ab13971694cabab09440c47ebf2fc0496a9d35fc3af33950fda3498f8e2392" + }, + "historical_source_commit": "d55bcd62ceb8f322bcf311a5a66e94c3ac7724f0", + "upstream_commit": "adc7f1241b42e322a6451854ab7e4b4c146bf78a" +} diff --git a/research/central-factor-packed/VALIDATION.json b/research/central-factor-packed/VALIDATION.json new file mode 100644 index 0000000000..9338f6ad64 --- /dev/null +++ b/research/central-factor-packed/VALIDATION.json @@ -0,0 +1,36 @@ +{ + "code_sha256": { + "benchmark.py": "6f054daef039db3e0f3c76f9e0f8d21c79687789c479060cd89f0ef4231a570a", + "packed.py": "42f244d6e81dc5ea038a9dea19ccc803872603a94d5e405de14af8a47a11b9f6", + "test_packed.py": "6b86f9f954ee720560680c7de2de748ecfc4ec07ab03cbb697fc22cb00786e32", + "verify.py": "1ae95e2077a3dd6eea8d20eac1b6c32022f978f7614d8a7bed3276a2ff2a1667" + }, + "minimal_relocated_replay": { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 3.7564202080247924, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED" + }, + "python312_replay": { + "base_commit": "47481c89fd30a43f8f882eb4b391e89c29273fd0", + "coefficients_checked": 6760000, + "engine": "packed", + "receipt_sha256": "ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1", + "scope": "complete_historical_audit", + "seconds": 5.29627666703891, + "source_files": 43, + "source_manifest_sha256": "cc1165946c6469f8873ad4fcf8be6698b210411c300314dde8a0319f9b1ad7df", + "status": "PASS_CENTRAL_FACTOR_PACKED" + }, + "selected_record_check": "python3 -B scripts/verify_selected_result.py\nPASS selected record, exact kappa, original source inventory and proof supplement: 1661957774647029/1000000000000000000\n", + "tests": { + "python312_tests": "test_adapter_changes_and_incomplete_receipts_are_rejected (__main__.PackedFactorTests.test_adapter_changes_and_incomplete_receipts_are_rejected) ... ok\ntest_column_swap_exposes_an_underpriced_radix (__main__.PackedFactorTests.test_column_swap_exposes_an_underpriced_radix) ... ok\ntest_equivalent_factors_and_sparse_order_are_accepted (__main__.PackedFactorTests.test_equivalent_factors_and_sparse_order_are_accepted) ... ok\ntest_every_small_scatter_entry_and_gather_sign (__main__.PackedFactorTests.test_every_small_scatter_entry_and_gather_sign) ... EXHAUSTIVE_CONTROLS {\"gather_deletions\": 231, \"gather_signs\": 231, \"scatter_replacements\": 1344}\nok\ntest_full_published_factor_and_parameter_cases (__main__.PackedFactorTests.test_full_published_factor_and_parameter_cases) ... ok\ntest_no_stale_acceptance_after_in_place_mutation (__main__.PackedFactorTests.test_no_stale_acceptance_after_in_place_mutation) ... ok\ntest_optimized_full_audit_and_existing_output_are_rejected (__main__.PackedFactorTests.test_optimized_full_audit_and_existing_output_are_rejected) ... ok\ntest_original_dirty_interface_tests_in_both_modes (__main__.PackedFactorTests.test_original_dirty_interface_tests_in_both_modes) ... ok\ntest_pins_detect_source_fixture_and_upstream_changes (__main__.PackedFactorTests.test_pins_detect_source_fixture_and_upstream_changes) ... ok\ntest_seed93_large_signed_entries_and_end_positions (__main__.PackedFactorTests.test_seed93_large_signed_entries_and_end_positions) ... ok\ntest_structure_types_and_charge_checks (__main__.PackedFactorTests.test_structure_types_and_charge_checks) ... ok\n\n----------------------------------------------------------------------\nRan 11 tests in 9.116s\n\nOK\n", + "python314_optimized_tests": "test_adapter_changes_and_incomplete_receipts_are_rejected (__main__.PackedFactorTests.test_adapter_changes_and_incomplete_receipts_are_rejected) ... ok\ntest_column_swap_exposes_an_underpriced_radix (__main__.PackedFactorTests.test_column_swap_exposes_an_underpriced_radix) ... ok\ntest_equivalent_factors_and_sparse_order_are_accepted (__main__.PackedFactorTests.test_equivalent_factors_and_sparse_order_are_accepted) ... ok\ntest_every_small_scatter_entry_and_gather_sign (__main__.PackedFactorTests.test_every_small_scatter_entry_and_gather_sign) ... EXHAUSTIVE_CONTROLS {\"gather_deletions\": 231, \"gather_signs\": 231, \"scatter_replacements\": 1344}\nok\ntest_full_published_factor_and_parameter_cases (__main__.PackedFactorTests.test_full_published_factor_and_parameter_cases) ... ok\ntest_no_stale_acceptance_after_in_place_mutation (__main__.PackedFactorTests.test_no_stale_acceptance_after_in_place_mutation) ... ok\ntest_optimized_full_audit_and_existing_output_are_rejected (__main__.PackedFactorTests.test_optimized_full_audit_and_existing_output_are_rejected) ... ok\ntest_original_dirty_interface_tests_in_both_modes (__main__.PackedFactorTests.test_original_dirty_interface_tests_in_both_modes) ... ok\ntest_pins_detect_source_fixture_and_upstream_changes (__main__.PackedFactorTests.test_pins_detect_source_fixture_and_upstream_changes) ... ok\ntest_seed93_large_signed_entries_and_end_positions (__main__.PackedFactorTests.test_seed93_large_signed_entries_and_end_positions) ... ok\ntest_structure_types_and_charge_checks (__main__.PackedFactorTests.test_structure_types_and_charge_checks) ... ok\n\n----------------------------------------------------------------------\nRan 11 tests in 8.113s\n\nOK\n", + "python314_tests": "test_adapter_changes_and_incomplete_receipts_are_rejected (__main__.PackedFactorTests.test_adapter_changes_and_incomplete_receipts_are_rejected) ... ok\ntest_column_swap_exposes_an_underpriced_radix (__main__.PackedFactorTests.test_column_swap_exposes_an_underpriced_radix) ... ok\ntest_equivalent_factors_and_sparse_order_are_accepted (__main__.PackedFactorTests.test_equivalent_factors_and_sparse_order_are_accepted) ... ok\ntest_every_small_scatter_entry_and_gather_sign (__main__.PackedFactorTests.test_every_small_scatter_entry_and_gather_sign) ... EXHAUSTIVE_CONTROLS {\"gather_deletions\": 231, \"gather_signs\": 231, \"scatter_replacements\": 1344}\nok\ntest_full_published_factor_and_parameter_cases (__main__.PackedFactorTests.test_full_published_factor_and_parameter_cases) ... ok\ntest_no_stale_acceptance_after_in_place_mutation (__main__.PackedFactorTests.test_no_stale_acceptance_after_in_place_mutation) ... ok\ntest_optimized_full_audit_and_existing_output_are_rejected (__main__.PackedFactorTests.test_optimized_full_audit_and_existing_output_are_rejected) ... ok\ntest_original_dirty_interface_tests_in_both_modes (__main__.PackedFactorTests.test_original_dirty_interface_tests_in_both_modes) ... ok\ntest_pins_detect_source_fixture_and_upstream_changes (__main__.PackedFactorTests.test_pins_detect_source_fixture_and_upstream_changes) ... ok\ntest_seed93_large_signed_entries_and_end_positions (__main__.PackedFactorTests.test_seed93_large_signed_entries_and_end_positions) ... ok\ntest_structure_types_and_charge_checks (__main__.PackedFactorTests.test_structure_types_and_charge_checks) ... ok\n\n----------------------------------------------------------------------\nRan 11 tests in 7.473s\n\nOK\n" + } +} diff --git a/research/central-factor-packed/VALIDATION.md b/research/central-factor-packed/VALIDATION.md new file mode 100644 index 0000000000..4ab5b7570a --- /dev/null +++ b/research/central-factor-packed/VALIDATION.md @@ -0,0 +1,40 @@ +# Verification receipt + +Base: `47481c89fd30a43f8f882eb4b391e89c29273fd0`. Assignment seed: 93. +Executed on October 14, 2026 AEDT (October 13 UTC), macOS arm64. +Raw test output, the cross-version and relocated receipts, and code hashes +are retained in `VALIDATION.json`; benchmark samples are in `BENCHMARK.json`. + +| Check | Result | +| --- | --- | +| Package tests, CPython 3.14.6 | 11 groups pass | +| Package tests, CPython 3.14.6 `-O` | 11 groups pass; full inherited-replay controls run only in normal mode | +| Package tests, CPython 3.12.12 | 11 groups pass | +| Original central-factor tests | All four run with each engine inside each package test run | +| Exhaustive h=8 corruptions | 1,344 scatter replacements + 231 gather sign flips + 231 deletions rejected by both engines | +| Complete h=26 product | All 6,760,000 coefficients checked; identical factor receipt | +| Timed full audits, Python 3.14.6 | Three baseline and three packed fresh processes; identical complete certificate | +| Full packed audit, Python 3.12.12 | Same complete certificate hash | +| Minimal offline relocation | Only pinned inputs and this package copied to a path with spaces; full replay passes from an unrelated cwd | +| `make selected-record-check` | PR890 exact value, original inventory and proof supplements pass | +| Source admission | All 43 inherited pins match base Git objects and refreshed main | + +Every complete replay's certificate SHA256 is +`ffae0f0a22863718e3134a924592dcf4b05e919223323ba536c587c592bfe6a1`. +Timing metadata belongs to the separate wrapper, not that certificate. +The three benchmarked implementation hashes still match the submitted code. + +Controls cover structural/type violations, wrong signs, missing first/last +gather columns, large signed scatter values, equivalent accepted factors, +wrong scalar charges despite correct products, a deliberately faulty radix, +mutable-input reuse, altered/missing inputs and adapter, incomplete/understated +receipts, disabled inherited assertions, and attempted output overwrites. +No optional dependency, network access, optimizer or Git command is needed by +the reproduced package. + +The package is additive and opt-in. No generator, default verifier, inherited +certificate, selected frontier or `upstream/` byte is changed. The full +`make verify`, selected cold replay, Lean and remote CI were not run for this +isolated historical adapter. This receipt does not claim those gates passed. +The written radix argument explains exactness; finite replay does not prove +the full multiplication theorem or discharge inherited conditional assumptions. diff --git a/research/central-factor-packed/benchmark.py b/research/central-factor-packed/benchmark.py new file mode 100644 index 0000000000..54b704569b --- /dev/null +++ b/research/central-factor-packed/benchmark.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +"""Alternate fresh processes on identical pinned inputs, without a speed gate.""" +import argparse +import hashlib +import json +from pathlib import Path +import platform +import statistics +import subprocess +import sys +import time + +HERE = Path(__file__).resolve().parent + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--pairs', type=int, default=3) + parser.add_argument('--output', type=Path, required=True) + args = parser.parse_args() + if args.pairs < 1 or args.output.exists(): + parser.error('Require positive pairs and a new output path') + samples = [] + for scope in ('factor', 'complete_historical_audit'): + receipts = set() + for pair in range(args.pairs): + order = ('baseline', 'packed') if pair % 2 == 0 else ('packed', 'baseline') + for engine in order: + command = [sys.executable, '-I', '-B', str(HERE / 'verify.py'), '--engine', engine] + if scope == 'factor': + command.append('--factor-only') + start = time.perf_counter() + proc = subprocess.run(command, capture_output=True, text=True, check=True) + elapsed = time.perf_counter() - start + result = json.loads(proc.stdout) + if result['scope'] != scope or result['status'] != 'PASS_CENTRAL_FACTOR_PACKED': + raise ValueError('Unexpected benchmark receipt') + receipts.add(result['receipt_sha256']) + samples.append(dict(pair=pair, wall_seconds=elapsed, **result)) + print(scope, pair, engine, f'{elapsed:.6f}s', flush=True) + if len(receipts) != 1: + raise ValueError('Engines produced different receipts') + medians = {} + for scope in ('factor', 'complete_historical_audit'): + times = {engine: statistics.median(x['wall_seconds'] for x in samples + if x['scope'] == scope and x['engine'] == engine) + for engine in ('baseline', 'packed')} + medians[scope] = dict(times, speedup=times['baseline'] / times['packed']) + result = dict(assignment_seed=93, pairs=args.pairs, fresh_processes=True, + python=sys.version, platform=platform.platform(), machine=platform.machine(), + clock='time.perf_counter', median_wall_seconds=medians, samples=samples, + implementation_sha256={p.name: hashlib.sha256(p.read_bytes()).hexdigest() + for p in (HERE / 'packed.py', HERE / 'verify.py', HERE / 'benchmark.py')}, + note='Descriptive local timing; no performance pass/fail threshold. ' + 'Complete audit includes source admission and full certificate comparison.') + with args.output.open('x') as stream: + stream.write(json.dumps(result, indent=2, sort_keys=True) + '\n') + + +if __name__ == '__main__': + main() diff --git a/research/central-factor-packed/packed.py b/research/central-factor-packed/packed.py new file mode 100644 index 0000000000..379b6cc4a5 --- /dev/null +++ b/research/central-factor-packed/packed.py @@ -0,0 +1,62 @@ +"""Exact, injective row packing for the historical dyadic central factor. + +Adapted validation/receipt from Douglas R. Colkitt's complex_centers.py. +Apache-2.0. See README.md for the radix argument and NOTICE.md for credit. +""" +from itertools import combinations + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def _radix_bits(scatter): + # Every gather coordinate is -1, 0 or 1 and appears at most once. + # Thus |actual - expected| <= ||scatter_row||_1 + 2 < 2**bits. + bound = max((sum(abs(x) for x in u) for u in scatter), default=0) + 2 + return bound.bit_length() + + +def verify_factor(f): + """Return the original receipt, checking all entries by exact row packing. + + The supplied factors, not the generator's closed formula, determine the + actual product. Python integers are unbounded; no modular fingerprint, + floating-point tolerance, sample, or cached acceptance is used. + """ + h = f['h'] + triples = list(combinations(range(h), 3)) + n = len(triples) + require(f['triples'] == triples and len(f['gather']) == len(f['scatter']) == n, + 'Wrong triple or factor dimensions') + require(all(len(u) == h and all(type(x) is int for x in u) for u in f['scatter']), + 'Scatter must be integral') + for v in f['gather']: + require(len({i for i, x in v}) == len(v) and + all(type(i) is int and type(x) is int and 0 <= i < h and x in (-1, 1) + for i, x in v), 'Invalid sparse gather') + + bits = _radix_bits(f['scatter']) + gather_columns = [0] * h + incidence_columns = [0] * h + ones = 0 + for j, (T, v) in enumerate(zip(triples, f['gather'])): + place = 1 << (bits * j) + ones += place + for i, x in v: + gather_columns[i] += x * place + for i in T: + incidence_columns[i] += place + for S, u in zip(triples, f['scatter']): + actual = sum(x * column for x, column in zip(u, gather_columns)) + expected = sum(incidence_columns[i] for i in S) - ones + require(actual == expected, 'Central factor coefficient mismatch') + + require(all(x in (-1, 0, 1, 2) for u in f['scatter'] for x in u), + 'Scalar charge requires these dyadic weights') + G = sum(len(v) for v in f['gather']) + R = sum(1 if abs(x) == 2 else 2 for u in f['scatter'] for x in u if x) + return dict(h=h, triples=n, central_roles=h, coefficients_checked=n*n, + integer_product_verified=True, gather_steps=G, scatter_steps=R, + all_scalar_weights_dyadic=True) diff --git a/research/central-factor-packed/test_packed.py b/research/central-factor-packed/test_packed.py new file mode 100644 index 0000000000..8dc4efe700 --- /dev/null +++ b/research/central-factor-packed/test_packed.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +"""Differential, malformed-input and defect-sensitive packing controls.""" +from copy import deepcopy +from fractions import Fraction +import importlib.util +import json +from pathlib import Path +import random +import shutil +import subprocess +import sys +import tempfile +import unittest +from unittest.mock import patch + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +sys.path.insert(0, str(ROOT / 'scripts')) +sys.path.insert(0, str(HERE)) +import packed +import verify +from experiments.complex_centers import factor, verify_factor as reference + + +def outcome(fn, value): + try: + return ('accepted', fn(value)) + except ValueError as error: + return ('rejected', str(error)) + + +class PackedFactorTests(unittest.TestCase): + def compare(self, value, accepted=False): + old = deepcopy(value) + expected = outcome(reference, value) + self.assertEqual(outcome(packed.verify_factor, value), expected) + self.assertEqual(value, old, 'Verifier mutated its input') + self.assertEqual(expected[0], 'accepted' if accepted else 'rejected') + return expected + + def test_full_published_factor_and_parameter_cases(self): + for h in (8, 10, 12, 18, 26): + with self.subTest(h=h): + self.compare(factor(h), accepted=True) + # Match the original verifier even on its vacuous small domains. + for h in (0, 1, 2): + self.compare(dict(h=h, triples=[], gather=[], scatter=[]), accepted=True) + + def test_equivalent_factors_and_sparse_order_are_accepted(self): + for h in (8, 12): + f = factor(h) + permutation = list(range(h)) + random.Random(93 + h).shuffle(permutation) + f['gather'] = [tuple(reversed([(permutation[i], x) for i, x in v])) + for v in f['gather']] + f['scatter'] = [tuple(u[permutation.index(i)] for i in range(h)) + for u in f['scatter']] + self.compare(f, accepted=True) + f = factor(h) + f['gather'] = [tuple((i, -x if i == 1 else x) for i, x in v) + for v in f['gather']] + f['scatter'] = [tuple(-x if i == 1 else x for i, x in enumerate(u)) + for u in f['scatter']] + self.compare(f, accepted=True) + + def test_every_small_scatter_entry_and_gather_sign(self): + base = factor(8) + counts = {'scatter_replacements': 0, 'gather_signs': 0, 'gather_deletions': 0} + for row, u in enumerate(base['scatter']): + for col, before in enumerate(u): + for after in (-1, 0, 1, 2): + if before == after: + continue + f = deepcopy(base) + replacement = list(u) + replacement[col] = after + f['scatter'][row] = tuple(replacement) + self.compare(f) + counts['scatter_replacements'] += 1 + for col, v in enumerate(base['gather']): + for term, (i, x) in enumerate(v): + f = deepcopy(base) + replacement = list(v) + replacement[term] = (i, -x) + f['gather'][col] = tuple(replacement) + self.compare(f) + counts['gather_signs'] += 1 + f['gather'][col] = v[:term] + v[term+1:] + self.compare(f) + counts['gather_deletions'] += 1 + print('EXHAUSTIVE_CONTROLS ' + json.dumps(counts, sort_keys=True), flush=True) + + def test_structure_types_and_charge_checks(self): + cases = [] + for key in ('triples', 'gather', 'scatter'): + f = factor(8) + f[key] = f[key][:-1] + cases.append(f) + for value in (True, Fraction(1, 2), 0.0): + f = factor(8) + f['scatter'][0] = (value,) + f['scatter'][0][1:] + cases.append(f) + for v in (((0, 1), (0, -1)), ((-1, 1),), ((8, 1),), + ((True, 1),), ((0, True),), ((0, 0),), ((0, 2),)): + f = factor(8) + f['gather'][0] = v + cases.append(f) + f = factor(8) + f['scatter'][0] = f['scatter'][0][:-1] + cases.append(f) + f = factor(8) + f['triples'][0], f['triples'][1] = f['triples'][1], f['triples'][0] + cases.append(f) + for f in cases: + self.compare(f) + # Product is correct, but a -2 scatter weight must still be rejected. + f = factor(8) + f['gather'] = [tuple((i, -x if i == 0 else x) for i, x in v) for v in f['gather']] + f['scatter'] = [(-u[0],) + u[1:] for u in f['scatter']] + self.assertEqual(self.compare(f)[1], 'Scalar charge requires these dyadic weights') + + def test_seed93_large_signed_entries_and_end_positions(self): + rng = random.Random(93) + for trial in range(64): + h = rng.choice((8, 10, 12, 14)) + f = factor(h) + row = rng.choice((0, len(f['scatter']) - 1, rng.randrange(len(f['scatter'])))) + col = rng.randrange(h) + u = list(f['scatter'][row]) + u[col] = rng.choice((-1, 1)) * (1 << rng.randrange(2, 200)) + f['scatter'][row] = tuple(u) + self.compare(f) + for where in (0, -1): + f = factor(26) + f['gather'][where] = () + self.compare(f) + + def test_column_swap_exposes_an_underpriced_radix(self): + f = factor(8) + f['gather'][0], f['gather'][1] = f['gather'][1], f['gather'][0] + self.compare(f) + # Deliberately faulty B=1 compares only row sums, losing columns. + # This control would pass that faulty implementation, but fails above. + with patch.object(packed, '_radix_bits', return_value=0): + self.assertEqual(outcome(packed.verify_factor, f)[0], 'accepted') + self.assertEqual(outcome(packed.verify_factor, f)[0], 'rejected') + + def test_no_stale_acceptance_after_in_place_mutation(self): + f = factor(8) + self.compare(f, accepted=True) + f['gather'][-1] = () + self.compare(f) + + def test_pins_detect_source_fixture_and_upstream_changes(self): + pins = verify.admit_sources() + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + for name in pins['files']: + destination = root / name + destination.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(ROOT / name, destination) + verify.admit_sources(root) + for name in ('scripts/experiments/complex_centers.py', verify.FIXTURE, + 'upstream/manifest.json'): + path = root / name + before = path.read_bytes() + path.write_bytes(before + b' ') + with self.assertRaisesRegex(ValueError, 'Source pin mismatch'): + verify.admit_sources(root) + path.write_bytes(before) + (root / 'scripts/audit_complex_centers.py').unlink() + with self.assertRaisesRegex(ValueError, 'Source pin mismatch'): + verify.admit_sources(root) + + def test_adapter_changes_and_incomplete_receipts_are_rejected(self): + with tempfile.TemporaryDirectory() as directory: + here = Path(directory) + for name in ('SOURCES.json', 'packed.py', 'verify.py'): + shutil.copyfile(HERE / name, here / name) + (here / 'packed.py').write_bytes((here / 'packed.py').read_bytes() + b'\n') + with patch.object(verify, 'HERE', here): + with self.assertRaisesRegex(ValueError, 'Adapter pin mismatch'): + verify.admit_sources() + # The inherited side audit contains assertions and its wrapper forbids -O. + if __debug__: + import audit_complex_centers as audit + expected = json.loads((ROOT / verify.FIXTURE).read_text()) + for field in ('central_factor', 'scalar_charge', 'side_phase_frames'): + broken = deepcopy(expected) + del broken[field] + with patch.object(audit, 'certificate', return_value=broken): + with self.assertRaisesRegex(ValueError, 'Complete historical certificate mismatch'): + verify.replay() + broken = deepcopy(expected) + broken['central_factor']['coefficients_checked'] -= 1 + with patch.object(audit, 'certificate', return_value=broken): + with self.assertRaisesRegex(ValueError, 'Complete historical certificate mismatch'): + verify.replay() + + def test_optimized_full_audit_and_existing_output_are_rejected(self): + result = subprocess.run([sys.executable, '-I', '-O', '-B', str(HERE / 'verify.py')], + capture_output=True, text=True) + self.assertNotEqual(result.returncode, 0) + self.assertIn('requires Python assertions', result.stderr) + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / 'existing.json' + path.write_text('preserve me') + result = subprocess.run([sys.executable, '-I', '-B', str(HERE / 'verify.py'), + '--output', str(path)], capture_output=True, text=True) + self.assertNotEqual(result.returncode, 0) + self.assertIn('Output already exists', result.stderr) + self.assertEqual(path.read_text(), 'preserve me') + + def test_original_dirty_interface_tests_in_both_modes(self): + sys.path.insert(0, str(ROOT / 'tests')) + import experiments.complex_centers as centers + for engine in (reference, packed.verify_factor): + with patch.object(centers, 'verify_factor', engine): + spec = importlib.util.spec_from_file_location('original_center_tests', + ROOT / 'tests/test_complex_centers.py') + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + result = unittest.TestResult() + unittest.defaultTestLoader.loadTestsFromModule(module).run(result) + self.assertEqual(result.testsRun, 4) + self.assertTrue(result.wasSuccessful(), result.errors + result.failures) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/research/central-factor-packed/verify.py b/research/central-factor-packed/verify.py new file mode 100644 index 0000000000..fe0341b677 --- /dev/null +++ b/research/central-factor-packed/verify.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Opt-in complete historical audit with a pinned exact central-factor adapter.""" +import argparse +import hashlib +import json +from pathlib import Path +import sys +import time + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +BASE = '47481c89fd30a43f8f882eb4b391e89c29273fd0' +FIXTURE = 'certificates/dyadic-central-factor.json' + + +def sha(data): + return hashlib.sha256(data).hexdigest() + + +def admit_sources(root=ROOT): + pins = json.loads((HERE / 'SOURCES.json').read_text()) + if pins['base_commit'] != BASE: + raise ValueError('Wrong base commit') + for name, expected in pins['files'].items(): + path = root / name + if not path.is_file() or sha(path.read_bytes()) != expected: + raise ValueError('Source pin mismatch: ' + name) + for name, expected in pins['adapter_files'].items(): + if sha((HERE / name).read_bytes()) != expected: + raise ValueError('Adapter pin mismatch: ' + name) + return pins + + +def replay(engine='packed', factor_only=False): + if not __debug__: + raise ValueError('Full inherited audit requires Python assertions; omit -O') + started = time.perf_counter() + pins = admit_sources() + sys.path.insert(0, str(ROOT / 'scripts')) + sys.path.insert(0, str(HERE)) + import audit_complex_centers as audit + import experiments.complex_centers as original + import packed + verifier = {'baseline': original.verify_factor, 'packed': packed.verify_factor}[engine] + if factor_only: + receipt = verifier(original.factor(26)) + expected = json.loads((ROOT / FIXTURE).read_text())['central_factor'] + if receipt != expected: + raise ValueError('Central-factor receipt mismatch') + raw = (json.dumps(receipt, indent=2, sort_keys=True) + '\n').encode() + else: + # audit imports this single function by name. All other implementation + # and source hashing stay original, and the patch is confined to this call. + previous = audit.verify_factor + try: + audit.verify_factor = verifier + receipt = audit.serializable(audit.certificate()) + finally: + audit.verify_factor = previous + raw = (json.dumps(receipt, indent=2, sort_keys=True) + '\n').encode() + if raw != (ROOT / FIXTURE).read_bytes(): + raise ValueError('Complete historical certificate mismatch') + # Detect an incomplete manifest or unexpected imported repository module. + for module in list(sys.modules.values()): + path = getattr(module, '__file__', None) + if path is None: + continue + path = Path(path).resolve() + if path.is_relative_to(ROOT / 'scripts'): + name = path.relative_to(ROOT).as_posix() + if name not in pins['files']: + raise ValueError('Unpinned imported module: ' + name) + return dict(status='PASS_CENTRAL_FACTOR_PACKED', engine=engine, + scope='factor' if factor_only else 'complete_historical_audit', + base_commit=BASE, coefficients_checked=2600**2, + receipt_sha256=sha(raw), source_files=len(pins['files']), + source_manifest_sha256=sha((HERE / 'SOURCES.json').read_bytes()), + seconds=time.perf_counter() - started) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--engine', choices=('baseline', 'packed'), default='packed') + parser.add_argument('--factor-only', action='store_true') + parser.add_argument('--output', type=Path, help='New result file; existing files are never replaced') + args = parser.parse_args() + if args.output is not None and args.output.exists(): + parser.error('Output already exists') + result = replay(args.engine, args.factor_only) + encoded = json.dumps(result, indent=2, sort_keys=True) + '\n' + if args.output is not None: + with args.output.open('x') as stream: + stream.write(encoded) + print(encoded, end='') + + +if __name__ == '__main__': + main()