From 99b901c9b5ac70cf441b3d7e585cc7b8744b5359 Mon Sep 17 00:00:00 2001 From: ross Date: Sun, 18 Oct 2026 23:41:14 +1100 Subject: [PATCH] Add R438 source coding with three copies and 429 helpers --- .../bit-r438-source-code/ADAPTATIONS.json | 56 +++ research/bit-r438-source-code/ARTIFACTS.json | 24 ++ research/bit-r438-source-code/EXPECTED.json | 54 +++ research/bit-r438-source-code/PROOF.md | 202 ++++++++++ research/bit-r438-source-code/README.md | 88 +++++ research/bit-r438-source-code/SOURCES.json | 30 ++ research/bit-r438-source-code/TASK.json | 71 ++++ research/bit-r438-source-code/VALIDATION.json | 83 +++++ research/bit-r438-source-code/VERIFY.json | 24 ++ research/bit-r438-source-code/WORD.json.gz | Bin 0 -> 59514 bytes research/bit-r438-source-code/check.py | 232 ++++++++++++ research/bit-r438-source-code/native_caps.py | 56 +++ .../producer/bit_scalar_invoice.py | 147 ++++++++ .../producer/bit_section_code.py | 246 ++++++++++++ .../producer/bit_signed_lift.py | 151 ++++++++ .../producer/bit_transvection.py | 350 ++++++++++++++++++ .../producer/build_support_code.py | 131 +++++++ .../bit-r438-source-code/producer/prune.py | 121 ++++++ research/bit-r438-source-code/reconstruct.py | 91 +++++ research/bit-r438-source-code/signed_rows.py | 15 + research/bit-r438-source-code/verify.py | 97 +++++ 21 files changed, 2269 insertions(+) create mode 100644 research/bit-r438-source-code/ADAPTATIONS.json create mode 100644 research/bit-r438-source-code/ARTIFACTS.json create mode 100644 research/bit-r438-source-code/EXPECTED.json create mode 100644 research/bit-r438-source-code/PROOF.md create mode 100644 research/bit-r438-source-code/README.md create mode 100644 research/bit-r438-source-code/SOURCES.json create mode 100644 research/bit-r438-source-code/TASK.json create mode 100644 research/bit-r438-source-code/VALIDATION.json create mode 100644 research/bit-r438-source-code/VERIFY.json create mode 100644 research/bit-r438-source-code/WORD.json.gz create mode 100644 research/bit-r438-source-code/check.py create mode 100644 research/bit-r438-source-code/native_caps.py create mode 100644 research/bit-r438-source-code/producer/bit_scalar_invoice.py create mode 100644 research/bit-r438-source-code/producer/bit_section_code.py create mode 100644 research/bit-r438-source-code/producer/bit_signed_lift.py create mode 100644 research/bit-r438-source-code/producer/bit_transvection.py create mode 100644 research/bit-r438-source-code/producer/build_support_code.py create mode 100644 research/bit-r438-source-code/producer/prune.py create mode 100644 research/bit-r438-source-code/reconstruct.py create mode 100644 research/bit-r438-source-code/signed_rows.py create mode 100644 research/bit-r438-source-code/verify.py diff --git a/research/bit-r438-source-code/ADAPTATIONS.json b/research/bit-r438-source-code/ADAPTATIONS.json new file mode 100644 index 0000000000..510eb2b34d --- /dev/null +++ b/research/bit-r438-source-code/ADAPTATIONS.json @@ -0,0 +1,56 @@ +[ + { + "path": "producer/bit_transvection.py", + "original_sha256": "97cb9f6bd3c29fc509e929fbeaec503defe3584da5736786719b2641e096f2fd", + "adapted_sha256": "4706d7e03fd9194e89914e0ee92b1d009ef25a2c14e45ddc6226ef181e68a52b", + "changes": "Repo default made relative; registered driver explicitly binds actual repo and fresh output." + }, + { + "path": "producer/bit_section_code.py", + "original_sha256": "4b35d963e07e062eddd093854d34c449d720d5140480f0c1ddd6fefef8c3472c", + "adapted_sha256": "4b35d963e07e062eddd093854d34c449d720d5140480f0c1ddd6fefef8c3472c", + "changes": "Exact original research source; module output binding supplied by registered driver." + }, + { + "path": "producer/bit_scalar_invoice.py", + "original_sha256": "8ed16fd022ba8f57cac1d1962fa845794181c308ffd9ed5bedb1b91fa3cb7c24", + "adapted_sha256": "8ed16fd022ba8f57cac1d1962fa845794181c308ffd9ed5bedb1b91fa3cb7c24", + "changes": "Exact original research source; module output binding supplied by registered driver." + }, + { + "path": "producer/bit_signed_lift.py", + "original_sha256": "e5e7bc86255c3a6c8f6eef7bc4bb759b9ac66a394fe87894ab43eb14b7853e36", + "adapted_sha256": "e5e7bc86255c3a6c8f6eef7bc4bb759b9ac66a394fe87894ab43eb14b7853e36", + "changes": "Exact original research source; module output binding supplied by registered driver." + }, + { + "path": "native_caps.py", + "original_sha256": "6e9ca1eb905d769716c009904f45d6849b225e48cd119f18b50c0379f35313cb", + "adapted_sha256": "cd1772b0780d5882b5ae50c268732848f102108b9f02a564c86773eba7916e72", + "changes": "Exact AST-selected local function bodies: need, canonical, rank, identity, multiply, exchange, address_identities. Global controller and unused main removed." + }, + { + "path": "signed_rows.py", + "original_sha256": "376356696663021693c0e2c9adf37f371675fe8837fb88232b8767a8b90793e8", + "adapted_sha256": "16dff88980ab3043ae9d51c3109e8e284e031da5332af2cd9b2e8244afdc8292", + "changes": "Exact AST-selected local function bodies: identity, add, parity. Global controller and unused main removed." + }, + { + "path": "check.py", + "original_sha256": "d284714fd65054279c180454b73eb717382e402669d5a04e3f373d0d7f54bc06", + "changes": "Exact independent projected and execute function bodies retained. Portable main derives actual raw R/K/J and final A, compares the complete projected word/boundaries, verifies all651 integer/F2 columns, native caps and seven defect controls. No producer imports.", + "adapted_sha256": "110f0eaa897b83daa223aec038f7ef40ff785e9fb730eeb8d670b5b95132ea5e" + }, + { + "path": "producer/build_support_code.py", + "original_sha256": "4b3e1ae12194f3f1a2294ffa8f92b0cf02c8c3163bf530987081a08406f9475e", + "adapted_sha256": "dd24cd8cbce7aa8cf4c13e51afe202a460f827b2b7b97f63d609d4f8dc7e8415", + "changes": "Fresh output binding; remove sys.path insertion; replace fixed regenerated gzip pin with caller-supplied complete semantic ancestry authentication. Construction, support checks and defect controls unchanged." + }, + { + "path": "producer/prune.py", + "original_sha256": "3532caa0c7ed88401234f86a8aa3e5bab7e5640a737b2ec08a19635444832cdf", + "adapted_sha256": "4a555dbd3154caa853a9b327fff4aa8ddcc938c2af4dfb1f540c1c35ad359c1f", + "changes": "Fresh-output binding; remove sys.path insertion; replace regenerated fixed-gzip guard by complete semantic predecessor authentication. Projection, original integer endpoint equality and negative control unchanged." + } +] diff --git a/research/bit-r438-source-code/ARTIFACTS.json b/research/bit-r438-source-code/ARTIFACTS.json new file mode 100644 index 0000000000..ba048927b8 --- /dev/null +++ b/research/bit-r438-source-code/ARTIFACTS.json @@ -0,0 +1,24 @@ +{ + "format": "complete-package-sha256-v1", + "files": { + "ADAPTATIONS.json": "a4325f122f4da020bf54060b5d33fb048df6f31fc3be232930ae78e904eab43c", + "EXPECTED.json": "f078222ab4e99aff085262c00ba77520cc62eb02003d8e0582ab6ad7dab7f402", + "PROOF.md": "ebcc91e74938b525b28e46bf03ec09d42d24ab02070dc96f4f0a51cee2cfb83d", + "README.md": "f1033297e1156f9fb154a4319bee394a82476195cd2a53d01d93ef7332536d27", + "SOURCES.json": "adaa3aa444f224590ba152fe16dd76ccd8ff8bd8a0b19477076c4d79ce4b94cb", + "TASK.json": "fa2dd91db03f05e78d909ddf9c96e5cc000fbecfb80a6c074521215c8b9c8553", + "VERIFY.json": "3a8b8559683d5f8a61f8a34cf0cd54513892f2543345d7ba478470d02a1377b7", + "WORD.json.gz": "1a6841fccba51fa922993c77b4b296e659c2c538252e5e06113d0438c5edb870", + "check.py": "110f0eaa897b83daa223aec038f7ef40ff785e9fb730eeb8d670b5b95132ea5e", + "native_caps.py": "cd1772b0780d5882b5ae50c268732848f102108b9f02a564c86773eba7916e72", + "producer/bit_scalar_invoice.py": "8ed16fd022ba8f57cac1d1962fa845794181c308ffd9ed5bedb1b91fa3cb7c24", + "producer/bit_section_code.py": "4b35d963e07e062eddd093854d34c449d720d5140480f0c1ddd6fefef8c3472c", + "producer/bit_signed_lift.py": "e5e7bc86255c3a6c8f6eef7bc4bb759b9ac66a394fe87894ab43eb14b7853e36", + "producer/bit_transvection.py": "4706d7e03fd9194e89914e0ee92b1d009ef25a2c14e45ddc6226ef181e68a52b", + "producer/build_support_code.py": "dd24cd8cbce7aa8cf4c13e51afe202a460f827b2b7b97f63d609d4f8dc7e8415", + "producer/prune.py": "4a555dbd3154caa853a9b327fff4aa8ddcc938c2af4dfb1f540c1c35ad359c1f", + "reconstruct.py": "12ea8141d609bfc49166bff2bb3f24f477d69fca4260d3523491c8b614cd4929", + "signed_rows.py": "16dff88980ab3043ae9d51c3109e8e284e031da5332af2cd9b2e8244afdc8292", + "verify.py": "3bcec1c1c29eb0348960679b70706f77c70a4faa2a6e58533c9d2059ea27ab1f" + } +} diff --git a/research/bit-r438-source-code/EXPECTED.json b/research/bit-r438-source-code/EXPECTED.json new file mode 100644 index 0000000000..1ad8df8143 --- /dev/null +++ b/research/bit-r438-source-code/EXPECTED.json @@ -0,0 +1,54 @@ +{ + "source_word": "research/bit-r438-transport-rehost/words/r438-t154.json.gz", + "source_sha256": "a353999bceac4ac957f540adfd3e5f8768297138b27132eeb83332e2ea4b1022", + "canonical_word_sha256": "ebc33ee086f610c1fd540fa56bb99b2b96a768e4aed4a18defcb0e1f507fca89", + "frozen_gzip_sha256": "1a6841fccba51fa922993c77b4b296e659c2c538252e5e06113d0438c5edb870", + "semantic_word_sha256": "e5fa1dbcb80f61c7c728bad7cc166f368ec73c673828273bea091caba8708892", + "six_copy_semantic_sha256": "f44b26376769580295293b1e782568d81ed297647106450a13bd82ecf086dd1b", + "unsigned_section_semantic_sha256": "a50fcbbec51830f84f7368bc6153fe3340ef345849a6cf9ea287d624a753cea4", + "original_six_copy_canonical_sha256": "6448fb2b201c6be722087fc547064ec7c3135af5a72ed363434822212a9b2afc", + "normalized_fields": [ + "source_word", + "signed_from", + "parent_word_gzip_sha256" + ], + "normalization_contract": "The final word omits only checked source location and validated same-run parent compressed identity in semantic comparison. Signed ancestry also normalizes its validated same-run parent hash. All schemas, frames, signed records, deleted physical indices, register counts and original source hashes are compared completely. Immutable frozen inputs retain exact byte hashes.", + "profile": { + "1": 1298, + "2": 1342, + "3": 79, + "4": 44, + "5": 93, + "6": 11, + "7": 9 + }, + "counts": { + "0": 2873, + "1": 13223, + "2": 3, + "3": 3 + }, + "rank_mass": 4989, + "rank_saving": 132, + "source_matrix_sha256": "0ab35dade762a3050b6fc15f653041134f8d5a8015cbdbdc049be0528659240b", + "source_code_ADDs": 1499, + "prefix_row_l1": { + "forward": 34285, + "inverse": 5839860 + }, + "support_semantic_sha256": "c281439e7e78c74c8223e5adfebf34c2be945f308b0f7e53b928c700151cbd74", + "support_canonical_sha256": "3541eab8057c8cebadbd46775ff2d8e759fd592d8a1b9aebde834821d96c051b", + "public_registers": 651, + "dirty_helpers": 429, + "deleted_original_families": [ + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479 + ] +} diff --git a/research/bit-r438-source-code/PROOF.md b/research/bit-r438-source-code/PROOF.md new file mode 100644 index 0000000000..1fbd2cad0e --- /dev/null +++ b/research/bit-r438-source-code/PROOF.md @@ -0,0 +1,202 @@ +# Three copied source pivots for the actual R438 local word + +This is a finite, source-pinned local construction over F2, an exact signed +integer lift, and a conditional native cap calculation. It is neither a formal +kernel proof nor a complete recursive supplier or multiplication theorem. + +## Registers, frames and endpoint + +The final word has 111 sources x, 111 arbitrary targets y, 429 arbitrary dirty +helpers h and one owned private copied field. All 651 public input columns are +independent. Its construction first uses the 438-helper, 660-column source +word and then deletes nine literally unread physical families as proved below. The private field is zero outside its immutable snapshot +lifetimes. Sources enter at their actual port lines P_p, targets and helpers at +frame zero. Sources and helpers finish at FULL; target p finishes at its actual +cap K_p=P_p-perp. These are the original R438 boundary frames. + +For the explicit invertible binary matrix A constructed below, the new forward +endpoint is `(x,y,h) -> (Ax,y+Ax,h)`. Its literal inverse is +`(x,y,h) -> (A^-1 x,y+x,h)`. The source endpoint is changed. Original theorems +requiring an unchanged source cannot be applied without proving the new caller +contract. Complemented physical backward-call interpretation and the complete +compiler remain separate obligations. + +## Delete centres and rebuild the zero-frame compensation + +Replay D then A of the actual pinned word. The nine retained helper totals are +`R x+T h`, with R of shape 9-by-111. Let K be the actual 111-by-9 scatter matrix. +No original gate reads a target. The complete row masks of M=RK are +`507,135,238,349,185,437,205,503,425`. Both M and R have rank 9, while +N=I+M has rank 6. + +Delete the nine centre COPY/ERASE episodes and their target scatters. Over F2, +this changes the original target `y+x` by `KR x+KT h`. Replace its original +zero-frame compensation by `D_new=D_old+KT`. Duplicate helper-to-target gates +cancel at frame zero: 5,758 ADDs replace 18,030. Every original public frame +visit is retained, including empty-source visits. The resulting clean-centre +word has endpoint `(x,y,h) -> (x,y+Jx,h)`, where J=I+KR and rank(J)=108. +The verifier derives R,K,J from the literal original word and checks every +public input column; it does not assume a model scatter matrix. + +## An invertible source code with three actual repaired target rows + +Let C0 be a basis of the left nullspace of N, with emitted row masks +`39,193,272`. Let P select physical target coordinates 0,1,2 and S=RP. +The 3-by-3 matrix C0 S is invertible. Define + +``` +B0 = (C0 S)^-1 C0. +``` + +Thus B0 S=I and B0 N=0. Let D be rows 0,1,2 of K. Delete these rows +from K to form W=K+PD, and define + +``` +Y = N + S D, A = I + W R, Q = P B0 R. +``` + +The actual row masks of Y are `10,373,282,165,176,405,356,145,166`, of rank 9. +A fixes kernel(R) and induces the invertible map Y on the quotient identified +by R: RA=YR. Thus A is invertible. Equivalently, if Ax=0 then YRx=0, so +Rx=0 and Ax=x=0. Both matrix inverse identities are also checked finitely. +Rows 0,1,2 of A are exactly their identity rows. Since B0Y=D, + +``` +QA = P B0 R A = P B0 Y R = P D R, +(I+Q)A = I + (K+PD)R + PDR = I+KR = J. +``` + +After the full-frame source code, z=Ax and the target is y+Jx. Adding Qz +therefore gives y+Ax over F2. Q has exactly three nonzero physical rows, +0,1,2. The actual source-code rank is rank(A-I)=9; small target support does +not imply small source-code rank. + +Three repaired target rows are minimal in this declared class. For any +invertible A, rank(A+J) >= rank(A)-rank(J)=3. A correction supported on r +physical target rows has rank at most r. This excludes r<3 for this fixed +clean-centre J and invertible source recoding, not arbitrary suppliers. + +## Literal source code and one snapshot per repaired row + +Normalize R on actual source coordinates `0,1,2,4,8,9,14,30,59`. Commuting +CNOTs replace those coordinates by a query basis. In this basis A has an +invertible 9-by-9 query block and fanout to the other source coordinates. +Gaussian elimination synthesizes the small block with 47 CNOTs. The ordered +code uses `474 prepare + 504 fanout + 47 quotient + 474 inverse prepare`, +or 1,499 ADDs, all at FULL. It uses no extra helper or private field. + +For each nonzero row q=Q[p], choose a source index t with q[t]=1. All source +fields are at FULL. Add each z_i with i!=t and q[i]=1 to z_t. The prepared +field is exactly `sum_i q[i] z_i` over the integers: its original z_t is one +of the required terms, not an unknown extra offset. Copy this actual source +into the cleared private field at target p's cap, add it to target p, and +ERASE the copy while the physical source is unchanged. Undo the preparation +in reverse order with negated ADD coefficients. Every source is restored +exactly to its value before this episode. + +The chosen pivots are 0,1,2. Their preparations use 59,53,60 ADDs; their inverse +preparations use the same counts. Including three scatters gives 347 repair +ADDs. Only one private snapshot is live at a time. No dirty helper is touched +by these three repair episodes. The six-copy dirty-helper variant is retained +only as explicit reconstruction ancestry; it is not the final construction. + +## Integer and native boundaries + +The signed word negates the actual factory cleanup, source unpreparation and +repair unpreparation ADDs. Literal reversal negates every ADD coefficient. +The complete 651-column integer replay establishes source `A_Z x`, every +helper exactly h and the private field zero. The target is +`y+T_Z x+E_Z h`, where `T_Z mod2=A` and E_Z is even. Target correctness is +asserted modulo 2, not as integer equality to y+A_Z x. The reverse source is +`A_Z^-1 x`. Full integer roundtrip is checked separately; A is not assumed +involutive. Wrong unpreparation signs preserve parity but change the integer +source, and are rejected independently. + +For each actual rational E8 line vector u with squared norm 4, the checker +constructs P=uu^t/4 and K=I-P. It binds the actual entrance frame to P and +target frame to K, including all 222 bindings. For +`D_U=[[I-U,U],[U,I-U]]`, exact rational multiplication proves +`D_I D_P=D_K` and `D_P^2=I` on all 16 columns, for all 111 ports (3,552 checked +columns). Hence the FULL-to-cap copied-total residual is D_P of rank one, +under the inherited native ADDRESS/copied-total interface. Source and target +port labels need not agree: the physical source is FULL at the cut. + +The independent ordered-word audit checks common frames for every ADD, +monotone containment and rank for every MOVE, actual source COPY, immutable +source throughout each snapshot, exact ERASE and endpoint frames, in both +directions. These local identities do not establish a full physical native +compiler, rounded implementation or recursive hosting theorem. + +## Delete nine literally unread physical families + +In the signed three-copy word, precisely the old helper indices 471 through +479 are never read as ADD sources or COPY/ERASE sources. The independent +checker discovers this set by scanning every record. The only operations on +these fields are 72 ADD destinations and 36 MOVEs, with paid profile +`27 e1+9 e5`. The same no-read property holds in the literal inverse. + +Delete these nine physical input/output families, discard their destination +operations, and renumber every remaining operand in order, including the +private field from 660 to 651. No remaining value or frame depends on a +removed family. Induction through the literal word therefore identifies the +new execution with projection of the original execution, forward and inverse. +The constructor also checks exact integer endpoint projection, and the +independent checker compares the entire projected record list and both +boundary arrays before replaying all 651 independent columns. Every one of +the remaining 429 arbitrary helpers is restored exactly. The deleted families +are absent from the contract; they are not retained with unpaid endpoints. +A mutant that reads a discarded field is rejected before projection. + +This removes another 72 local rank units and 72 ADDs. It does not establish a +72-unit hosted saving: under the incumbent width-8 whole-family accounting, +returning nine families to idle-owner children adds `9*8=72` rank units per +local call at beta=0 (648 across nine calls). Thus that returned idle obligation +cancels the pruning reduction at this mass level. Changed chronological owners, +stock and complete higher moments remain outside this package. The local +132-unit reduction below must not be read as a net global gain. + +## Complete local invoice + +| Item | Pinned R438 | This word | +|---|---:|---:| +| Sources / targets / dirty helpers | 111 / 111 / 438 | 111 / 111 / 429 | +| Owned private fields / maximum live copies | 1 / 1 | 1 / 1 | +| ADDs | 24,248 | 13,223 | +| MOVE children | 2,909 | 2,873 | +| COPY / ERASE pairs | 9 | 3 | +| COPY ranks | 9 times 7 | 3 times 1 | +| Paid children | 2,918 | 2,876 | +| Rank mass | 5,121 | 4,989 | + +The complete profile is `{1:1298,2:1342,3:79,4:44,5:93,6:11,7:9}`. +Its exact change is `-9 e7-24 e1-9 e5`, saving 132 rank units per local invocation. +The ADD invoice is `5758 compensation + 5619 clean factory/cleanup + 1499 +source code + 347 repair`. No chronological owners, native allocation, +private reservation, code restoration or final decoder cost is removed from +a global bill by this local calculation. + +The exact signed prefix row norms are 34,285 forward and 5,839,860 inverse. +They are checked local arithmetic facts only. A new global perturbation/rounding +proof and precision reserve are required before using them in a supplier. + +## Verification and remaining conditions + +`reconstruct.py` regenerates the complete ordered word from the two pinned live +sources through the declared section and signed ancestry. The registered +verifier compares the full decompressed payload with `WORD.json.gz`. Only +validated source-location metadata and validated same-run compressed-parent +identities in signed/pruned ancestry are normalized. Every record, sign, frame, schema and register count +is compared. Immutable source and frozen word files retain exact byte hashes. + +`check.py` imports no producer. Its separate sparse integer interpreter checks +all 651 columns in both directions and the roundtrip, actual R/K/J, source +inverse, all dirty restoration, all target parity, complete profile and exact +rational native caps. Eleven ancestry fault checks and seven independent controls +cover missing compensation/unpreparation, mutable snapshots, wrong inverse +code, wrong integer signs, FULL-copy rank, a corrupt section query and a read of a deleted family. + +Open global obligations include composition of the changed source interface, +terminal code removal at the actual caps, physical helper/owner/access and +storage schedules, rounded cleanup and precision, recursive caller contracts, +and a full joint complex/BIT outer transfer. This local result supplies none +of those admissions and claims no new kappa. diff --git a/research/bit-r438-source-code/README.md b/research/bit-r438-source-code/README.md new file mode 100644 index 0000000000..e501165027 --- /dev/null +++ b/research/bit-r438-source-code/README.md @@ -0,0 +1,88 @@ +# Three source snapshots replace nine R438 centres + +This source-pinned local BIT construction replaces nine rank-7 copied centres +with three rank-1 snapshots of prepared actual source fields. Deleting nine subsequently unread physical helper families gives a +complete +local rank mass of **4,989 instead of 5,121**, **13,223 instead of 24,248 ADDs**, +and **429 instead of 438 arbitrary dirty helpers**, with one owned private field. + +The changed F2 contract is `(x,y,h) -> (Ax,y+Ax,h)`, with an explicit invertible +111-by-111 source code A. Its literal inverse is `(A^-1 x,y+x,h)`. A has +rank(A-I)=9. Three actual repaired target rows are minimal for the fixed +clean-centre map J and invertible source recoding. This is a finite local +construction and written proof, **not a new kappa or global supplier claim**. + +The 132-unit reduction is local only. Under incumbent width-8 family +accounting, returned idle-owner children add 72 rank units per local call at +beta=0, cancelling the extra 72-unit pruning reduction. Full owner and moment +accounting remain open; this is not a net global 132-unit saving. + +The signed integer lift restores every dirty helper exactly and maps the +source to A_Z x. The target formula is only asserted modulo 2. The separate +native audit verifies exact rational cap ADDRESS identities under the +copied-total interface; it is not a new physical compiler theorem. +[PROOF.md](PROOF.md) gives the section derivation, source-pivot word, full bill, +integer distinction and remaining hypotheses. + +## Reproduce + +Use Python 3.12 and the two live source paths declared in [VERIFY.json](VERIFY.json): + +```sh +python3.12 scripts/research_package.py --package research/bit-r438-source-code +# Direct replay also works in the committed Git-free package export: +python3.12 -I -O -B -Werror research/bit-r438-source-code/verify.py --out /tmp/r438-fresh-result +``` + +The output path must be fresh and outside the package. The standard-library +replay regenerates the entire word, compares complete decompressed contents, +then independently checks all 651 integer/F2 columns forward and inverse, +all 429 dirty helpers, the roundtrip, all frame/rank events, 111 rational cap +projectors and 3,552 ADDRESS columns. Eleven construction-ancestry and seven +independent defect controls execute. Verification reads source files and writes +only external runtime output. The registered cap is 600 seconds. + +[WORD.json.gz](WORD.json.gz) has full canonical SHA256 +`ebc33ee086f610c1fd540fa56bb99b2b96a768e4aed4a18defcb0e1f507fca89`. +[EXPECTED.json](EXPECTED.json) specifies the complete semantic comparison. +Gzip container bytes produced by different zlib implementations are not a +regenerated-word acceptance criterion. Only checked source-location and +same-run compressed-parent provenance fields are normalized; scientific +contents are compared in full. The frozen input itself has an exact byte pin. + +[SOURCES.json](SOURCES.json) binds both live main inputs and historical task +provenance at `20ecf2891d80b5acf18d980b2164fb44ea7faa90`. +[ADAPTATIONS.json](ADAPTATIONS.json) identifies the new research producer and +independent audit source hashes and the precise portability/extraction changes. +The six-copy and unpruned three-copy intermediates exist only inside reconstruction +ancestry. The public result and proof describe the final three-copy word consistently. +[VALIDATION.json](VALIDATION.json) records actual local validation separately +from hosted CI. + +## Open next questions + +- Can the coded source interface be composed and its terminal code removed at + the actual capped target endpoints for a fully priced global supplier? +- Can that complete word obtain a rigorous rounded cleanup/precision bound + and a physical owner, access and tape schedule within a useful joint budget? + +[TASK.json](TASK.json) gives concrete first steps and blockers. Local prefix +norms and the rank saving do not settle these obligations. Existing family +ceilings apply only under their original hypotheses; this change does not +establish a new coverage law or authorize an unbounded construction round. + +## Sources and credit + +The live R438 word and baseline replay retain Ali Romman's construction and +boundary-persistence work, Sagar Thakrar's transport/rehosting work, and the +DreamingOfClouds/eumemic/PR589/PR555/PR543/PR545/PR510 lineage credited by those sources. +Ali Romman's [PR1862](https://github.com/CrocSwap/integer-mult-bounds/pull/1862) +(`bb29ea73ad9be9a0c3d53cdcb1d22b2ee9ffe42f`) +provides the prior ordered-ring source-code/unit-transfer motif. Hanson +Sun/bbMisk's [PR1522](https://github.com/CrocSwap/integer-mult-bounds/pull/1522) +provides related restored mutable-source-query tours. These are conceptual +predecessors, not runtime imports or claims that generic source coding is new. + +Ross Richardson, with substantial OpenAI Codex assistance in construction, +independent agent audit, proof and packaging. The audit is a separate AI +implementation, not human review or formal-kernel verification. Apache-2.0. diff --git a/research/bit-r438-source-code/SOURCES.json b/research/bit-r438-source-code/SOURCES.json new file mode 100644 index 0000000000..716a784d21 --- /dev/null +++ b/research/bit-r438-source-code/SOURCES.json @@ -0,0 +1,30 @@ +{ + "schema_version": 1, + "base_commit": "20ecf2891d80b5acf18d980b2164fb44ea7faa90", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "b1fea0c94436b236cc2b7d41a7be032811b94c81", + "sha256": "bb2eaa58647b353f88d0aec2eafb9d30df1be53589231b23e12ceef3e4bad129" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "67f085acd86acd7d4e03922d9cf4b26bca66fed5", + "sha256": "47b42433f5a85809a3aadd29c2c339da2c6ed728e4f7762df6b88bccb7874cf0" + }, + { + "path": "research/bit-boundary-persistence/build.py", + "usage": "input", + "git_blob": "074d045cf6a5de84f67bd772ae422edc051d3c6e", + "sha256": "58f402c365eb18b9c3dd736523999676f1d1652e40c1a9b4f6967c1b7acb72df" + }, + { + "path": "research/bit-r438-transport-rehost/words/r438-t154.json.gz", + "usage": "input", + "git_blob": "e12a566658a4b2c8b6ae0ecc34fd41290f68f5e8", + "sha256": "a353999bceac4ac957f540adfd3e5f8768297138b27132eeb83332e2ea4b1022" + } + ] +} diff --git a/research/bit-r438-source-code/TASK.json b/research/bit-r438-source-code/TASK.json new file mode 100644 index 0000000000..b9cc1450ed --- /dev/null +++ b/research/bit-r438-source-code/TASK.json @@ -0,0 +1,71 @@ +{ + "schema_version": 1, + "task_id": "coverage-law-change", + "priority_revision": 6, + "base_commit": "20ecf2891d80b5acf18d980b2164fb44ea7faa90", + "original_card": { + "id": "coverage-law-change", + "question": "Can a template or call contract leave two or more unpaid coordinates per live family?", + "starting_points": [ + "docs/research/research-family-status.md", + "research/complex-local-word-ceiling/README.md", + "research/idle-axis-hosting/PROOF.md", + "certificates/selected-result.json" + ], + "methods": [ + "State a replacement for the coverage identity (mass = 72W + 64N) and the contract change that realizes it, with its implementation cost.", + "Find an obstruction: show which data-endpoint obligation forces exactly one unpaid coordinate in the current template." + ], + "acceptance_gate": "An explicit replacement identity, verified on a small complete instance with dirty inputs, priced with ceiling.ceiling(unpaid=...). A scoped local result may be retained without a complete supplier. Expanding it into further construction rounds requires the family-level budget and obligation gate in research-family-status.md; an optimistic passing relaxation alone is not acceptance.", + "first_step": { + "command": [ + "python3", + "-B", + "research/complex-local-word-ceiling/verify.py" + ], + "expected": "PASS_COMPLEX_LOCAL_WORD_CEILING", + "inspect": "Read the selected word's per-call local profile, its packing ceiling and the lever table; run levers.py for the ideal budget of the lever you target.", + "scope": "Positive control and planning budget only; this is not a new construction or full cold replay." + }, + "first_experiment": "Explain where the single unpaid coordinate per family comes from in the hosted template; propose one change and price it. Ideal budget: two unpaid coordinates per family is 3.77x (levers.py).", + "bottleneck_link": "The deficit is one coordinate per family minus the centre charge; doubling unpaid coordinates per family scales it directly.", + "allowed_variations": [ + "One template change or one endpoint-contract change.", + "If the coverage law, template or guard changes, derive an applicable fully charged replacement bound instead of applying the incumbent ceiling outside its scope." + ], + "scope_change_triggers": [ + "Counting a coordinate as unpaid while leaving it unadvanced in the data endpoint.", + "Continuing a partial cost improvement while leaving the same unpriced consumer, restoration or central-readout obligation unresolved; refresh the family expansion decision first. Local product-retiming evidence has a narrow scope and is not a ban on changed graphs or contracts." + ], + "overlap_terms": [ + "coverage identity", + "unpaid coordinate", + "deficit law", + "W - 64N" + ] + }, + "scope_status": "changed", + "actual_scope": "Source-pinned R438 local source-code replacement with three actual target repairs and deletion of nine unread physical families, giving 429 dirty helpers; exact signed restoration and complete local frame/rank invoice.", + "scope_change_reason": "The original card asks for a new full coverage law. This scoped contribution changes the local source contract and prices its literal word; it does not claim an all-family law or global supplier. The priority-6 family gate permits independently useful local results without global expansion.", + "bottleneck_link": "Nine rank-7 copied centres become three rank-1 source snapshots; nine subsequently unread helpers are deleted. Local mass 5121->4989. Returning those nine width-8 families to idle-owner children cancels 72 of the local reduction at beta=0 under incumbent accounting. The source endpoint changes, and terminal decoding plus all global implementation costs remain open.", + "budget_minutes": 240, + "stop_rule": "Stop after one source-closed local construction and independent replay; no global supplier or kappa admission without complete caller, native, precision, owner, tape and joint outer obligations.", + "outcome": "partial", + "evidence": "PROOF.md; WORD.json.gz; registered verify.py regenerates and independently checks the complete local result.", + "author": "Ross Richardson, with substantial OpenAI Codex assistance", + "ai_assistance": "Substantial OpenAI Codex assistance, including separate producer and independent audit agents; no human or formal-kernel review claimed.", + "open_questions": [ + { + "question": "Can the changed source code be composed and its terminal code removed at the actual cap endpoints?", + "why_it_matters": "A local source-code saving is not a global supplier saving until the caller interface and decoder costs are paid.", + "first_step": "Write the exact global source/target code and price a literal cap-compatible terminal decoder, including dirty restoration.", + "blocked_by": "No full endpoint/decoder construction is admitted by this package." + }, + { + "question": "Does a fully composed word meet rounded precision, owner, access and physical tape bounds in a useful joint budget?", + "why_it_matters": "The local signed prefix norms and frame invoice do not establish the recursive implementation contract.", + "first_step": "After a concrete global word exists, derive complete perturbation weights and chronological physical storage/call bounds before any outer transfer.", + "blocked_by": "The global word and complete caller/decoder contract are unresolved here." + } + ] +} diff --git a/research/bit-r438-source-code/VALIDATION.json b/research/bit-r438-source-code/VALIDATION.json new file mode 100644 index 0000000000..00220476fd --- /dev/null +++ b/research/bit-r438-source-code/VALIDATION.json @@ -0,0 +1,83 @@ +{ + "status": "PASS_LOCAL_REGISTERED_SCOPE", + "scientific_result": { + "address_columns": 3552, + "ancestry_controls": 11, + "canonical_frozen_word_sha256": "ebc33ee086f610c1fd540fa56bb99b2b96a768e4aed4a18defcb0e1f507fca89", + "columns": 651, + "counts": { + "0": 2873, + "1": 13223, + "2": 3, + "3": 3 + }, + "dirty_helpers": 429, + "frame_bindings": 222, + "independent_controls": [ + "wrong_integer_unprepare_sign", + "omit_pivot_unprepare", + "FULL_to_FULL_copy", + "mutate_live_source", + "reuse_noninvolutive_code_as_inverse", + "wrong_section_query", + "read_deleted_family" + ], + "native_projectors": 111, + "no_new_kappa": true, + "profile": { + "1": 1298, + "2": 1342, + "3": 79, + "4": 44, + "5": 93, + "6": 11, + "7": 9 + }, + "python": "3.12.12 (main, Oct 9 2025, 11:07:00) [Clang 17.0.0 (clang-1700.6.3.2)]", + "rank_mass": 4989, + "rank_saving": 132, + "scope": "Exact local signed and F2 operators, complete common-frame/rank invoice and rational cap ADDRESS identities; no global compiler, precision, owner or kappa admission", + "seconds": 14.474679999999353, + "semantic_word_sha256": "e5fa1dbcb80f61c7c728bad7cc166f368ec73c673828273bea091caba8708892", + "stages": [ + "reconstruct", + "check" + ], + "status": "PASS_R438_THREE_SOURCE_COPIES_LOCAL_ONLY" + }, + "command": [ + "python3.12", + "-I", + "-O", + "-B", + "-Werror", + "research/bit-r438-source-code/verify.py", + "--out", + "FRESH_EXTERNAL_OUTPUT" + ], + "separate_ai_audit": { + "source_sha256": "d284714fd65054279c180454b73eb717382e402669d5a04e3f373d0d7f54bc06", + "receipt_sha256": "4efc043e71ba125bacfcdb1e2ed638dee685479846f70b2d863e889a5c075ec9", + "support_audit_source_sha256": "1c2687271b96b8e3bee1da9572b1af7596b4e506d8d803293af5b974ba057272", + "support_audit_receipt_sha256": "feb4e3ae776afad07802ef277d022f8bac6aeb177d7fe2057c35d75a03574164", + "scope": "Separate audit of exact unread-family projection, all651 signed/F2 columns,429 helpers and full invoice. Public check.py retains its exact projected/execute function bodies and adds direct original-word matrix derivation, native cap identities and seven fault controls. No human/formal review implied." + }, + "metadata": "PASS_PACKAGE_METADATA_AND_PINS", + "committed_byte_source_history": "pending final commit", + "committed_git_free_export": "pending final commit", + "hosted_ci": "not yet published", + "limitations": [ + "No global controller, terminal decoder, precision, owner/tape or kappa admission.", + "Two live source inputs are ancestral canonical20ec bytes; full original Git history required only by metadata/source-history gates." + ], + "registered_runner": { + "status": "PASS_REGISTERED_RESEARCH_PACKAGE", + "seconds": 14.44879658300124, + "command": [ + "python3.12", + "scripts/research_package.py", + "--package", + "research/bit-r438-source-code" + ] + } +} diff --git a/research/bit-r438-source-code/VERIFY.json b/research/bit-r438-source-code/VERIFY.json new file mode 100644 index 0000000000..bafb74f7ce --- /dev/null +++ b/research/bit-r438-source-code/VERIFY.json @@ -0,0 +1,24 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/bit-boundary-persistence/build.py", + "research/bit-r438-transport-rehost/words/r438-t154.json.gz" + ], + "commands": [ + { + "argv": [ + "{python}", + "-I", + "-O", + "-B", + "-Werror", + "{package}/verify.py" + ], + "timeout_seconds": 600, + "checks": "Complete live-source regeneration and literal dead-family projection, decompressed word equality, independent 651-column integer/F2 forward and inverse, all 429 helper restoration, 111 exact native cap identities, full frame/rank invoice, eleven ancestry and seven independent defect controls." + } + ] +} diff --git a/research/bit-r438-source-code/WORD.json.gz b/research/bit-r438-source-code/WORD.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..672c41534608d0d812b8020e496177d7c41c8527 GIT binary patch literal 59514 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

