diff --git a/research/ck-sign-normalization-seed22/CLAIM.json b/research/ck-sign-normalization-seed22/CLAIM.json new file mode 100644 index 0000000000..e41da699e0 --- /dev/null +++ b/research/ck-sign-normalization-seed22/CLAIM.json @@ -0,0 +1,30 @@ +{ + "track": "complex supplier", + "assignment_seed": 22, + "randomness": "secrets.randbelow(100), backed by OS randomness", + "base_commit": "f567884aeb8851b6e794af1184119a3bfbe1e631", + "object": "Historical PR626 CK scalar primitive lowering: deferred register negations inside same-frame scalar runs, with explicit signed-state restoration at every boundary", + "method": "Symbolic sign-state compiler, exact rational replay, full primitive accounting including boundary flushes. All runs in both orientations; no random search.", + "expected_deliverable": "Scoped finite circuit improvement or exact zero-gain result, executable checker and deterministic receipt; no new kappa", + "expected_finish_utc": "2026-10-13T12:46:00Z", + "coordination": "No pinned issues returned by GitHub pinnedIssues query; open issues 650 and 913 are not sprint coordination issues. Local claim.", + "candidates_considered": [ + { + "task": "JP8 known-zero coefficient-work clears", + "decision": "Reject duplicate: PR839" + }, + { + "task": "SW4 pre-read insertion slides", + "decision": "Reject duplicate: PR910" + }, + { + "task": "CK same-frame signed primitive-state normalization", + "decision": "Chosen: distinct from signed coefficient routes PR860 and Horner coefficient PR837" + } + ], + "seed_diversification": "Selected the historical CK member of the CK/JP8 pair; completed every scalar run in both orientations. Does not claim novelty from seed alone.", + "status": "Completed finite circuit construction: 224 real primitives saved per orientation; exact primary and independent verification and mutation controls pass.", + "result_url": "https://github.com/CrocSwap/integer-mult-bounds/pull/919", + "completed_utc": "2026-10-13T12:33:47Z", + "final_overlap": "707-PR full snapshot through917 plus immediate new-arrival refresh through918 (carry-grade audit, distinct); no duplicate found." +} diff --git a/research/ck-sign-normalization-seed22/EXPECTED.json b/research/ck-sign-normalization-seed22/EXPECTED.json new file mode 100644 index 0000000000..fc65672d75 --- /dev/null +++ b/research/ck-sign-normalization-seed22/EXPECTED.json @@ -0,0 +1,400 @@ +{ + "assignment_seed": 22, + "base_commit": "f567884aeb8851b6e794af1184119a3bfbe1e631", + "kappa": "unchanged", + "programs": { + "backward": { + "baseline_primitive_sha256": "e342c630489789aa7e2aa938d8740ffc63d267d2420994be902893e7d9b50bf4", + "baseline_real_primitives": 169634, + "baseline_tags_per_component": { + "add": 12118, + "clear": 21467, + "copy": 15226, + "double": 5585, + "halve": 19499, + "negate": 348, + "subtract": 10574 + }, + "candidate_primitive_sha256": "30fdb5a6c9c29be8a2255a98c9c9d4bef4abb9e880f0c78522ea36ac74d64200", + "candidate_real_primitives": 169410, + "candidate_tags_per_component": { + "add": 11831, + "clear": 21467, + "copy": 15226, + "double": 5585, + "halve": 19499, + "negate": 236, + "subtract": 10861 + }, + "changed_runs": [ + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 52, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 10282 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 81, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 10481 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 110, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 10680 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 139, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 10879 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 168, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11079 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 197, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11279 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 226, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11479 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 255, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11679 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 284, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11879 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 313, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 12079 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 342, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 12279 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 371, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 12479 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 400, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 12678 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 429, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 12877 + } + ], + "events": 27256, + "formal_input_columns": 725, + "fractional_bits_max": [ + 8, + 8 + ], + "logical_columns": 716, + "non_scalar_events": 5320, + "non_scalar_sha256": "531e05a4b8b8a471ecabf5d842f31546daf8b39020be4a29423b6807c0748956", + "paid_profile": { + "1": 2596, + "2": 552, + "3": 304, + "4": 160, + "5": 70, + "6": 8, + "8": 8 + }, + "prefix_row_l1_max": [ + "4847", + "4847" + ], + "private_input_columns": 9, + "real_saved": 224, + "run_savings_census": { + "0": 2205, + "16": 14 + }, + "runs": 2219, + "scalar_macros": 21936 + }, + "forward": { + "baseline_primitive_sha256": "16ae874e3352c4df265026f62db95359a30399f1edc4c1b151d564d71902380c", + "baseline_real_primitives": 169618, + "baseline_tags_per_component": { + "add": 11919, + "clear": 21459, + "copy": 15234, + "double": 5585, + "halve": 19499, + "negate": 348, + "subtract": 10765 + }, + "candidate_primitive_sha256": "a4d57ec12e582cf26deb849606d0518b8f7fdf351936adb6b61135f1c11ad904", + "candidate_real_primitives": 169394, + "candidate_tags_per_component": { + "add": 12206, + "clear": 21459, + "copy": 15234, + "double": 5585, + "halve": 19499, + "negate": 236, + "subtract": 10478 + }, + "changed_runs": [ + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 52, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 10282 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 81, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 10481 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 110, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 10680 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 139, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 10879 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 168, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11079 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 197, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11279 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 226, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11479 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 255, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11679 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 284, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 11879 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 313, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 12079 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 290, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 274, + "frame": 342, + "real_saved": 16, + "scalar_macros": 76, + "start_event": 12279 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 371, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 12479 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 400, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 12678 + }, + { + "baseline_negations_per_component": 12, + "baseline_real_primitives": 282, + "boundary_negations_per_component": 4, + "candidate_real_primitives": 266, + "frame": 429, + "real_saved": 16, + "scalar_macros": 75, + "start_event": 12877 + } + ], + "events": 27256, + "formal_input_columns": 725, + "fractional_bits_max": [ + 3, + 3 + ], + "logical_columns": 716, + "non_scalar_events": 5320, + "non_scalar_sha256": "abd97762e9fadfec126b381bbfff9e32a6e2c396da9f03b42bbefdb4d4781eba", + "paid_profile": { + "1": 2596, + "2": 552, + "3": 304, + "4": 160, + "5": 70, + "6": 8, + "8": 8 + }, + "prefix_row_l1_max": [ + "5120", + "5120" + ], + "private_input_columns": 9, + "real_saved": 224, + "run_savings_census": { + "0": 2205, + "16": 14 + }, + "runs": 2219, + "scalar_macros": 21936 + } + }, + "status": "PASS_CK_SIGN_NORMALIZATION" +} diff --git a/research/ck-sign-normalization-seed22/INDEPENDENT.json b/research/ck-sign-normalization-seed22/INDEPENDENT.json new file mode 100644 index 0000000000..6c29379336 --- /dev/null +++ b/research/ck-sign-normalization-seed22/INDEPENDENT.json @@ -0,0 +1,57 @@ +{ + "controls": { + "boundary_segmentation": "frame, nonscalar, and end boundaries retained", + "clear_reset_cost": "primitive count differs", + "endpoint_neutral_prefix_growth": "prefix row outside signed baseline", + "lost_copy_sign": "full endpoint operator differs", + "missed_source_sign_flip": "prefix row outside signed baseline", + "omitted_boundary_flush": "full endpoint operator differs" + }, + "programs": { + "backward": { + "all_prefix_rows_contained_modulo_sign": true, + "all_run_endpoint_operators_equal": true, + "baseline_real_primitives": 169634, + "candidate_real_primitives": 169410, + "largest_independent_input_basis": 547, + "max_run_basis_denominator_exponent_candidate": 6, + "max_run_basis_denominator_exponent_reference": 6, + "max_run_basis_prefix_l1_candidate": { + "denominator": 1, + "numerator": 4145 + }, + "max_run_basis_prefix_l1_reference": { + "denominator": 1, + "numerator": 4145 + }, + "primitive_word_sha256": "30fdb5a6c9c29be8a2255a98c9c9d4bef4abb9e880f0c78522ea36ac74d64200", + "run_boundaries_sha256": "7b190d3bb13aa5fae007fe88a1407c9186a91eb93e3647d949eaa98ceef2a4af", + "saved_real_primitives": 224, + "scalar_macros": 21936, + "scalar_runs": 2219 + }, + "forward": { + "all_prefix_rows_contained_modulo_sign": true, + "all_run_endpoint_operators_equal": true, + "baseline_real_primitives": 169618, + "candidate_real_primitives": 169394, + "largest_independent_input_basis": 547, + "max_run_basis_denominator_exponent_candidate": 4, + "max_run_basis_denominator_exponent_reference": 4, + "max_run_basis_prefix_l1_candidate": { + "denominator": 1, + "numerator": 1034 + }, + "max_run_basis_prefix_l1_reference": { + "denominator": 1, + "numerator": 1034 + }, + "primitive_word_sha256": "a4d57ec12e582cf26deb849606d0518b8f7fdf351936adb6b61135f1c11ad904", + "run_boundaries_sha256": "93cc4bb098e24c6675645daa5e79fa32bb65a3985b8f52fe7691c35a6b57dbc9", + "saved_real_primitives": 224, + "scalar_macros": 21936, + "scalar_runs": 2219 + } + }, + "status": "PASS_CK_SIGN_INDEPENDENT" +} diff --git a/research/ck-sign-normalization-seed22/PROOF.md b/research/ck-sign-normalization-seed22/PROOF.md new file mode 100644 index 0000000000..01011101cd --- /dev/null +++ b/research/ck-sign-normalization-seed22/PROOF.md @@ -0,0 +1,161 @@ +# Boundary-local register-sign normalization + +This note proves the exact-arithmetic local substitution implemented by this +package. It concerns the historical PR626 CK scalar words after the lowering in +`research/complex-dyadic-lowering/lower.py`; it does not establish a new +multiplication exponent or repair inherited physical interfaces. + +Contribution: Ross Richardson (@RossRichardson), with substantial OpenAI Codex assistance. The scalar lowering +is due to Sagar Thakrar with substantial OpenAI Codex assistance; its credited +PR425/433/531, PR622 and PR626 circuit lineage remains applicable. New material +is under the repository's Apache-2.0 license. The present base commit is +`f567884aeb8851b6e794af1184119a3bfbe1e631`. + +## Object and boundaries + +A run consists of consecutive lowered scalar primitives in one unchanged frame. +It ends before every non-scalar event, before any scalar frame change, and at the +end of the program. No sign state may pass one of those boundaries. The +normalizer emits an ordinary finite word over the predecessor's existing +alphabet: clear, copy, double, halve, negate, add and subtract. Sign bookkeeping +is a compile-time calculation and is absent from the emitted circuit. + +Let `x_r` be the logical contents of register `r` in the predecessor circuit and +`y_r` its physical contents in the emitted circuit. Maintain signs +`epsilon_r in {+1,-1}` and the invariant + +``` +x_r = epsilon_r * y_r. +``` + +All signs initially equal `+1`. This statement is about arbitrary values, or +entire symbolic linear rows; it does not assume clean registers, independent +current register values, or any particular input assignment. + +## Inductive transition proof + +For each predecessor primitive, emit the following operation and update only +the listed signs. Here `sigma=+1` denotes add and `sigma=-1` denotes subtract. + +| Predecessor operation | Emitted operation | Sign update | +| --- | --- | --- | +| `x_t <- 0` | `y_t <- 0` | `epsilon_t <- +1` | +| `x_t <- x_s` | `y_t <- y_s` | `epsilon_t <- epsilon_s` | +| `x_t <- 2*x_t` | `y_t <- 2*y_t` | none | +| `x_t <- x_t/2` | `y_t <- y_t/2` | none | +| `x_t <- -x_t` | no operation | `epsilon_t <- -epsilon_t` | +| `x_t <- x_t + sigma*x_s` | `y_t <- y_t + sigma*epsilon_t*epsilon_s*y_s` | none | + +Clear satisfies the invariant because both sides are zero; resetting its sign +also avoids pointless later restoration. Copy satisfies it because +`epsilon_s*y_s=x_s`, including when the target previously had a different sign. +Doubling and halving commute with multiplication by a sign. Negation is exactly +represented by toggling the logical interpretation. For the final row, + +``` +epsilon_t * (y_t + sigma*epsilon_t*epsilon_s*y_s) + = epsilon_t*y_t + sigma*epsilon_s*y_s + = x_t + sigma*x_s, +``` + +using `epsilon_t^2=1`. Thus the invariant holds after every predecessor +primitive. The existing signed-addition alphabet implements either resulting +coefficient without extra source preparation or a helper register. If subtract +were unavailable or had a different cost, the stated cost identity would not +follow. + +At each boundary emit one physical negation for every register whose sign is +negative, then set that sign to `+1`. Since `x_r=-y_r` before that negation, +`x_r=y_r` afterward. Other registers are unchanged. Every register therefore +has exactly the predecessor value before the next event or frame is entered. +The whole-program exact map follows by induction over runs and unchanged +non-scalar events, even if those events are treated as opaque operations. +Boundary negations remain in the outgoing frame, so this argument does not +move an instruction across a frame change or recursive interface. + +## Prefix norm and dirty inputs + +Regard each register as a rational linear row over all original input columns, +including arbitrary dirty helper and coefficient-work columns. At every matched +prefix, the emitted row is the predecessor row multiplied by a sign. Hence its +absolute entries, `l1` norm, reduced denominators, and absolute value on any fixed +input are unchanged. +An omitted logical negation changes no physical magnitude. At a boundary flush, +negating any subset of registers likewise changes no register magnitude. Each +emitted prefix is therefore covered by a predecessor prefix's per-register +absolute-value envelope; the predecessor's maximum row-norm bound still applies. +This is a sign-equivalence argument, not literal membership of an emitted row in +the predecessor's row set. A test demanding literal prefix-row containment would +be stronger than the property established here and can reject valid sign changes. + +Because the complete boundary values agree, helper restoration, coefficient-work +clearing, output shears and source values agree at every preserved interface. +No additional stream, source access, copy, recursive child or frame adapter is +introduced. Flushed negations are real charged operations, not free changes of +representation. The inherited charged payload and rounding/tape realization +remain assumptions; exact row identities alone do not prove an all-size rounded +implementation. + +## Complete scalar cost + +For run `j`, let `C_j` be its predecessor primitive count, `N_j` its number of +negations, and `F_j` the number of negative signs at its ending boundary. +Every non-negation remains one primitive, every predecessor negation is removed, +and every ending negative sign costs one emitted negation. Therefore + +``` +C'_j = C_j - N_j + F_j. +``` + +The complete real-component scalar count is the sum over all runs. Applying the +same real-coefficient word to real and imaginary components gives + +``` +C'_complex = C_complex - 2 * sum_j(N_j - F_j). +``` + +All recursive child multiplicities and non-scalar charges remain unchanged. +Equivalently, if an inherited local recurrence is +`R = sum_i m_i R_i + C_complex + A`, its replacement is +`R' = sum_i m_i R_i + C'_complex + A`, with exactly the same `m_i`, interfaces +and non-scalar charge `A`. This is an accounting identity, not a new asymptotic +recurrence solution. + +Normalization is not universally cheaper. For example, `negate A; copy B,A; +copy C,A` has three predecessor primitives but needs two copies and three +boundary negations under this rule. A claim of savings must check the complete +pinned word, or explicitly choose the original word for unprofitable runs. No +universal savings or optimality follows merely from deleting negation opcodes. + +For each of the two CK orientations in this package, the complete census is +348 predecessor negations and 236 boundary negations per real component. The +resulting saving is `2*(348-236)=224` real primitives per orientation. The receipt +and exact replay, rather than this hand calculation alone, establish that these +counts cover the pinned programs. + +## Discriminating controls + +Useful implementation controls must distinguish endpoint equality, prefix +coverage, boundaries and accounting: + +- Negate a source and then add it to a target: omitting the + `epsilon_t*epsilon_s` coefficient correction produces the wrong linear map. +- Negate a source and copy it to another register: failing to inherit the source + sign produces the wrong copied value when signs are flushed. +- Finish a run with one pending negative register: omitting its boundary + negation breaks the boundary map even if a later run would cancel it. +- Insert `double S; halve S` before an otherwise correct circuit: endpoint + equality survives, but a prefix bound chosen tight at `S` rejects the growth. +- Add an unnecessary pair of negations: endpoints and norms survive, but an + exact primitive count or word hash rejects the extra cost. +- Use the copy-fanout word above as a positive accounting control: the verified + formula must report growth rather than silently count only removed negations. + +Keeping a negative sign after clear is not by itself a semantic counterexample: +zero has either sign. It is a normalization/cost deviation, and should not be +presented as a failed algebraic identity without an additional incorrect step. + +The induction above proves the local algebraic rule for arbitrary finite words +in the stated alphabet and boundary discipline. A finite replay of the two CK +words independently checks the concrete implementation and its coverage; it is +not a formal proof of the full conditional integer-multiplication theorem. diff --git a/research/ck-sign-normalization-seed22/README.md b/research/ck-sign-normalization-seed22/README.md new file mode 100644 index 0000000000..d668cc0d43 --- /dev/null +++ b/research/ck-sign-normalization-seed22/README.md @@ -0,0 +1,150 @@ +# CK helper-run sign normalization + +**Finite complex-supplier circuit construction; no new kappa.** Deferring register +negations inside one scalar frame, then paying every required boundary negation, +saves **224 real primitives per orientation** of the historical PR626 CK word +after Sagar Thakrar's accepted PR696 lowering. + +| Complete scalar projection | PR696 baseline | Replacement | Saved | +| --- | ---: | ---: | ---: | +| Forward | 169,618 | 169,394 | 224 | +| Backward / inverse transpose | 169,634 | 169,410 | 224 | + +Counts include both real and imaginary components, all coefficient preparation, +source reads, copies, clears and boundary restoration. They are instruction +counts, not measured runtime gains. The 21,936 scalar macros are partitioned +into 2,219 maximal same-frame runs in each orientation. Exactly 14 runs save +16 real primitives each; 2,205 have zero cost change and none increases cost. +The changed runs have frames `52 + 29*k`, `0 <= k < 14`, on the helper blocks +within logical registers 224 through 447. Every changed event interval is listed +in [EXPECTED.json](EXPECTED.json). + +The complete paid recursive profile remains +`{1:2596, 2:552, 3:304, 4:160, 5:70, 6:8, 8:8}`. This historical supplier is not +the selected #799 X4 supplier. At the exact base below, the selected conditional +value is **0.001661634653669567**; this package neither changes nor recomputes it. + +## Reproduce + +From the repository root, standard-library Python 3.9+: + +```sh +python3 -I -O -B research/ck-sign-normalization-seed22/check.py +``` + +Expected final line: + +```text +PASS_CK_SIGN_PACKAGE runs=2219+2219 columns=725 saved=224/224 kappa=unchanged +``` + +The command checks the source pins, recomputes both committed receipts, and +compares the independently generated primitive-stream hashes and costs. It is +offline and writes nothing. The exact new circuit is generated by +`compile.optimize_run` applied to each `verify.segments` run of the pinned +program, using the pinned `lower.py`. Each primitive retains that run's frame. +All non-scalar events remain in their original order and are emitted unchanged +when composing these substitutions with the original program. No original +generator, selected certificate, or `upstream/` file is edited. + +Additional adverse and portability checks: + +```sh +python3 -I -O -B research/ck-sign-normalization-seed22/test_package.py +``` + +Expected: three tests pass. They include 56 actual-run deletion/sign mutations, +a copy-fanout accounting case, isolated optimized execution from a minimal +source closure with spaces in its path, alternate gzip encoding, and rejection +of a changed source or forged saving. The independent checker additionally +rejects five toy mutations and checks frame/non-scalar/end segmentation. A +positive segmentation check is not counted as a rejected mutation. + +## Mechanism and complete cost + +Maintain `logical[r] = sign[r] * physical[r]`. A negate toggles the compile-time +sign; signed addition changes sign when its two operands have different signs; +copy inherits its source sign; clear resets it. Emit an actual negate for every +remaining negative sign before a non-scalar event, any scalar frame change, or +the program end. The compiler emits an ordinary fixed primitive circuit; there +is no runtime metadata or additional helper. + +Every non-negation remains one operation, including all operand accesses. +Per real component, each orientation removes 348 negations and pays 236 boundary +negations. The complete reduction is `2*(348-236)=224`. In general this rule can +increase cost when a negated source is copied into several outputs; the package +explicitly tests that case rather than assuming omitted negations are free. + +The [proof](PROOF.md) establishes exact boundary equality and unchanged absolute +prefix envelopes for arbitrary dirty inputs. For an inherited cost +`R = sum_i m_i R_i + C + A`, the substitution changes only `C` to `C-224`; +every child multiplicity `m_i` and the unchanged adapter/frame/hosting charge `A` +is retained. This fixed scalar saving does not change the recursive moment or +justify a new exponent. There is no supplier search or favorable unimplemented +cost model being promoted to a kappa claim. + +## Verification scope + +Two independently written arithmetic interpreters check different bases: + +* The primary Fraction interpreter replays both complete **scalar projections** + on 725 arbitrary initial columns: 716 logical and nine private. It checks + every run boundary, the expected final shear, all helper restoration and + private clearing. Exact scalar-projection prefix row-l1 maxima remain + 5,120 forward and 4,847 backward; fractional depths remain 3 and 8 bits. +* The second interpreter uses normalized integer dyadic rows and an independent + event splitter. Every touched register starts as an independent input at + **each run**, including private work. It checks full endpoint operators and + every candidate prefix row against exact baseline prefix rows modulo sign. + The largest local basis has 547 columns. Its run-input l1 maxima are 1,034 and + 4,145, and denominator exponents 4 and 6. These are different coordinates from + the complete scalar-projection quantities and must not be compared as if they + were competing global bounds. + +Neither interpreter executes Clifford/frame/non-scalar event semantics. The +arbitrary run-input operator equality proves an exact local substitution across +those unchanged opaque boundaries; it is not a fresh native physical replay. +The independent checker shares the pinned predecessor lowering and candidate +compiler, but not the primary interpreter, splitter, or Fraction row arithmetic. +The original 192-bit local allocation is retained, not reduced. Native admission, +typed production integration, physical rounded precision/tape realization, and +fresh owner/invoice/assembly bindings remain separate obligations. All-size +compiler, hosting and analytic assumptions remain inherited. Finite checking +does not formally verify the full integer-multiplication theorem. + +## Provenance, coverage and overlap + +Exact base: `f567884aeb8851b6e794af1184119a3bfbe1e631`. +Historical PR626 source: `660de893d27bb7abd1d5b01b1640207528a5c851`. +Accepted PR696 lowering: `5a3f983715027c4fd83f50bc9001d4b18463bed1`. +[SOURCE-PINS.json](SOURCE-PINS.json) binds every consumed source by SHA256, +using decompressed payloads for gzip inputs. + +The OS-generated assignment seed was **22**, selecting complex-supplier work. +The seed was used to choose CK rather than JP8; within that object, coverage is +the complete deterministic census of both words, not a randomized experiment. +The stopping rule was to check all 4,438 same-frame runs once, then verify and +package the result. No general circuit optimum or impossibility is asserted. +[CLAIM.json](CLAIM.json) records the three candidates and local claim; no pinned +sprint coordination issue existed. + +Inspected related work includes #839's known-zero JP8 clears; #910's SW4 slides; +#750's CK cleanup scale relocation; #807/#816's restored frame-zero CK helper +and target bases; #860's signed coefficient-work routes; #882's bounded JP8 +coefficient circuits; and #883's selected-X4 precondition fusion. This package +instead cancels physical negations across the nonzero-frame helper runs of an +unchanged historical CK macro word. Pending savings are not added together. +The final overlap snapshot and subsequent arrivals are recorded in +[VALIDATION.md](VALIDATION.md). + +Credit Sagar Thakrar's #696 primitive lowering; icekylinx's emitter and circuit +lineage; Jeremy Kothe's #622 CK construction; Chafik Boukhalfa's #626 package; +DreamingOfClouds, eumemic, Rohan Arun and the retained predecessor notices. +The accepted #799/#741 review by the repository maintainers was used to identify +the current frontier and distinguish it from this historical object. + +Contribution by **Ross Richardson (@RossRichardson)** with substantial +**OpenAI Codex assistance** in research, implementation, proof, independent +checker, review and writing. The two implementations and review are AI-assisted; +no independent human review is claimed. New files are Apache-2.0; source notices +and licenses remain unchanged. diff --git a/research/ck-sign-normalization-seed22/SOURCE-PINS.json b/research/ck-sign-normalization-seed22/SOURCE-PINS.json new file mode 100644 index 0000000000..c83f7b7a96 --- /dev/null +++ b/research/ck-sign-normalization-seed22/SOURCE-PINS.json @@ -0,0 +1,12 @@ +{ + "base_commit": "f567884aeb8851b6e794af1184119a3bfbe1e631", + "source_pr626_head": "660de893d27bb7abd1d5b01b1640207528a5c851", + "lowering_pr696_head": "5a3f983715027c4fd83f50bc9001d4b18463bed1", + "hash_semantics": "SHA256 of decompressed payload for gzip, exact bytes otherwise", + "files": { + "research/complex-dyadic-lowering/lower.py": "eb37d00063dc09323e9aca041d23da749ce17fbd71dade9aaf1c059cab0b9753", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/LOCAL-PROGRAMS.json.gz": "854f17274092263dc25e60367f4cd0d29f60a8446becd17cc1883ebed7a97900", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/LOCAL-CHECKS.json": "059c4e59142bdf5c19dc7c0afebcddfec28e6e60cbc7299b8bdcc624afbc0cbe", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/INDEPENDENT-LOCAL-REPLAY.json": "ecefb9e661301d8081522be68bbe6640e175c011eb1177f643383d193c6fb2f0" + } +} diff --git a/research/ck-sign-normalization-seed22/VALIDATION.md b/research/ck-sign-normalization-seed22/VALIDATION.md new file mode 100644 index 0000000000..b5d8b84b62 --- /dev/null +++ b/research/ck-sign-normalization-seed22/VALIDATION.md @@ -0,0 +1,69 @@ +# Validation and handoff + +Tested on macOS arm64, 2026-10-13 UTC, with CPython **3.14.6** and system CPython +**3.9.6**. Both versions pass the complete `check.py` command and all three +`test_package.py` tests under `-I -O -B`. No third-party dependencies are needed. + +The package verifies both orientations and all 4,438 runs. The Fraction scalar +projection and independent integer run-operator implementation agree on exact +emitted-stream digests, complete counts and boundary maps. There are 56 rejected +actual-run mutants (one missing final restoration and one changed add sign per +gain-producing run/orientation), five rejected toy mutations, a positive +boundary-segmentation check and a positive copy-fanout cost-growth check. +The minimal relocated source closure also passes after gzip recompression; +source corruption and a forged saving are rejected. + +`make selected-record-check` passes at the original base. The new files do not +alter the selected result, `upstream/`, any existing generator or certificate. +`git diff --check` passes. A separate AI reviewer found no blocking algebraic or +accounting defect; its minor success-message issue was fixed and the package +rerun. This is AI-assisted review, not independent human peer review. + +The repository-wide `make verify`, selected cold supplier replay, full native +Clifford/frame replay, global admission/owner/invoice/assembly, Lean and remote CI +were **not run**. This standalone finite research package adds no hook to those +paths. The focused checks above exercise its actual changed circuits, while +physical/compiler integration is explicitly outside its claim. No historical +receipt is represented as a fresh full replay. + +## Refreshed source and overlap check + +Original/fixed contribution base: +`f567884aeb8851b6e794af1184119a3bfbe1e631`. +During verification, upstream main advanced to +`91a2094f2e022930069e8cfdc810a3ea1b81cd09`. The eight-file change concerns the +review batch and integration receipt; the selected certificate and current +status are unchanged. All four consumed input hashes were rechecked directly +from this fetched Git tree and match [SOURCE-PINS.json](SOURCE-PINS.json). +The new bounded-review policy was read; this package does not mark any pending +work reviewed or incorporated. + +The submission refresh inspected **707 open PRs through #917**, including titles +and exact heads. Relevant new arrivals: + +| PR | Inspected head | Distinction | +| --- | --- | --- | +| #917, Ross Richardson | `085c32a25e2a09b029fa816195b97fa93d6f0788` | Changes historical CK frame-zero compensation with two-sided bases. This result changes nonzero-frame helper runs; no code or claimed saving is composed. | +| #916, Stephen Shore | `1f0cd934f83ddf2f14f20275ecca072c5b85a7b9` | Admits #883's selected-X4 precondition lowering. This package does not implement or claim that integration. | +| #860, AmazedBot | `72899c888af7e171f8aba4d5c66f4b31a5719eba` | Signed coefficient-work reuse and admission for historical CK. Here the original coefficient lowering and work clearing remain. | +| #750, Sagar Thakrar | `b6d6934092c063ab2575ebee00f48bbc7b1c9d82` | Moves a cleanup scale and changes coefficients. Here macro order and unsigned coefficient preparation remain. | +| #807, David Awad | `b1a5c533a22c2665600102d872f6a84e0664a70d` | Restored helper-basis changes to frame-zero compensation. | +| #816, @dd-hemant | `133735a2cc2319c12ba5d786214b2217e083e7da` | Restored target forest in frame-zero compensation. | +| #882, @mightyOil | `e698981e0ffa680b6c5896dace1609025b97ad70` | Bounded within-macro JP8 synthesis. | +| #883, @mightyOil | `b31a870a3842b37f6ab97767c506ce91783632a2` | Selected-X4 two-register precondition fusion. | + +The live pinned-issues query remained empty. The claim is therefore local; +no separate reservation issue was opened. Original predecessor credits and +licenses are retained. The result is a completed finite circuit contribution, +with an unchanged recurrence profile and no new kappa or global optimum claim. + +## Final handoff + +Submitted as [PR919](https://github.com/CrocSwap/integer-mult-bounds/pull/919). +A minimal export of exact implementation commit +`39b702f14f4ff74b87868257e5358e489e1dfe5c` (12 package files and four pinned +inputs, no Git checkout or cached artifacts) passed both `check.py` and all +package tests. The following commit only adds this handoff and updates the local +claim with the result link; executable code and both receipts are identical. +The immediate pre-submit refresh also saw #918's unrelated carry-grade modulus +audit (`df86cd10f78693061a0a545153d7d6f65dd62c4e`). No pinned sprint issue appeared. diff --git a/research/ck-sign-normalization-seed22/check.py b/research/ck-sign-normalization-seed22/check.py new file mode 100644 index 0000000000..a3fbc186ff --- /dev/null +++ b/research/ck-sign-normalization-seed22/check.py @@ -0,0 +1,39 @@ +"""One-command exact primary and independently implemented CK verification. + +Ross Richardson with substantial OpenAI Codex assistance. Apache-2.0. +""" +import importlib.util +import json +from pathlib import Path + +HERE = Path(__file__).resolve().parent + + +def load(name): + spec = importlib.util.spec_from_file_location("ck_package_" + name, HERE / (name + ".py")) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def main(): + primary = load("verify") + independent = load("check_independent") + actual = primary.verify() + primary.require(primary.canonical(actual) == primary.canonical(primary.read(HERE / "EXPECTED.json")), + "primary receipt differs") + second = independent.verify() + primary.require(primary.canonical(second) == primary.canonical(primary.read(HERE / "INDEPENDENT.json")), + "independent receipt differs") + for direction, row in actual["programs"].items(): + other = second["programs"][direction] + for key in ("baseline_real_primitives", "candidate_real_primitives", "scalar_macros"): + primary.require(row[key] == other[key], "independent count differs: " + key) + primary.require(row["runs"] == other["scalar_runs"], "run coverage differs") + primary.require(row["candidate_primitive_sha256"] == other["primitive_word_sha256"], + "independent primitive stream differs") + print("PASS_CK_SIGN_PACKAGE runs=2219+2219 columns=725 saved=224/224 kappa=unchanged") + + +if __name__ == "__main__": + main() diff --git a/research/ck-sign-normalization-seed22/check_independent.py b/research/ck-sign-normalization-seed22/check_independent.py new file mode 100644 index 0000000000..9432f279ed --- /dev/null +++ b/research/ck-sign-normalization-seed22/check_independent.py @@ -0,0 +1,261 @@ +"""Independent exact dyadic-operator check of pinned CK sign normalization. + +Ross Richardson, with substantial OpenAI Codex assistance. Apache-2.0. +Checks finite scalar runs, not the complete multiplication theorem. The row +interpreter uses no Fraction, production interpreter, or production run splitter. +The shared pinned predecessor lowering uses Fraction. Standard library only. +""" +import argparse +import gzip +import hashlib +import importlib.util +import json +from pathlib import Path + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +PROGRAM = ROOT / 'research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/LOCAL-PROGRAMS.json.gz' +PROGRAM_SHA256 = '854f17274092263dc25e60367f4cd0d29f60a8446becd17cc1883ebed7a97900' +LOWERING = ROOT / 'research/complex-dyadic-lowering/lower.py' +LOWERING_SHA256 = 'eb37d00063dc09323e9aca041d23da749ce17fbd71dade9aaf1c059cab0b9753' + + +def require(ok, message): + if not ok: + raise ValueError(message) + + +def load(path, name): + spec = importlib.util.spec_from_file_location(name, path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def normalize(exponent, coefficients): + """Canonical sparse integer row multiplied by 2**(-exponent).""" + coefficients = {i: n for i, n in coefficients.items() if n} + if not coefficients: + return (0, ()) + powers = [(abs(n) & -abs(n)).bit_length() - 1 for n in coefficients.values()] + common = min(powers) + return (exponent - common, + tuple(sorted((i, n >> common) for i, n in coefficients.items()))) + + +def unsigned(row): + exponent, coefficients = row + if coefficients and coefficients[0][1] < 0: + coefficients = tuple((i, -n) for i, n in coefficients) + return exponent, coefficients + + +def registers(word): + result = set() + for op in word: + tag = op[0] + arity = 3 if tag in ('copy', 'add', 'subtract') else 2 + require(tag in ('clear', 'copy', 'add', 'subtract', 'double', 'halve', 'negate'), + 'unknown primitive') + require(len(op) == arity, 'primitive arity') + for reg in op[1:]: + require(isinstance(reg, tuple) and len(reg) == 2, 'register encoding') + result.add(reg) + return result + + +def step(rows, op): + tag, target = op[:2] + exponent, coefficients = rows[target] + if tag == 'clear': + rows[target] = (0, ()) + elif tag == 'copy': + rows[target] = rows[op[2]] + elif tag == 'negate': + rows[target] = (exponent, tuple((i, -n) for i, n in coefficients)) + elif tag in ('double', 'halve'): + rows[target] = (exponent + (1 if tag == 'halve' else -1), coefficients) if coefficients else (0, ()) + elif tag in ('add', 'subtract'): + other_exponent, other_coefficients = rows[op[2]] + common_exponent = max(exponent, other_exponent) + values = {i: n << (common_exponent - exponent) for i, n in coefficients} + sign = 1 if tag == 'add' else -1 + for i, n in other_coefficients: + values[i] = values.get(i, 0) + sign * (n << (common_exponent - other_exponent)) + rows[target] = normalize(common_exponent, values) + else: + raise ValueError('unknown primitive') + + +def norm(row): + exponent, coefficients = row + return sum(abs(n) for _, n in coefficients), exponent + + +def larger_norm(left, right): + common = max(left[1], right[1]) + return left if left[0] << (common - left[1]) >= right[0] << (common - right[1]) else right + + +def norm_receipt(value): + numerator, exponent = value + while numerator and numerator % 2 == 0: + numerator //= 2 + exponent -= 1 + return {'numerator': numerator << max(0, -exponent), + 'denominator': 1 << max(0, exponent)} + + +def compare(reference, candidate, exact_count=None): + """All touched inputs are independent, including every private register. + + Besides the endpoint operator, check exact per-register prefix containment + modulo sign. This implies preservation of each baseline absolute coefficient + envelope for this run. Containment uses exact tuples, never digest equality. + """ + touched = registers(reference) + require(registers(candidate) <= touched, 'candidate introduced register') + initial = {reg: (0, ((i, 1),)) for i, reg in enumerate(sorted(touched))} + expected, actual = initial.copy(), initial.copy() + seen = {reg: {unsigned(row)} for reg, row in initial.items()} + reference_norm = candidate_norm = (1, 0) if touched else (0, 0) + reference_denominator = candidate_denominator = 0 + for primitive in reference: + step(expected, primitive) + target = primitive[1] + seen[target].add(unsigned(expected[target])) + reference_norm = larger_norm(reference_norm, norm(expected[target])) + reference_denominator = max(reference_denominator, expected[target][0]) + for primitive in candidate: + step(actual, primitive) + target = primitive[1] + require(unsigned(actual[target]) in seen[target], 'prefix row outside signed baseline') + candidate_norm = larger_norm(candidate_norm, norm(actual[target])) + candidate_denominator = max(candidate_denominator, actual[target][0]) + require(actual == expected, 'full endpoint operator differs') + if exact_count is not None: + require(len(candidate) == exact_count, 'primitive count differs') + return {'basis': len(touched), 'reference_norm': reference_norm, + 'candidate_norm': candidate_norm, + 'reference_denominator': reference_denominator, + 'candidate_denominator': candidate_denominator} + + +def split_events(events, lower): + """Maximal consecutive scalar events at a single frame, independently split.""" + runs, current, frame, start = [], [], None, None + for index, event in enumerate(events): + is_scalar = event[0] == 'scalar' + if start is not None and (not is_scalar or frame != event[2]): + runs.append((start, index, frame, current)) + current, frame, start = [], None, None + if is_scalar: + if start is None: + start, frame = index, event[2] + current.extend(lower(event[1])) + if start is not None: + runs.append((start, len(events), frame, current)) + return runs + + +def controls(optimize): + t, s = ('T', 0), ('S', 0) + cases = { + 'omitted_boundary_flush': ([('negate', t)], [], None), + 'missed_source_sign_flip': + ([('negate', s), ('add', t, s), ('negate', s)], [('add', t, s)], None), + 'lost_copy_sign': + ([('negate', s), ('copy', t, s), ('negate', s)], [('copy', t, s)], None), + # Keeping a negative sign through clear can be algebraically valid but + # needlessly pays a subtraction and final negate instead of one add. + 'clear_reset_cost': + ([('negate', t), ('clear', t), ('add', t, s)], + [('clear', t), ('subtract', t, s), ('negate', t)], 2), + 'endpoint_neutral_prefix_growth': + ([('add', t, s)], [('double', s), ('halve', s), ('add', t, s)], None), + } + rejected = {} + for name, (reference, mutant, count) in cases.items(): + compare(reference, optimize(reference), count) + try: + compare(reference, mutant, count) + except ValueError as error: + rejected[name] = str(error) + else: + raise ValueError('accepted negative control: ' + name) + require(rejected['clear_reset_cost'] == 'primitive count differs', 'clear control was not count-sensitive') + require(rejected['endpoint_neutral_prefix_growth'] == 'prefix row outside signed baseline', + 'prefix control was not prefix-sensitive') + # An ordinary frame change, a nonscalar boundary, and the end of the word + # each independently require a flush. No production splitter is consulted. + events = [['scalar', ['negate', t], 0], ['scalar', ['negate', t], 1], + ['phase', 'barrier'], ['scalar', ['negate', t], 1]] + runs = split_events(events, lambda op: [tuple(op)]) + require([(a, b, f) for a, b, f, _ in runs] == [(0, 1, 0), (1, 2, 1), (3, 4, 1)], + 'boundary splitter control') + for _, _, _, word in runs: + compare(word, optimize(word)) + rejected['boundary_segmentation'] = 'frame, nonscalar, and end boundaries retained' + return rejected + + +def verify(): + payload = gzip.decompress(PROGRAM.read_bytes()) + require(hashlib.sha256(payload).hexdigest() == PROGRAM_SHA256, 'pinned program payload differs') + programs = json.loads(payload) + require(hashlib.sha256(LOWERING.read_bytes()).hexdigest() == LOWERING_SHA256, 'pinned lowering differs') + lower = load(LOWERING, 'ck_independent_baseline_lowering').lower + optimize = load(HERE / 'compile.py', 'ck_candidate_compiler').optimize_run + require(set(programs) == {'forward', 'backward'}, 'program orientation set') + results = {} + for orientation in ('forward', 'backward'): + runs = split_events(programs[orientation], lower) + scalar_macros = sum(event[0] == 'scalar' for event in programs[orientation]) + require(sum(end - start for start, end, _, _ in runs) == scalar_macros, 'scalar event coverage') + before = after = largest_columns = 0 + max_reference_norm = max_candidate_norm = (0, 0) + max_reference_denominator = max_candidate_denominator = 0 + digest = hashlib.sha256() + boundaries = hashlib.sha256() + for start, end, frame, reference in runs: + candidate = optimize(reference) + checked = compare(reference, candidate) + largest_columns = max(largest_columns, checked['basis']) + max_reference_norm = larger_norm(max_reference_norm, checked['reference_norm']) + max_candidate_norm = larger_norm(max_candidate_norm, checked['candidate_norm']) + max_reference_denominator = max(max_reference_denominator, checked['reference_denominator']) + max_candidate_denominator = max(max_candidate_denominator, checked['candidate_denominator']) + before += len(reference) + after += len(candidate) + boundaries.update(json.dumps([start, end, frame], separators=(',', ':')).encode() + b'\n') + for op in candidate: + digest.update(json.dumps([frame, op], separators=(',', ':')).encode() + b'\n') + results[orientation] = { + 'scalar_runs': len(runs), + 'scalar_macros': scalar_macros, + 'baseline_real_primitives': 2 * before, + 'candidate_real_primitives': 2 * after, + 'saved_real_primitives': 2 * (before - after), + 'largest_independent_input_basis': largest_columns, + 'max_run_basis_prefix_l1_reference': norm_receipt(max_reference_norm), + 'max_run_basis_prefix_l1_candidate': norm_receipt(max_candidate_norm), + 'max_run_basis_denominator_exponent_reference': max_reference_denominator, + 'max_run_basis_denominator_exponent_candidate': max_candidate_denominator, + 'primitive_word_sha256': digest.hexdigest(), + 'run_boundaries_sha256': boundaries.hexdigest(), + 'all_run_endpoint_operators_equal': True, + 'all_prefix_rows_contained_modulo_sign': True, + } + return {'status': 'PASS_CK_SIGN_INDEPENDENT', 'programs': results, + 'controls': controls(optimize)} + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--json', action='store_true') + args = parser.parse_args() + result = verify() + if args.json: + print(json.dumps(result, sort_keys=True, indent=2)) + else: + print('PASS_CK_SIGN_INDEPENDENT programs=2 controls=' + str(len(result['controls']))) diff --git a/research/ck-sign-normalization-seed22/compile.py b/research/ck-sign-normalization-seed22/compile.py new file mode 100644 index 0000000000..08709f4d60 --- /dev/null +++ b/research/ck-sign-normalization-seed22/compile.py @@ -0,0 +1,41 @@ +"""Exact lazy-sign compilation within a single scalar frame. + +Ross Richardson, with substantial OpenAI Codex assistance. Apache-2.0. +This compiler is new; the consumed primitive lowering is Sagar Thakrar's PR696. +""" + + +def optimize_run(primitives): + """Return an explicit primitive word with identical boundary register values. + + Logical value = (-1 if register in negative else 1) * physical value. + All pending signs are materialized before returning. No state crosses runs. + Copy fanout can increase cost in general; no universal saving is asserted. + """ + negative, result = set(), [] + for instruction in primitives: + tag, target = instruction[:2] + if tag == "negate": + negative.symmetric_difference_update((target,)) + continue + if tag in ("add", "subtract"): + source = instruction[2] + if (target in negative) != (source in negative): + tag = "subtract" if tag == "add" else "add" + result.append((tag, target, source)) + elif tag == "copy": + source = instruction[2] + sign = source in negative + negative.discard(target) + if sign: + negative.add(target) + result.append(instruction) + elif tag == "clear": + negative.discard(target) + result.append(instruction) + elif tag in ("double", "halve"): + result.append(instruction) + else: + raise ValueError("unknown primitive: " + str(tag)) + result.extend(("negate", register) for register in sorted(negative)) + return result diff --git a/research/ck-sign-normalization-seed22/test_package.py b/research/ck-sign-normalization-seed22/test_package.py new file mode 100644 index 0000000000..77abb18694 --- /dev/null +++ b/research/ck-sign-normalization-seed22/test_package.py @@ -0,0 +1,99 @@ +"""Package portability and concrete circuit/source/receipt corruption controls. + +Ross Richardson with substantial OpenAI Codex assistance. Apache-2.0. +""" +import gzip +import importlib.util +import json +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +REL = HERE.relative_to(ROOT) + + +def load(name): + spec = importlib.util.spec_from_file_location("ck_test_" + name, HERE / (name + ".py")) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +class PackageTests(unittest.TestCase): + def test_actual_gain_run_mutants(self): + primary, independent, compiler = load("verify"), load("check_independent"), load("compile") + primary.source_check() + lower = primary.module("ck_test_baseline", ROOT / primary.INPUTS[0]).lower + programs = primary.read(ROOT / primary.INPUTS[1]) + rejected = 0 + for events in programs.values(): + for _, _, _, word in independent.split_events(events, lower): + candidate = compiler.optimize_run(word) + if len(candidate) >= len(word): + continue + independent.compare(word, candidate) + self.assertEqual(candidate[-1][0], "negate") + with self.assertRaises(ValueError): + independent.compare(word, candidate[:-1]) + rejected += 1 + changed = list(candidate) + index = next(i for i, p in enumerate(changed) if p[0] in ("add", "subtract")) + old = changed[index] + changed[index] = ("add" if old[0] == "subtract" else "subtract", *old[1:]) + with self.assertRaises(ValueError): + independent.compare(word, changed) + rejected += 1 + self.assertEqual(rejected, 56) + + def test_copy_fanout_is_not_claimed_free(self): + checker, compiler = load("check_independent"), load("compile") + a, b, c = ("A", 0), ("B", 0), ("C", 0) + word = [("negate", a), ("copy", b, a), ("copy", c, a)] + candidate = compiler.optimize_run(word) + checker.compare(word, candidate, 5) + self.assertEqual(len(candidate) - len(word), 2) + + def test_minimal_relocation_recompression_and_corruption(self): + primary = load("verify") + with tempfile.TemporaryDirectory(prefix="ck sign minimal ") as tmp: + target = Path(tmp) + for item in HERE.iterdir(): + if item.is_file(): + destination = target / REL / item.name + destination.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(item, destination) + for name in primary.INPUTS: + destination = target / name + destination.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(ROOT / name, destination) + program = target / primary.INPUTS[1] + program.write_bytes(gzip.compress(gzip.decompress(program.read_bytes()), compresslevel=1, mtime=1234)) + def run(): + return subprocess.run([sys.executable, "-I", "-O", "-B", str(target / REL / "check.py")], + cwd=target, text=True, capture_output=True, timeout=120) + result = run() + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn("PASS_CK_SIGN_PACKAGE", result.stdout) + source = target / primary.INPUTS[0] + original = source.read_bytes() + source.write_bytes(original + b"\n# deliberate source corruption\n") + result = run() + self.assertNotEqual(result.returncode, 0) + self.assertIn("source pin:", result.stderr) + source.write_bytes(original) + receipt = target / REL / "EXPECTED.json" + data = json.loads(receipt.read_text()) + data["programs"]["forward"]["real_saved"] += 2 + receipt.write_text(json.dumps(data)) + result = run() + self.assertNotEqual(result.returncode, 0) + self.assertIn("primary receipt differs", result.stderr) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/research/ck-sign-normalization-seed22/verify.py b/research/ck-sign-normalization-seed22/verify.py new file mode 100644 index 0000000000..21fd83a97a --- /dev/null +++ b/research/ck-sign-normalization-seed22/verify.py @@ -0,0 +1,204 @@ +"""Reproduce the complete historical CK sign-normalization census, offline. + +Ross Richardson with substantial OpenAI Codex assistance. Apache-2.0. +""" +import argparse +from collections import Counter +from fractions import Fraction as Q +import gzip +import hashlib +import importlib.util +import json +from pathlib import Path + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +PROVIDER = "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/" +INPUTS = ( + "research/complex-dyadic-lowering/lower.py", + PROVIDER + "LOCAL-PROGRAMS.json.gz", + PROVIDER + "LOCAL-CHECKS.json", + PROVIDER + "INDEPENDENT-LOCAL-REPLAY.json", +) + + +def require(ok, message): + if not ok: + raise ValueError(message) + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(",", ":")).encode() + + +def digest(value): + return hashlib.sha256(value).hexdigest() + + +def read(path): + data = path.read_bytes() + return json.loads(gzip.decompress(data) if path.suffix == ".gz" else data) + + +def module(name, path): + spec = importlib.util.spec_from_file_location(name, path) + result = importlib.util.module_from_spec(spec) + spec.loader.exec_module(result) + return result + + +def source_check(): + pins = read(HERE / "SOURCE-PINS.json") + require(set(pins["files"]) == set(INPUTS), "source inventory differs") + for name in INPUTS: + data = (ROOT / name).read_bytes() + if name.endswith(".gz"): + data = gzip.decompress(data) + require(digest(data) == pins["files"][name], "source pin: " + name) + return pins + + +def segments(events): + """Every scalar run is bounded by any event or any literal frame change.""" + run, start, frame = [], 0, None + for index, event in enumerate(events): + if event[0] != "scalar" or event[2] != frame: + if run: + yield start, frame, run + run = [] + frame = None + if event[0] == "scalar": + if not run: + start, frame = index, event[2] + run.append(event) + if run: + yield start, frame, run + + +def step(rows, op): + tag, target = op[:2] + if tag == "clear": + rows[target] = {} + elif tag == "copy": + rows[target] = dict(rows[op[2]]) + elif tag in ("double", "halve", "negate"): + factor = {"double": Q(2), "halve": Q(1, 2), "negate": Q(-1)}[tag] + rows[target] = {key: factor * value for key, value in rows[target].items()} + elif tag in ("add", "subtract"): + factor = 1 if tag == "add" else -1 + for key, value in list(rows[op[2]].items()): + new = rows[target].get(key, Q(0)) + factor * value + if new: + rows[target][key] = new + else: + rows[target].pop(key, None) + else: + raise ValueError("unknown primitive: " + tag) + + +def replay(events, checks, lower, optimize, orientation): + require(digest(canonical(events)) == checks["sha256"], "event semantic digest") + runs = list(segments(events)) + registers = {("L", i) for i in range(716)} | {("W", 0)} + for _, _, run in runs: + for event in run: + for primitive in lower(event[1]): + registers.update(primitive[1:]) + rows = [{register: {register: Q(1)} for register in registers} for _ in range(2)] + peaks, depths, counts = [Q(1), Q(1)], [0, 0], [Counter(), Counter()] + streams = [hashlib.sha256(), hashlib.sha256()] + changed, gains = [], Counter() + macro_count = 0 + for start, frame, run in runs: + original = [p for event in run for p in lower(event[1])] + candidate = optimize(original) + macro_count += len(run) + touched = {reg for p in original for reg in p[1:]} + for version, word in enumerate((original, candidate)): + for primitive in word: + step(rows[version], primitive) + counts[version][primitive[0]] += 1 + streams[version].update(canonical([frame, primitive]) + b"\n") + row = rows[version][primitive[1]] + peaks[version] = max(peaks[version], sum(map(abs, row.values()), Q(0))) + depths[version] = max(depths[version], max( + (x.denominator.bit_length() - 1 for x in row.values()), default=0)) + require(all(rows[0][reg] == rows[1][reg] for reg in touched), + "boundary mismatch at event " + str(start)) + saving = 2 * (len(original) - len(candidate)) + gains[saving] += 1 + if saving: + changed.append({"start_event": start, "scalar_macros": len(run), "frame": frame, + "baseline_real_primitives": 2 * len(original), + "candidate_real_primitives": 2 * len(candidate), + "real_saved": saving, + "baseline_negations_per_component": sum(p[0] == "negate" for p in original), + "boundary_negations_per_component": sum(p[0] == "negate" for p in candidate)}) + require(macro_count == checks["scalar_macros"], "incomplete scalar coverage") + require(peaks[0] == peaks[1] and depths[0] == depths[1], "prefix envelope increased") + require(rows[0] == rows[1], "whole scalar map differs") + for r in range(716): + expected = {("L", r): Q(1)} + if orientation == "forward" and 112 <= r < 224: + expected[("L", r - 112)] = Q(1) + if orientation == "backward" and r < 112: + expected[("L", r + 112)] = Q(-1) + require(rows[1][("L", r)] == expected, "whole scalar shear or restoration differs") + require(all(not row for reg, row in rows[1].items() if reg[0] != "L"), "private work not cleared") + non_scalar = [e for e in events if e[0] != "scalar"] + paid = Counter() + for event in non_scalar: + if event[0] == "climb": + paid[event[5]] += 1 + elif event[0] == "center": + paid[event[4]] += 1 + require({str(k): v for k, v in paid.items()} == checks["paid_profile"], "paid profile differs") + return { + "formal_input_columns": len(registers), "logical_columns": 716, + "private_input_columns": len(registers) - 716, + "events": len(events), "scalar_macros": macro_count, "runs": len(runs), + "non_scalar_events": len(non_scalar), "non_scalar_sha256": digest(canonical(non_scalar)), + "baseline_real_primitives": 2 * sum(counts[0].values()), + "candidate_real_primitives": 2 * sum(counts[1].values()), + "real_saved": 2 * (sum(counts[0].values()) - sum(counts[1].values())), + "baseline_tags_per_component": dict(sorted(counts[0].items())), + "candidate_tags_per_component": dict(sorted(counts[1].items())), + "baseline_primitive_sha256": streams[0].hexdigest(), + "candidate_primitive_sha256": streams[1].hexdigest(), + "prefix_row_l1_max": [str(x) for x in peaks], "fractional_bits_max": depths, + "paid_profile": checks["paid_profile"], + "run_savings_census": {str(k): v for k, v in sorted(gains.items())}, + "changed_runs": changed, + } + + +def verify(): + pins = source_check() + lower = module("ck_sign_baseline", ROOT / INPUTS[0]).lower + optimize = module("ck_sign_compiler", HERE / "compile.py").optimize_run + programs = read(ROOT / INPUTS[1]) + checks = read(ROOT / INPUTS[2]) + require(set(programs) == {"forward", "backward"}, "orientation coverage") + results = {direction: replay(programs[direction], checks[direction], lower, optimize, direction) + for direction in ("forward", "backward")} + return {"status": "PASS_CK_SIGN_NORMALIZATION", "base_commit": pins["base_commit"], + "assignment_seed": 22, "kappa": "unchanged", "programs": results} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--write", type=Path, help="write a new receipt during development") + parser.add_argument("--json", action="store_true") + args = parser.parse_args() + result = verify() + if args.write: + with args.write.open("x") as file: + file.write(json.dumps(result, indent=2, sort_keys=True) + "\n") + else: + require(canonical(result) == canonical(read(HERE / "EXPECTED.json")), "expected receipt mismatch") + if args.json: + print(json.dumps(result, indent=2, sort_keys=True)) + else: + rows = [result["programs"][d] for d in ("forward", "backward")] + print("PASS_CK_SIGN_NORMALIZATION runs=" + "+".join(str(r["runs"]) for r in rows) + + " saved=" + "/".join(str(r["real_saved"]) for r in rows) + " kappa=unchanged")