q_V!^G2pb`8%%8O#)sms+W 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 literal 0 HcmV?d00001 diff --git a/research/bit-r438-source-code/check.py b/research/bit-r438-source-code/check.py new file mode 100644 index 0000000000..9da42bb5ff --- /dev/null +++ b/research/bit-r438-source-code/check.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python3 +"""Independent sparse integer / F2 endpoint and rational native-cap replay. + +No producer module is imported. Every public input is an independent column. +""" +from collections import Counter +import argparse +import gzip +import hashlib +import json +from pathlib import Path +import types + +HERE = Path(__file__).resolve().parent + +def load(name): + path = HERE / (name + ".py") + module = types.ModuleType(name) + exec(compile(path.read_bytes(), str(path), "exec"), module.__dict__) + return module + +cap, scalar = load("native_caps"), load("signed_rows") +need = cap.need + +def projected(program): + dead = [h for h in range(222,660) + if all(not(op == 1 and s == h or op in (2,3) and d == h) + for op,d,s,c,f,p in program['records'])] + need(dead == list(range(471,480)),'unread physical helper classification') + dead_set = set(dead) + keep = [p for p in range(660) if p not in dead_set] + mapping = {old:new for new,old in enumerate(keep)} + mapping[660] = len(keep) + records = [] + removed = Counter() + for op,d,s,c,f,p in program['records']: + if d in dead_set: + need(op in (0,1),'discarded helper has an owned snapshot role') + if op == 0: + removed[f] += 1 + continue + need(op == 0 or s not in dead_set,'remaining record reads discarded input') + records.append([op,mapping[d],s if op == 0 else mapping[s],c,f,p]) + return keep,records,dict(sorted(removed.items())) + +def execute(word,keep,records,backward=False,initial=None): + n = len(keep) + rows = ([{i:1} for i in range(n)]+[{}]) if initial is None else [r.copy() for r in initial] + frames = [word['final' if backward else 'start'][i] for i in keep]+[None] + dims = [cap.rank(word['lines'][j] for j in f) for f in word['frames']] + masks = [sum(1 << j for j in f) for f in word['frames']] + opened,copies,prefix = None,0,1 + profile,counts = Counter(),Counter() + for op,d,s,c,f,p in reversed(records) if backward else records: + counts[op] += 1 + if op == 0: + old,new = (c,s) if backward else (s,c) + lo,hi = (new,old) if backward else (old,new) + need(frames[d] == old and not masks[lo] & ~masks[hi] and dims[hi]-dims[lo] == f > 0,'projected MOVE frame/rank') + frames[d] = new + profile[f] += 1 + elif op == 1: + need(d < n and d != s and frames[d] == frames[s] == f and d != opened,'projected common-frame ADD or snapshot source mutation') + rows[d] = scalar.add(rows[d],rows[s],-c if backward else c) + prefix = max(prefix,sum(abs(v) for v in rows[d].values())) + elif op == (3 if backward else 2): + need(opened is None and s == n and not rows[n] and frames[n] is None,'projected fresh private field') + need(d < 111 and frames[d] == c == 1 and not masks[f] & ~masks[c] and dims[c]-dims[f] == 1,'projected actual source cap COPY') + rows[n],frames[n],opened = rows[d].copy(),f,d + profile[1] += 1 + copies += 1 + else: + need(op == (2 if backward else 3) and opened == d and s == n and rows[n] == rows[d] and frames[d] == c and frames[n] == f,'projected immutable snapshot ERASE') + rows[n],frames[n],opened = {},None,None + need(opened is None and not rows[n] and frames[n] is None and copies == 3,'projected private endpoint') + need(frames[:n] == [word['start' if backward else 'final'][i] for i in keep],'retained physical endpoint frames') + need(profile == Counter({1:1298,2:1342,3:79,4:44,5:93,6:11,7:9}),'projected paid profile') + need(counts == Counter({0:2873,1:13223,2:3,3:3}),'projected literal record counts') + return rows,{'prefix_row_l1':prefix,'profile':dict(sorted(profile.items())), + 'rank_mass':sum(k*v for k,v in profile.items()),'copies':copies, + 'counts':dict(sorted(counts.items()))} + +def binary_rank(rows): + basis = {} + for row in rows: + while row: + p = row.bit_length() - 1 + if p not in basis: + basis[p] = row + break + row ^= basis[p] + return len(basis) + +def binary_product(a, b): + output = [] + for row in a: + value = 0 + for i, other in enumerate(b): + if row >> i & 1: + value ^= other + output.append(value) + return output + +def matrices(raw, meta): + rows = [1 << i for i in range(660)] + for phase in ("D", "A"): + for _, dst, sources in raw[phase]: + for src in sources: + rows[dst] ^= rows[src] + mask = (1 << 111) - 1 + need(all(not(rows[j] & (((1 << 111)-1) << 111)) for j in raw["ret"]), "retained target dependency") + R = [rows[j] & mask for j in raw["ret"]] + K = [sum(1 << j for j in subset) for subset in raw["scatter"]] + M = binary_product(R, K) + J = [(1 << i) ^ r for i, r in enumerate(binary_product(K, R))] + need((R, K, M, J) == tuple(meta[k] for k in ("R", "K", "M", "J")), "actual raw R/K/J binding") + need(M == [507,135,238,349,185,437,205,503,425], "actual quotient matrix") + need(binary_rank(R) == binary_rank(M) == 9 and binary_rank(J) == 108, "actual ranks") + eye = [1 << i for i in range(111)] + A, inv, Q = (meta[k] for k in ("H", "Hinv", "Q")) + direct_A = [eye[i] if i < 3 else J[i] for i in range(111)] + need(A == direct_A and A[:3] == [1,2,4], "actual row-deletion source code") + N = [(1 << i) ^ row for i,row in enumerate(M)] + S = [sum(((row >> p) & 1) << p for p in range(3)) for row in R] + D = K[:3] + Y = [a ^ b for a,b in zip(N,binary_product(S,D))] + B0 = meta["B0"] + need(Y == [10,373,282,165,176,405,356,145,166] and binary_rank(Y) == 9, "invertible actual quotient") + need(binary_product(B0,N) == [0]*3 and binary_product(B0,S) == [1,2,4], "left-null section") + need(binary_product(B0,Y) == D and meta["Y"] == Y and meta["D"] == D, "quotient repair identity") + need(binary_product(A, inv) == binary_product(inv, A) == eye, "source-code inverse") + need(binary_product(J, inv) == [a ^ b for a,b in zip(eye,Q)], "section equation") + need([i for i,r in enumerate(Q) if r] == [0,1,2] and binary_rank(Q) == 3, "three actual target rows") + need(binary_rank([a ^ b for a,b in zip(A,eye)]) == 9, "source-code rank") + return A, inv + +def source_code(records): + code = [r for r in records if r[0] == 1 and r[5] in (21,22,23,24)] + need(len(code) == 1499, "complete source-code gates") + forward, reverse = scalar.identity(111), scalar.identity(111) + for _, x, y, c, frame, phase in code: + need(x < 111 and y < 111 and frame == 1, "source-only code") + forward[x] = scalar.add(forward[x], forward[y], c) + for _, x, y, c, frame, phase in reversed(code): + reverse[x] = scalar.add(reverse[x], reverse[y], -c) + return forward[:111], reverse[:111] + +def endpoints(forward, reverse, records, A, inv): + az, azi = source_code(records) + need(forward[:111] == az and reverse[:111] == azi, "exact integer source and inverse") + need(scalar.parity(az) == A and scalar.parity(azi) == inv, "source parity binding") + n = len(forward) - 1 + eye = scalar.identity(n) + for i in range(222,n): + need(forward[i] == reverse[i] == eye[i], "arbitrary dirty helper restoration") + for rows in (forward, reverse): + for p in range(111): + need({j:c for j,c in rows[111+p].items() if 111 <= j < 222} == {111+p:1}, "target identity block") + need(all(c % 2 == 0 for j,c in rows[111+p].items() if j >= 222), "target even helper leakage") + expected_f = [1 << i for i in range(n)] + [0] + expected_r = expected_f[:] + for i in range(111): + expected_f[i], expected_f[111+i] = A[i], expected_f[111+i] ^ A[i] + expected_r[i], expected_r[111+i] = inv[i], expected_r[111+i] ^ (1 << i) + need(scalar.parity(forward) == expected_f and scalar.parity(reverse) == expected_r, "all 651 F2 endpoint columns") + +def rejection(label, fn): + try: + fn() + except ValueError: + return label + raise ValueError("Defect control escaped: " + label) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--repo", type=Path, required=True) + parser.add_argument("--out", type=Path, required=True) + args = parser.parse_args() + expected = json.loads((HERE / "EXPECTED.json").read_bytes()) + source = args.repo / expected["source_word"] + need(hashlib.sha256(source.read_bytes()).hexdigest() == expected["source_sha256"], "original native source hash") + raw = json.loads(gzip.decompress(source.read_bytes())) + word = json.loads(gzip.decompress((args.out / "BIT-PRUNED-WORD.json.gz").read_bytes())) + support = json.loads(gzip.decompress((args.out / "support/BIT-SUPPORT-WORD.json.gz").read_bytes())) + keep, projected_records, removed = projected(support) + need(len(keep) == 651 and removed == {1:27,5:9}, "complete unread-family projection") + need(word["records"] == projected_records and word["public_registers"] == word["private_register"] == 651, "complete literal projected word") + need(word["deleted_public_families"] == list(range(471,480)), "deleted physical identities") + need(word["start"] == [raw["start"][i] for i in keep] and word["final"] == [raw["final"][i] for i in keep], "projected actual boundary frames") + meta = json.loads((args.out / "support/BIT-SUPPORT.json").read_bytes())["matrices"] + need(hashlib.sha256(cap.canonical(meta)).hexdigest() == expected["source_matrix_sha256"], "complete final matrix payload") + A, inv = matrices(raw, meta) + records = word["records"] + forward, fwd = execute(raw, keep, records) + reverse, rev = execute(raw, keep, records, True) + endpoints(forward, reverse, records, A, inv) + roundtrip, _ = execute(raw, keep, records, True, forward) + need(roundtrip == scalar.identity(651), "full integer roundtrip") + projectors = cap.address_identities(raw) + need([r[1] for r in records if r[0] == 2] == [0,1,2], "actual source pivots") + need(fwd["prefix_row_l1"] == 34285 and rev["prefix_row_l1"] == 5839860, "exact local integer prefix norms") + sign_records = [r[:3]+[-r[3]]+r[4:] if r[0] == 1 and r[5] == 33 else r[:] for r in records] + bad_sign, _ = execute(raw, keep, sign_records) + need(scalar.parity(bad_sign) == scalar.parity(forward) and bad_sign[:111] != forward[:111], "sign defect distinguished beyond parity") + controls = ["wrong_integer_unprepare_sign"] + controls.append(rejection("omit_pivot_unprepare", lambda: execute(raw,keep,[r for r in records if not(r[0] == 1 and r[5] == 33)]))) + bad = [r[:] for r in records] + position = next(i for i,r in enumerate(bad) if r[0] == 2) + bad[position][4] = 1 + controls.append(rejection("FULL_to_FULL_copy", lambda: execute(raw,keep,bad))) + bad = [r[:] for r in records] + position = next(i for i,r in enumerate(bad) if r[0] == 2) + pivot = bad[position][1] + bad.insert(position+1,[1,pivot,(pivot+1)%111,1,1,99]) + controls.append(rejection("mutate_live_source", lambda: execute(raw,keep,bad))) + controls.append(rejection("reuse_noninvolutive_code_as_inverse", lambda: endpoints(forward, reverse, records, A, A))) + wrong = dict(meta) + wrong["Q"] = meta["Q"][:] + wrong["Q"][0] ^= 1 + controls.append(rejection("wrong_section_query", lambda: matrices(raw,wrong))) + bad_support = dict(support, records=support["records"]+[[1,111,471,1,0,99]]) + controls.append(rejection("read_deleted_family", lambda: projected(bad_support))) + result = {"status":"PASS_INDEPENDENT_LOCAL_SIGNED_NATIVE", "columns":651, "dirty_helpers":429, + "source_code_rank":9, "clean_target_rank":108, "minimal_repair_rows_in_fixed_class":3, + "forward":fwd, "inverse":rev, "projectors":len(projectors), "address_columns":3552, + "frame_bindings":222, "deleted_original_families":list(range(471,480)), "removed_profile":removed, "projector_hashes":projectors, "controls":controls, + "integer_target_contract":"y+T_Z x+E_Z h; T_Z mod2=A and E_Z even", "no_new_kappa":True} + (args.out / "INDEPENDENT.json").write_text(json.dumps(result,indent=2,sort_keys=True)+"\n") + print(json.dumps({k:result[k] for k in ("status","columns","dirty_helpers","source_code_rank","projectors","controls","no_new_kappa")},sort_keys=True)) + +if __name__ == "__main__": + main() diff --git a/research/bit-r438-source-code/native_caps.py b/research/bit-r438-source-code/native_caps.py new file mode 100644 index 0000000000..5fdd309b4c --- /dev/null +++ b/research/bit-r438-source-code/native_caps.py @@ -0,0 +1,56 @@ +"""Independent exact rational E8 cap ADDRESS identities; no controller.""" +from fractions import Fraction as Q +from hashlib import sha256 +import json + +def need(ok, message): + if not ok: + raise ValueError(message) + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(',', ':')).encode() + +def rank(rows): + basis = {} + for row in rows: + row = list(map(Q, row)) + for j, old in sorted(basis.items()): + c = row[j] + row = [x-c*y for x,y in zip(row,old)] + j = next((j for j,x in enumerate(row) if x), None) + if j is not None: + c = row[j] + basis[j] = [x/c for x in row] + return len(basis) + +def identity(n): + return [[Q(i == j) for j in range(n)] for i in range(n)] + +def multiply(a, b): + return [[sum(x*y for x,y in zip(row,col)) for col in zip(*b)] for row in a] + +def exchange(u): + c = [[Q(i == j)-u[i][j] for j in range(8)] for i in range(8)] + return [c[i]+u[i] for i in range(8)]+[u[i]+c[i] for i in range(8)] + +def address_identities(word): + ident = identity(8) + out = [] + for p, q in enumerate(word['lines']): + need(sum(x*x for x in q) == 4, 'actual E8 root norm') + start = [word['lines'][j] for j in word['frames'][word['start'][p]]] + cap = [word['lines'][j] for j in word['frames'][word['final'][111+p]]] + need(rank(start) == 1 and all(all(4*x == sum(a*b for a,b in zip(row,q))*y + for x,y in zip(row,q)) for row in start), 'actual entrance is not P_p') + need(rank(cap) == 7 and all(sum(x*y for x,y in zip(row,q)) == 0 for row in cap), + 'actual target cap is not K_p') + proj = [[Q(x*y,4) for y in q] for x in q] + complement = [[ident[i][j]-proj[i][j] for j in range(8)] for i in range(8)] + need(multiply(proj,proj) == proj and rank(proj) == 1, 'actual P_p projector') + need(multiply(exchange(ident),exchange(proj)) == exchange(complement), + 'D_I D_P differs from D_K') + need(multiply(exchange(proj),exchange(proj)) == identity(16), 'D_P squared differs from I') + encoded = [[[v.numerator,v.denominator] for v in row] for row in proj] + out.append(sha256(canonical(encoded)).hexdigest()) + need(len(out) == 111, 'actual punctured root count') + return out diff --git a/research/bit-r438-source-code/producer/bit_scalar_invoice.py b/research/bit-r438-source-code/producer/bit_scalar_invoice.py new file mode 100644 index 0000000000..97d7559df0 --- /dev/null +++ b/research/bit-r438-source-code/producer/bit_scalar_invoice.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +"""Literal scalar/integer prefix invoice of the three-target R438 producer. + +No native operator lowering is assumed here. The ordered integer lift uses +the emitted forward ADD coefficients +1; its inverse reverses the exact word +and uses -1. Only reduction modulo2 has the declared coded BIT endpoint. +""" +from collections import Counter +import gzip +import hashlib +import json +from pathlib import Path +import sys + +sys.dont_write_bytecode = True +import bit_transvection as base + +HERE = Path(__file__).resolve().parent +N = 660 + + +def eye(n): + return [[int(i == j) for j in range(n)] for i in range(n)] + [[0]*n] + + +def digest(rows): + h = hashlib.sha256() + for row in rows: + h.update((','.join(map(str,row))+'\n').encode()) + return h.hexdigest() + + +def execute(records, initial, reverse=False, invert_sign=True): + rows = [row[:] for row in initial] + live, copies, maximum, phase_max = None, 0, 1, {} + for number,(op,dst,src,coefficient,frame,phase) in enumerate( + reversed(records) if reverse else records): + if op == 1: + sign = coefficient * (-1 if reverse and invert_sign else 1) + rows[dst] = [a+sign*b for a,b in zip(rows[dst],rows[src])] + value = sum(abs(x) for x in rows[dst]) + maximum = max(maximum,value) + phase_max[str(phase)] = max(phase_max.get(str(phase),0),value) + elif op == (3 if reverse else 2): + base.require(live is None and not any(rows[N]), 'Integer COPY overwrites private dirt') + rows[N], live = rows[dst][:], dst + maximum = max(maximum,sum(abs(x) for x in rows[N])) + copies += 1 + elif op == (2 if reverse else 3): + base.require(live == dst and rows[N] == rows[dst], + f'Integer ERASE snapshot changed at record{number}') + rows[N], live = [0]*N, None + else: + base.require(op == 0, 'Unknown integer operation') + base.require(live is None and not any(rows[N]), 'Integer private buffer not clear') + return rows,dict(maximum_exact_prefix_row_l1=maximum, + phase_exact_prefix_row_l1=phase_max,copies=copies, + endpoint_matrix_sha256=digest(rows), + endpoint_max_row_l1=max(sum(abs(x) for x in row) for row in rows)) + + +def parity(rows): + return [sum((x & 1) << j for j,x in enumerate(row)) for row in rows] + + +def small_bounds(records): + selected = [r for r in records if r[0] == 1 and 21 <= r[5] <= 24] + bounds, exact = [], [] + for reverse in (False,True): + values = [1]*111 + for op,dst,src,coefficient,frame,phase in reversed(selected) if reverse else selected: + values[dst] += abs(coefficient)*values[src] + bounds.append(max(values)) + rows = [[int(i == j) for j in range(111)] for i in range(111)] + maximum = 1 + for op,dst,src,coefficient,frame,phase in reversed(selected) if reverse else selected: + sign = coefficient * (-1 if reverse else 1) + rows[dst] = [a+sign*b for a,b in zip(rows[dst],rows[src])] + maximum = max(maximum,sum(abs(x) for x in rows[dst])) + exact.append(maximum) + return dict(adds=len(selected),forward_positive=bounds[0],reverse_positive=bounds[1], + forward_exact_prefix_l1=exact[0],reverse_exact_prefix_l1=exact[1], + extra_helpers=0,extra_private_fields=0) + + +def main(): + meta = json.loads((HERE/'BIT-THREE-ROW.json').read_text()) + blob = (HERE/'BIT-THREE-ROW-WORD.json.gz').read_bytes() + base.require(hashlib.sha256(blob).hexdigest() == meta['output_gzip_sha256'], + 'Three-row word pin changed') + word = json.loads(gzip.decompress(blob)) + records = word['records'] + start = eye(N) + forward,fwd = execute(records,start) + inverse,rev = execute(records,start,reverse=True) + roundtrip,rt = execute(records,forward,reverse=True) + base.require(roundtrip == start, 'Ordered integer inverse failed all660 columns') + bad,bad_stats = execute(records,forward,reverse=True,invert_sign=False) + base.require(bad != start, 'Wrong integer inverse sign control escaped') + expected_forward = [1 << j for j in range(N)] + [0] + expected_inverse = expected_forward[:] + for p in range(111): + expected_forward[p] = meta['matrices']['H'][p] + expected_forward[111+p] ^= meta['matrices']['H'][p] + expected_inverse[p] = meta['matrices']['Hinv'][p] + expected_inverse[111+p] ^= 1 << p + base.require(parity(forward) == expected_forward, 'Integer forward reduction differs') + base.require(parity(inverse) == expected_inverse, 'Integer inverse reduction differs') + positive = base.positive_bounds(records,N) + base.require(fwd['maximum_exact_prefix_row_l1'] == positive['forward'], + 'Forward positive envelope is not the exact nonnegative norm') + base.require(rev['maximum_exact_prefix_row_l1'] <= positive['reverse'], + 'Reverse triangle envelope failed') + counts = Counter(r[0] for r in records) + phase_adds = Counter(str(r[5]) for r in records if r[0] == 1) + copy_ranks = Counter(r[5] for r in records if r[0] == 2) + boundary = Counter(r[4] for r in records if r[0] == 0) + output = dict(status='PASS_LITERAL_SCALAR_INTEGER_LIFT_AND_INVERSE_NO_GLOBAL_TRANSFER', + source_word_gzip_sha256=meta['output_gzip_sha256'], + covered_integer_columns=N,covered_integer_endpoint_coefficients=N*N, + forward=fwd,reverse_signed=rev,roundtrip_signed=rt, + source_code=small_bounds(records),positive=positive, + scalar_invoice=dict(ADD=counts[1],MOVE_children=counts[0],COPY=counts[2],ERASE=counts[3], + ADDs_per_phase=dict(sorted(phase_adds.items())), + COPY_rank_histogram=dict(sorted(copy_ranks.items())), + MOVE_rank_histogram=dict(sorted(boundary.items())), + owned_private_fields=1,max_live_immutable_snapshots=1, + public_source_fields=111,public_target_fields=111, + public_dirty_helper_fields=438, + new_source_code_helpers=0,new_source_code_private_fields=0, + extra_repair_helper_fields=0,reused_repair_helper=222), + negative_control=dict(wrong_reverse_integer_sign_detected=True, + bad_roundtrip_sha256=bad_stats['endpoint_matrix_sha256'], + F2_signs_cannot_detect_this_control=True), + exact_lift_statement='The emitted integer forward matrix reduces modulo2 to(Ax,y+Ax,h). Its exact inverse is the reversed word with negative ADD coefficients; all660 input columns restore overZ. The forward helper rows are NOT claimed to be identity overZ.', + precision_statement='F and reverse triangleR are exact ordered scalar envelopes for inputs with absolute value at most1, scaling linearly for larger bounds. Historical104/192 bit guards fail;173/320 are numerical sufficient exponents for the old scalar formulas, with applicability to a changed native/global interface still owed.', + unresolved=['Native field/address transport and actual integer normalization', + '63 extra global code bridges, their signed integer lift and full prefix bounds', + 'Terminal N E^-1 N, chronological owner and physical stock', + 'Complete payload/numerical scratch and all-size recurrence repricing']) + (HERE/'BIT-SCALAR-INVOICE.json').write_text(json.dumps(output,indent=2,sort_keys=True)+'\n') + print(json.dumps({k:output[k] for k in ('status','forward','reverse_signed','source_code','scalar_invoice')}, + indent=2,sort_keys=True)) + + +if __name__ == '__main__': + main() diff --git a/research/bit-r438-source-code/producer/bit_section_code.py b/research/bit-r438-source-code/producer/bit_section_code.py new file mode 100644 index 0000000000..71c0e4d4ba --- /dev/null +++ b/research/bit-r438-source-code/producer/bit_section_code.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +"""R438 source coding with three actual repaired target rows over F2. + +The source code is invertible and generally not an involution. Its literal +inverse is used on the backward local call. This is a local changed interface, +with native/global/precision admission left to independent work. +""" +from collections import Counter +import gzip +import hashlib +import json +from pathlib import Path +import sys + +sys.dont_write_bytecode = True +import bit_transvection as base + +HERE = Path(__file__).resolve().parent +need, prod, inv, bits, rank = base.require, base.product, base.inverse, base.bits, base.rank + + +def transpose(rows, n): + return [sum(((row >> j) & 1) << i for i, row in enumerate(rows)) for j in range(n)] + + +def kernel(rows, n): + rows, pivots, used = rows[:], [], 0 + for j in range(n): + p = next((i for i in range(used, len(rows)) if rows[i] >> j & 1), None) + if p is None: + continue + rows[used], rows[p] = rows[p], rows[used] + for i in range(len(rows)): + if i != used and rows[i] >> j & 1: + rows[i] ^= rows[used] + pivots.append(j) + used += 1 + result = [] + for j in range(n): + if j not in pivots: + value = 1 << j + for i, p in enumerate(pivots): + if rows[i] >> j & 1: + value |= 1 << p + result.append(value) + need(prod(rows, transpose(result, n)) == [0] * len(rows), 'Kernel failed') + return result + + +def particular(left, right): + """Solve left X=right with all nonpivot variables zero.""" + n = len(left) + rows = [a | (b << n) for a, b in zip(left, right)] + pivots, used = [], 0 + for j in range(n): + p = next((i for i in range(used, n) if rows[i] >> j & 1), None) + if p is None: + continue + rows[used], rows[p] = rows[p], rows[used] + for i in range(n): + if i != used and rows[i] >> j & 1: + rows[i] ^= rows[used] + pivots.append(j) + used += 1 + need(all(row >> n == 0 for row in rows[used:]), 'Inconsistent right-hand side') + result = [0] * n + for i, p in enumerate(pivots): + result[p] = rows[i] >> n + need(prod(left, result) == right, 'Particular solution failed') + return result + + +def cnot_word(matrix): + """A literal row-ADD circuit for an invertible binary square matrix.""" + rows, ops = matrix[:], [] + n = len(rows) + def add(dst, src): + rows[dst] ^= rows[src] + ops.append((dst, src)) + for j in range(n): + p = next((i for i in range(j, n) if rows[i] >> j & 1), None) + need(p is not None, 'Singular CNOT matrix') + if p != j: + add(j, p) + add(p, j) + add(j, p) + for i in range(n): + if i != j and rows[i] >> j & 1: + add(i, j) + need(rows == [1 << i for i in range(n)], 'CNOT elimination failed') + rows = [1 << i for i in range(n)] + result = list(reversed(ops)) + for dst, src in result: + rows[dst] ^= rows[src] + need(rows == matrix, 'CNOT circuit order failed') + return result + + +def section(data): + R, K, M, J = (data[k] for k in ('R', 'K', 'M', 'J')) + N = [(1 << i) ^ row for i, row in enumerate(M)] + C0 = kernel(transpose(N, 9), 9) + need(len(C0) == 3, 'Wrong left-nullity') + C = prod(C0, R) + selected, columns = [], [] + for p in range(111): + column = sum(((row >> p) & 1) << j for j, row in enumerate(C)) + if rank(columns + [column]) > len(columns): + selected.append(p) + columns.append(column) + if len(selected) == 3: + break + S = [sum(((row >> p) & 1) << j for j, p in enumerate(selected)) for row in R] + B0 = prod(inv(prod(C0, S)), C0) + need(prod(B0, S) == [1 << j for j in range(3)], 'Bad rank3 section') + F9 = [(1 << j) ^ row for j, row in enumerate(prod(S, B0))] + X0 = particular(N, F9) + T = transpose(kernel(N, 9), 9) + X = [a ^ b for a, b in zip(X0, prod(T, B0))] + need(rank(X) == 9 and prod(N, X) == F9, 'Invertible quotient lift failed') + PB = [0] * 111 + for j, p in enumerate(selected): + PB[p] = B0[j] + W = [a ^ b for a, b in zip(prod(K, X), PB)] + Hinv = [(1 << p) ^ row for p, row in enumerate(prod(W, R))] + need(rank(Hinv) == 111, 'Source inverse code singular') + H = inv(Hinv) + Q = prod(PB, R) + need(prod(J, Hinv) == [(1 << p) ^ row for p, row in enumerate(Q)], 'JHinv residual failed') + need([a ^ b for a,b in zip(J, prod(Q, H))] == H, 'Coded target identity failed') + need(prod(H, Hinv) == [1 << p for p in range(111)], 'Source code inverse failed') + need([p for p,row in enumerate(Q) if row] == selected, 'Wrong target support') + return dict(R=R, K=K, M=M, J=J, N=N, C0=C0, C=C, selected=selected, + S=S, B0=B0, F9=F9, X0=X0, T=T, X=X, W=W, + H=H, Hinv=Hinv, Q=Q) + + +def compact_code(data, pivots): + # Replace nine physical pivot coordinates by a normalized query basis. + R = data['R'] + S = [sum(((row >> p) & 1) << j for j,p in enumerate(pivots)) for row in R] + query = prod(inv(S), R) + B = [1 << p for p in range(111)] + prepare = [] + for j, p in enumerate(pivots): + B[p] = query[j] + for src in bits(query[j] ^ (1 << p)): + need(src not in pivots, 'Normalized query still mixes pivots') + prepare.append([1, p, src, 1, 1, 21]) + need(prod(B, B) == [1 << p for p in range(111)], 'Query change not involutive') + middle = prod(prod(B, data['H']), B) + pivot_set = set(pivots) + D = [sum(((middle[p] >> q) & 1) << j for j,q in enumerate(pivots)) for p in pivots] + fanout = [] + for p in range(111): + allowed = sum(1 << q for q in pivots) | ((1 << p) if p not in pivot_set else 0) + need(middle[p] & ~allowed == 0, 'Source code has a non-query middle term') + if p not in pivot_set: + need(middle[p] >> p & 1, 'Nonpivot identity diagonal missing') + for src in bits(middle[p] ^ (1 << p)): + fanout.append([1, p, src, 1, 1, 22]) + small = [[1, pivots[d], pivots[s], 1, 1, 23] for d,s in cnot_word(D)] + unprepare = [rec[:5] + [24] for rec in reversed(prepare)] + records = prepare + fanout + small + unprepare + rows = [1 << p for p in range(111)] + for op, dst, src, coefficient, frame, phase in records: + rows[dst] ^= rows[src] + need(rows == data['H'], 'Compact source word differs from its code') + return records, dict(query=query, pivots=pivots, B=B, middle=middle, D=D, + prepare_adds=len(prepare), fanout_adds=len(fanout), + quotient_adds=len(small), unprepare_adds=len(unprepare)) + + +def main(): + word, builder, baseline, old_records = base.load() + old_data = base.matrices(word) + _, old_parts = base.construct(word, old_records, old_data) + data = section(old_data) + code, code_data = compact_code(data, old_data['selected']) + repair = [] + b, count, v = 222, 660, 111 + for p in data['selected']: + cap = word['final'][v+p] + episode = [[2,b,count,1,cap,1], [1,v+p,count,1,cap,15], [3,b,count,1,cap,0]] + gather = [[1,b,src,1,1,16] for src in bits(data['Q'][p])] + repair.extend(episode + gather + episode + [rec[:5]+[17] for rec in gather]) + records = old_parts['prefix'] + old_parts['clean'] + code + repair + forward = base.replay(word, builder, records, data) + reverse = base.replay(word, builder, records, data, reverse=True) + expect = Counter({int(k):n for k,n in baseline['profile'].items()}) + expect[7] -= 9 + expect[1] += 6 + need(forward['profile'] == dict(sorted(expect.items())), 'Profile differs') + need(reverse['profile'] == forward['profile'], 'Reverse profile differs') + need(forward['rank_mass'] == 5064 and forward['copies'] == 6, 'Wrong paid bill') + controls = [ + base.must_fail('omit_changed_D', lambda: base.replay( + word,builder,records[len(old_parts['prefix']):],data)), + base.must_fail('omit_query_unprepare', lambda: base.replay( + word,builder,[r for r in records if not(r[0] == 1 and r[5] == 24)],data)), + base.must_fail('omit_dirty_repair_restore', lambda: base.replay( + word,builder,[r for r in records if not(r[0] == 1 and r[5] == 17)],data)), + base.must_fail('mutate_copied_snapshot', lambda: base.replay( + word,builder,records,data,mutate_snapshot=True)), + base.must_fail('use_same_noninvolutive_code_in_reverse', lambda: base.replay( + word,builder,records,{**data,'Hinv':data['H']},reverse=True)), + ] + container = dict(format='coded-r438-three-row-local-records-v1', + public_registers=660,private_register=660, + source_word=str(base.WORD),source_gzip_sha256=base.WORD_SHA, + start=word['start'],final=word['final'],records=records, + copy_schema='[2,physical_source,660,sourceframe,privateframe,rank]', + erase_schema='[3,physical_source,660,sourceframe,privateframe,0]') + raw = base.canonical(container) + outword = HERE/'BIT-THREE-ROW-WORD.json.gz' + outword.write_bytes(gzip.compress(raw,mtime=0)) + output = dict(status='PASS_LOCAL_THREE_TARGET_ROWS_NO_GLOBAL_SUPPLIER_NO_NEW_KAPPA', + source_pin=base.MAIN_PIN,source_word=str(base.WORD),source_gzip_sha256=base.WORD_SHA, + baseline_builder_sha256=base.BUILDER_SHA, + output_word=str(outword),output_canonical_sha256=hashlib.sha256(raw).hexdigest(), + output_gzip_sha256=hashlib.sha256(outword.read_bytes()).hexdigest(), + matrices=data,source_code=code_data,forward=forward,reverse=reverse, + source_code_rank=rank([row^(1<(Ax,y+Ax,h)', + literal_inverse='(x,y,h)->(A^-1 x,y+x,h)', + matrix_names='H=A, Hinv=A^-1; J Hinv=I+Q', + initial_frames='source Pp; target0; helper0', + final_frames='source FULL; target Pp-perp; helper FULL', + copied_snapshots='Two unchanged arbitrary-helper snapshots per each of three target rows'), + scope='Finite660-column F2 proof and complete literal local frame/rank invoice; no native global admission', + unresolved=['Actual native operator lift and complementary backward frame interpretation', + 'Signed integer lift, new precision reserve, and physical scalar scratch', + 'Global19-event code and terminal cap decoder', + 'Chronological owners, unused remainders, full recursive supplier contract']) + (HERE/'BIT-THREE-ROW.json').write_text(json.dumps(output,indent=2,sort_keys=True)+'\n') + print(json.dumps({k:output[k] for k in ('status','forward','adds','part_adds','source_code_rank','positive')}, + indent=2,sort_keys=True)) + + +if __name__ == '__main__': + main() diff --git a/research/bit-r438-source-code/producer/bit_signed_lift.py b/research/bit-r438-source-code/producer/bit_signed_lift.py new file mode 100644 index 0000000000..6160f4540e --- /dev/null +++ b/research/bit-r438-source-code/producer/bit_signed_lift.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +"""Choose real signed cleanup for the unchanged three-row BIT construction. + +The coded BIT endpoint is modulo2. Unlike the original all-positive integer +lift, this forward lift restores all438 dirty helpers exactly overZ, and its +source code acts only on x. No native/global admission is inferred. +""" +from collections import Counter +import gzip +import hashlib +import json +from pathlib import Path +import sys + +sys.dont_write_bytecode = True +import bit_transvection as base +import bit_scalar_invoice as scalar + +HERE = Path(__file__).resolve().parent +N,V = 660,111 + + +def source_integer_code(records): + code = [r for r in records if r[0] == 1 and 21 <= r[5] <= 24] + rows = [[int(i == j) for j in range(V)] for i in range(V)] + for op,dst,src,c,frame,phase in code: + rows[dst] = [a+c*b for a,b in zip(rows[dst],rows[src])] + inverse = [[int(i == j) for j in range(V)] for i in range(V)] + for op,dst,src,c,frame,phase in reversed(code): + inverse[dst] = [a-c*b for a,b in zip(inverse[dst],inverse[src])] + trial = [row[:] for row in rows] + for op,dst,src,c,frame,phase in reversed(code): + trial[dst] = [a-c*b for a,b in zip(trial[dst],trial[src])] + base.require(trial == [[int(i == j) for j in range(V)] for i in range(V)], + 'Integer source code and inverse fail') + return rows,inverse + + +def column_control(records, input_column, bad_phase): + values = [int(i == input_column) for i in range(N)] + [0] + for op,dst,src,c,frame,phase in records: + if op == 1: + values[dst] += (1 if phase == bad_phase else c)*values[src] + elif op == 2: + values[N] = values[dst] + elif op == 3: + base.require(values[N] == values[dst], 'Control snapshot failed before endpoint') + values[N] = 0 + differences = [dict(row=i,value=values[i],expected=int(i == input_column)) + for i in range(2*V,N) if values[i] != int(i == input_column)] + base.require(differences, 'Bad cleanup sign control escaped') + return dict(input_column=input_column,bad_phase=bad_phase,first_difference=differences[0]) + + +def main(): + old_meta = json.loads((HERE/'BIT-THREE-ROW.json').read_text()) + old_blob = (HERE/'BIT-THREE-ROW-WORD.json.gz').read_bytes() + base.require(hashlib.sha256(old_blob).hexdigest() == old_meta['output_gzip_sha256'], + 'Raw three-row source changed') + word = json.loads(gzip.decompress(old_blob)) + records = [r[:] for r in word['records']] + copy_number = -1 + changes = Counter() + for r in records: + op,dst,src,c,frame,phase = r + if op == 2: + copy_number += 1 + if op != 1: + continue + if phase in (5,24,17) or (phase == 15 and copy_number%2 == 0): + r[3] = -1 + changes[str(phase)] += 1 + base.require(copy_number+1 == 6, 'Wrong snapshot episode count') + forward,fwd = scalar.execute(records,scalar.eye(N)) + inverse,rev = scalar.execute(records,scalar.eye(N),reverse=True) + roundtrip,rt = scalar.execute(records,forward,reverse=True) + base.require(roundtrip == scalar.eye(N), 'Signed integer roundtrip failed') + A,Ainv = source_integer_code(records) + for p in range(V): + base.require(forward[p] == A[p]+[0]*(N-V), + 'Forward integer source code depends on a target/helper') + base.require(inverse[p] == Ainv[p]+[0]*(N-V), + 'Inverse integer source code depends on a target/helper') + for h in range(2*V,N): + base.require(forward[h] == [int(j == h) for j in range(N)], + f'Actual forward integer helper{h} not restored') + base.require(inverse[h] == [int(j == h) for j in range(N)], + f'Actual inverse integer helper{h} not restored') + for p in range(V): + base.require(forward[V+p][V:2*V] == [int(j == p) for j in range(V)], + 'Integer target self-block changed') + base.require(all(x%2 == 0 for x in forward[V+p][2*V:]), + 'Integer target has odd dirty-helper leakage') + expected_forward = [1 << j for j in range(N)] + [0] + expected_inverse = expected_forward[:] + for p in range(V): + expected_forward[p] = old_meta['matrices']['H'][p] + expected_forward[V+p] ^= old_meta['matrices']['H'][p] + expected_inverse[p] = old_meta['matrices']['Hinv'][p] + expected_inverse[V+p] ^= 1 << p + base.require(scalar.parity(forward) == expected_forward, 'Signed forward parity differs') + base.require(scalar.parity(inverse) == expected_inverse, 'Signed inverse parity differs') + # The ordinary all-input frame audit treats +/-1 equally overF2, but now + # consumes this actual signed record list, with the original source bytes. + raw_word,builder,baseline,_ = base.load() + native_scalar_forward = base.replay(raw_word,builder,records,old_meta['matrices']) + native_scalar_reverse = base.replay(raw_word,builder,records,old_meta['matrices'],reverse=True) + controls = [column_control(records,0,5),column_control(records,0,17)] + word['format'] = 'coded-r438-three-row-signed-local-records-v1' + word['records'] = records + word['signed_from'] = old_meta['output_gzip_sha256'] + raw = base.canonical(word) + outword = HERE/'BIT-SIGNED-WORD.json.gz' + outword.write_bytes(gzip.compress(raw,mtime=0)) + F,R = fwd['maximum_exact_prefix_row_l1'],rev['maximum_exact_prefix_row_l1'] + output = dict(status='PASS_SIGNED_LIFT_ACTUAL_FORWARD_DIRTY_RESTORATION_NO_GLOBAL_TRANSFER', + raw_word_gzip_sha256=old_meta['output_gzip_sha256'], + output_word=str(outword),output_gzip_sha256=hashlib.sha256(outword.read_bytes()).hexdigest(), + output_canonical_sha256=hashlib.sha256(raw).hexdigest(), + matrices_sha256=hashlib.sha256(base.canonical(old_meta['matrices'])).hexdigest(), + signed_changes=dict(sorted(changes.items())), + forward=fwd,reverse_signed=rev,roundtrip_signed=rt, + source_code=scalar.small_bounds(records), + source_integer_matrix_sha256=scalar.digest(A), + source_integer_inverse_sha256=scalar.digest(Ainv), + public_integer_input_columns=N, + actual_forward_integer_equalities=dict(source='A_Z x, independent of all targets/helpers', + dirty_helpers='all438 exactly h',private='exactly zero', + target='y+T_Z x+E_Z h, with T_Z mod2=A and E_Z even'), + actual_inverse_integer_equalities=dict(source='A_Z^-1 x',dirty_helpers='all438 exactly h',private='exactly zero'), + signed_prefix_F=F,signed_prefix_R=R, + old_formula_screen_with_exact_signed_norms=dict(local_bits=(64*F**3*R**2).bit_length(), + nine_bits=((1<<18)*F**5*R**4).bit_length(), + applicability='Requires new proof that exact signed coefficient norms meet the native rounded-network contract'), + cancellation_free=base.positive_bounds(records,N), + local_frame_invoice=native_scalar_forward, + local_reverse_frame_invoice=native_scalar_reverse, + ADDs=sum(r[0] == 1 for r in records), + negative_controls=controls, + scope='Exact full660-column integer forward, inverse, parity and helper restoration. The target/source coded BIT identity is modulo2, not equality overZ.', + unresolved=['Native/global63-code-bridge invoice and its signed source code', + 'Complete rounded-network perturbation weights and precision/payload reserve', + 'Terminal N E^-1 N, chronological owner and all-size physical supplier']) + (HERE/'BIT-SIGNED-LIFT.json').write_text(json.dumps(output,indent=2,sort_keys=True)+'\n') + print(json.dumps({k:output[k] for k in ('status','signed_changes','signed_prefix_F','signed_prefix_R', + 'old_formula_screen_with_exact_signed_norms','source_code','ADDs')}, + indent=2,sort_keys=True)) + + +if __name__ == '__main__': + main() diff --git a/research/bit-r438-source-code/producer/bit_transvection.py b/research/bit-r438-source-code/producer/bit_transvection.py new file mode 100644 index 0000000000..1c951d55fe --- /dev/null +++ b/research/bit-r438-source-code/producer/bit_transvection.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python3 +"""Exact R438 local replacement with a coded source and literal dirty repairs. + +This is a changed local interface, not an admitted nine-stage supplier. All +660 public scalar input columns are independent over F2. The native operator +and integer-lift/controller obligations are independently owned by the sibling +recursive specialist. No source checkout is modified. +""" +from collections import Counter +import gzip +import hashlib +import importlib.util +import json +from pathlib import Path +import sys + +sys.dont_write_bytecode = True +HERE = Path(__file__).resolve().parent +REPO = HERE.parents[2] # rebound explicitly by reconstruct.py +WORD = REPO / 'research/bit-r438-transport-rehost/words/r438-t154.json.gz' +BUILDER = REPO / 'research/bit-boundary-persistence/build.py' +MAIN_PIN = '20ecf2891d80b5acf18d980b2164fb44ea7faa90' +WORD_SHA = 'a353999bceac4ac957f540adfd3e5f8768297138b27132eeb83332e2ea4b1022' +BUILDER_SHA = '58f402c365eb18b9c3dd736523999676f1d1652e40c1a9b4f6967c1b7acb72df' + + +def require(value, message): + if not value: + raise ValueError(message) + + +def bits(mask): + while mask: + low = mask & -mask + yield low.bit_length() - 1 + mask ^= low + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(',', ':')).encode() + + +def rank(rows): + pivots = {} + for row in rows: + while row: + pivot = row.bit_length() - 1 + if pivot in pivots: + row ^= pivots[pivot] + else: + pivots[pivot] = row + break + return len(pivots) + + +def product(left, right): + """Rows of left times rows of right, both bit-packed over F2.""" + return [sum_xor(right[j] for j in bits(row)) for row in left] + + +def sum_xor(values): + result = 0 + for value in values: + result ^= value + return result + + +def inverse(rows): + n = len(rows) + aug = [row | (1 << (n + j)) for j, row in enumerate(rows)] + for j in range(n): + pivot = next((i for i in range(j, n) if aug[i] >> j & 1), None) + require(pivot is not None, 'Singular section') + aug[j], aug[pivot] = aug[pivot], aug[j] + for i in range(n): + if i != j and aug[i] >> j & 1: + aug[i] ^= aug[j] + require([row & ((1 << n) - 1) for row in aug] == [1 << j for j in range(n)], + 'Inverse left block failed') + return [row >> n for row in aug] + + +def load(): + require(hashlib.sha256(WORD.read_bytes()).hexdigest() == WORD_SHA, + 'R438 source gzip pin changed') + require(hashlib.sha256(BUILDER.read_bytes()).hexdigest() == BUILDER_SHA, + 'Baseline replay source pin changed') + word = json.loads(gzip.decompress(WORD.read_bytes())) + require((word['v'], word['R'], word['h']) == (111, 438, 8), 'Wrong dimensions') + spec = importlib.util.spec_from_file_location('pinned_boundary_builder', BUILDER) + builder = importlib.util.module_from_spec(spec) + spec.loader.exec_module(builder) + baseline, records = builder.replay(word) + return word, builder, baseline, records + + +def matrices(word): + v, count = word['v'], 2 * word['v'] + word['R'] + rows = [1 << j for j in range(count)] + for phase in ('D', 'A'): + for _, dst, sources in word[phase]: + for src in sources: + rows[dst] ^= rows[src] + ret_rows = [rows[j] for j in word['ret']] + source_mask = (1 << v) - 1 + helper_mask = ((1 << count) - 1) ^ ((1 << (2 * v)) - 1) + require(all(row & ~ (source_mask | helper_mask) == 0 for row in ret_rows), + 'A retained total reads an arbitrary target') + R = [row & source_mask for row in ret_rows] + T = [row & helper_mask for row in ret_rows] + K = [sum(1 << j for j in subset) for subset in word['scatter']] + M = product(R, K) + require(M == [507, 135, 238, 349, 185, 437, 205, 503, 425], 'RK changed') + require(rank(M) == 9 and rank(R) == 9, 'Wrong query rank') + selected, columns = [], [] + for p in range(v): + column = sum(((row >> p) & 1) << j for j, row in enumerate(R)) + if rank(columns + [column]) > len(columns): + selected.append(p) + columns.append(column) + if len(selected) == 9: + break + S = [sum(((row >> p) & 1) << j for j, p in enumerate(selected)) for row in R] + Sinv = inverse(S) + L = product(Sinv, M) + U = [0] * v + for j, p in enumerate(selected): + U[p] = L[j] + W = [k ^ u for k, u in zip(K, U)] + Q = product(U, R) + H = [(1 << p) ^ row for p, row in enumerate(product(W, R))] + J = [(1 << p) ^ row for p, row in enumerate(product(K, R))] + require(product(R, W) == [0] * 9, 'RW is not zero') + require(product(H, H) == [1 << p for p in range(v)], 'H is not involutive') + require(product(R, H) == R, 'RH differs from R') + require(product(J, H) == [(1 << p) ^ Q[p] for p in range(v)], 'JH residual failed') + require(product(Q, H) == Q, 'Repair query changes under H') + require([p for p, row in enumerate(Q) if row] == selected, 'Repair support changed') + return dict(R=R, T=T, K=K, M=M, selected=selected, S=S, Sinv=Sinv, + L=L, U=U, W=W, H=H, Q=Q, J=J) + + +def construct(word, baseline_records, data): + v, count = word['v'], 2 * word['v'] + word['R'] + require(all(f == 0 for f in word['start'][v:]), 'Initial target/helper frames differ') + require(all(f == 1 for f in word['final'][:v] + word['final'][2*v:]), + 'A source/helper is not FULL at the new H cut') + require(not any(v <= s < 2*v for phase in ('D', 'A', 'B', 'C') + for _, _, ss in word[phase] for s in ss), 'Target read in original word') + old_comp = [0] * v + for frame, dst, sources in word['D']: + require(frame == 0 and v <= dst < 2*v, 'Original D is not a zero-frame target shear') + for src in sources: + require(src >= 2*v, 'Original D reads data instead of a dirty helper') + old_comp[dst-v] ^= 1 << src + # The original D and extra KT compensation commute at frame zero. + # Cancel their duplicate parity gates before emitting the changed D. + comp = [old ^ extra for old, extra in zip(old_comp, product(data['K'], data['T']))] + prefix = [[1, v+p, src, 1, 0, 10] + for p, row in enumerate(comp) for src in bits(row)] + # Keep every original public-register frame visit, including empty-source + # visits. Only the nine owned copied totals and their scatter are removed. + clean = [rec[:] for rec in baseline_records + if rec[0] not in (2, 3) and not (rec[0] == 1 and (rec[2] == count or rec[5] == 1))] + borrow = list(range(2*v, 2*v+9)) + # Four simultaneous banks of CNOTs implement x -> (I+WR)x while every + # arbitrary dirty z_j is restored. RW=0 is checked above. + phase1 = [[1, p, borrow[j], 1, 1, 11] + for p, row in enumerate(data['W']) for j in bits(row)] + phase2 = [[1, borrow[j], p, 1, 1, 12] + for j, row in enumerate(data['R']) for p in bits(row)] + phase3 = [[1, p, borrow[j], 1, 1, 13] + for p, row in enumerate(data['W']) for j in bits(row)] + phase4 = [[1, borrow[j], p, 1, 1, 14] + for j, row in enumerate(data['R']) for p in bits(row)] + repairs = [] + b = borrow[0] + for p in data['selected']: + cap = word['final'][v+p] + # Each episode reads one physical unchanged dirty register b. The + # private field is zero before COPY and exactly equals b at ERASE. + # No zero-initialized query register or second simultaneous copy is used. + episode = [[2, b, count, 1, cap, 1], + [1, v+p, count, 1, cap, 15], + [3, b, count, 1, cap, 0]] + gather = [[1, b, src, 1, 1, 16] for src in bits(data['Q'][p])] + repairs.extend(episode) + repairs.extend(gather) + repairs.extend(episode) + repairs.extend([rec[:4] + [1, 17] for rec in gather]) + records = prefix + clean + phase1 + phase2 + phase3 + phase4 + repairs + parts = dict(prefix=prefix, clean=clean, H1=phase1, H2=phase2, H3=phase3, + H4=phase4, repairs=repairs) + return records, parts + + +def replay(word, builder, records, data, reverse=False, mutate_snapshot=False): + v, count = word['v'], 2 * word['v'] + word['R'] + values = [1 << j for j in range(count)] + [0] + current = (word['final'] if reverse else word['start'])[:] + masks = [sum(1 << j for j in frame) for frame in word['frames']] + dims = [builder.rank(word['lines'][j] for j in frame) for frame in word['frames']] + profile, live, snapshots, paths = Counter(), None, 0, [[f] for f in current] + old_private, changed = None, False + for number, rec in enumerate(reversed(records) if reverse else records): + op, dst, src, coefficient, frame, phase = rec + if op == 0: + old, new, paid = src, coefficient, frame + if reverse: + old, new = new, old + require(current[dst] == old, f'Wrong climb start at {number}') + require((masks[new] & ~masks[old] == 0) if reverse else + (masks[old] & ~masks[new] == 0), f'Non-nested move {number}') + require(abs(dims[new]-dims[old]) == paid, f'Wrong climb rank {number}') + current[dst] = new + paths[dst].append(new) + profile[paid] += 1 + elif op == 1: + require(current[dst] == frame, f'Wrong ADD destination frame {number}') + require((old_private if src == count else current[src]) == frame, + f'Wrong ADD source frame {number}') + require(src != count or live is not None, 'Read from erased private field') + values[dst] ^= values[src] + if mutate_snapshot and live is not None and not changed: + values[live] ^= 1 + changed = True + elif op == (3 if reverse else 2): + require(live is None and values[count] == 0, 'COPY overwrites live dirt') + require(current[dst] == coefficient, 'COPY source frame differs') + require(masks[frame] & ~masks[coefficient] == 0, 'COPY goes upward') + paid = dims[coefficient]-dims[frame] + require(paid > 0, 'Nonpositive COPY rank') + profile[paid] += 1 + values[count] = values[dst] + old_private, live = frame, dst + snapshots += 1 + elif op == (2 if reverse else 3): + require(live == dst and old_private == frame, 'ERASE mismatched source/frame') + require(current[dst] == coefficient, 'ERASE source frame differs') + require(values[count] == values[dst], f'ERASE snapshot changed at {number}') + values[count], old_private, live = 0, None, None + else: + raise ValueError(f'Unknown operation {op}') + require(live is None and values[count] == 0, 'Private field not clear') + require(current == (word['start'] if reverse else word['final']), 'Final frames differ') + expected = [1 << j for j in range(count)] + [0] + for p in range(v): + expected[p] = data.get('Hinv', data['H'])[p] if reverse else data['H'][p] + expected[v+p] ^= (1 << p) if reverse else data['H'][p] + require(values == expected, f'Wrong {"reverse" if reverse else "forward"} dirty map') + return dict(public_columns=count, nonzero_output_rows=sum(bool(x) for x in values), + endpoint_sha256=hashlib.sha256(canonical(values)).hexdigest(), + profile=dict(sorted(profile.items())), + rank_mass=sum(k*n for k,n in profile.items()), copies=snapshots, + max_live_copies=1, dirty_helpers_restored=word['R'], + paths_sha256=hashlib.sha256(canonical(paths)).hexdigest()) + + +def positive_bounds(records, count): + bounds = [] + for reverse in (False, True): + values, maximum = [1] * count + [0], 1 + for op, dst, src, coefficient, frame, phase in reversed(records) if reverse else records: + if op == 1: + values[dst] += values[src] + maximum = max(maximum, values[dst]) + elif op == (3 if reverse else 2): + values[count] = values[dst] + maximum = max(maximum, values[count]) + elif op == (2 if reverse else 3): + values[count] = 0 + bounds.append(maximum) + F, R = bounds + local, nine = 64*F**3*R**2, (1 << 18)*F**5*R**4 + return dict(forward=F, reverse=R, local_bits=local.bit_length(), nine_bits=nine.bit_length(), + historical_local_guard_pass=local < 1 << 104, + historical_nine_guard_pass=nine < 1 << 192, + applicability='Numerical screen only; changed source-code interface not admitted') + + +def must_fail(name, thunk): + try: + thunk() + except (ValueError, AssertionError) as error: + return dict(name=name, detected=True, message=str(error)) + raise ValueError(f'Negative control escaped: {name}') + + +def main(): + word, builder, baseline, old_records = load() + data = matrices(word) + records, parts = construct(word, old_records, data) + forward = replay(word, builder, records, data) + reverse = replay(word, builder, records, data, reverse=True) + expect = Counter({int(k): n for k,n in baseline['profile'].items()}) + expect[7] -= 9 + expect[1] += 18 + require(forward['profile'] == dict(sorted(expect.items())), 'Unexpected profile delta') + require(reverse['profile'] == forward['profile'], 'Reverse profile differs') + require(forward['rank_mass'] == 5076 and forward['copies'] == 18, 'Wrong local bill') + controls = [ + must_fail('omit_changed_dirty_compensation', lambda: replay( + word, builder, records[len(parts['prefix']):], data)), + must_fail('omit_first_bulk_H_phase', lambda: replay( + word, builder, [r for r in records if not (r[0] == 1 and r[5] == 11)], data)), + must_fail('omit_repair_dirty_restore', lambda: replay( + word, builder, [r for r in records if not (r[0] == 1 and r[5] == 17)], data)), + must_fail('mutate_live_snapshot_source', lambda: replay( + word, builder, records, data, mutate_snapshot=True)), + ] + container = dict(format='coded-r438-local-records-v1', register_order='X0..110,Y0..110,H0..437,C', + public_registers=660, private_register=660, word_path=str(WORD), + word_gzip_sha256=WORD_SHA, start=word['start'], final=word['final'], + record_schema='[op,dst,src,coefficient/sourceframe,frame/privateframe,phase/rank]', + copy_schema='[2,physical_source,660,sourceframe,privateframe,rank]', + erase_schema='[3,physical_source,660,sourceframe,privateframe,0]', + records=records) + raw = canonical(container) + outword = HERE / 'BIT-TRANSVECTION-WORD.json.gz' + outword.write_bytes(gzip.compress(raw, mtime=0)) + output = dict(status='PASS_CHANGED_LOCAL_GF2_INTERFACE_NO_GLOBAL_SUPPLIER_NO_NEW_KAPPA', + source_pin=MAIN_PIN, source_word=str(WORD), source_gzip_sha256=WORD_SHA, + source_builder=str(BUILDER), builder_sha256=hashlib.sha256(BUILDER.read_bytes()).hexdigest(), + output_word=str(outword), output_canonical_sha256=hashlib.sha256(raw).hexdigest(), + output_gzip_sha256=hashlib.sha256(outword.read_bytes()).hexdigest(), + matrices=data, source_query_supports=[r.bit_count() for r in data['R']], + helper_query_supports=[r.bit_count() for r in data['T']], + baseline={k:v for k,v in baseline.items() if k != 'paths'}, + forward=forward, reverse=reverse, + adds=sum(r[0] == 1 for r in records), records=len(records), + part_adds={k:sum(r[0] == 1 for r in rows) for k,rows in parts.items()}, + positive=positive_bounds(records, 660), negative_controls=controls, + contract=dict(forward='(x,y,h)->(Hx,y+Hx,h)', + literal_inverse='(x,y,h)->(Hx,y+x,h)', + initial_frames='source Pp; target0; every helper0', + final_frames='source FULL; target Pp-perp; every helper FULL', + private='One live immutable copied snapshot; zero between episodes', + changed_original_hypotheses=['H4: appended source H and helpers restored by a new word', + 'End source is coded Hx, not x']), + unresolved=['Independent exact native operator lift including complementary backward cuts', + 'Ordered signed integer lift and applicable precision theorem', + 'Whole9-stage controller code removal at actual cap queries', + 'Chronological owner/stock and complete outer recurrence admission']) + (HERE / 'BIT-TRANSVECTION.json').write_text(json.dumps(output, indent=2, sort_keys=True)+'\n') + print(json.dumps({k:output[k] for k in ('status','forward','adds','records','part_adds','positive')}, + indent=2, sort_keys=True)) + + +if __name__ == '__main__': + main() diff --git a/research/bit-r438-source-code/producer/build_support_code.py b/research/bit-r438-source-code/producer/build_support_code.py new file mode 100644 index 0000000000..c4c5605e6b --- /dev/null +++ b/research/bit-r438-source-code/producer/build_support_code.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +"""R438 source code that only deletes support from each K column. + +Three actual source rows remain identity. Target repair is still three direct +source-pivot snapshots. A matched native global decoder is NOT supplied. +Apache-2.0; substantial OpenAI Codex assistance. +""" +from collections import Counter +import gzip +import hashlib +import json +from pathlib import Path +import sys + +HERE = Path(__file__).resolve().parent +SOURCE = HERE # rebound to fresh signed ancestry by reconstruct.py +sys.dont_write_bytecode = True +import bit_transvection as base +import bit_section_code as section +import bit_scalar_invoice as scalar +import bit_signed_lift as signed + + +def authenticate_predecessor(packed): + raise ValueError('Use reconstruct.py to authenticate the regenerated predecessor payload') + + +def main(): + old_blob = (SOURCE/'BIT-SIGNED-WORD.json.gz').read_bytes() + authenticate_predecessor(old_blob) + old_word = json.loads(gzip.decompress(old_blob)) + original,builder,baseline,_ = base.load() + raw = base.matrices(original) + data = section.section(raw) + selected = data['selected'] + pk = [raw['K'][p] for p in selected] + y = [a^b for a,b in zip(data['N'],base.product(data['S'],pk))] + base.require(base.rank(y) == 9,'Support-preserving quotient is singular') + wprime = [0 if p in selected else row for p,row in enumerate(raw['K'])] + a = [(1<