diff --git a/research/raw-pencil-sl-transport/EVIDENCE.md b/research/raw-pencil-sl-transport/EVIDENCE.md new file mode 100644 index 0000000000..a1fbc7ad72 --- /dev/null +++ b/research/raw-pencil-sl-transport/EVIDENCE.md @@ -0,0 +1,95 @@ +# Validation and limits + +The base is canonical main df0137efd35e11b4445734bf612bdd4c7ebc330c. +Priority revision 7 and selected conditional kappa 0.00310045 remain unchanged. +The eleven source inputs are exact retained bytes from the two consumed +packages. SOURCES.json gives every blob, SHA256 and retention commit. + +## Complete finite domains + +The normal Python 3.14.7 checks cover every one of 81,244 raw pencils in +eleven domains. Independent elementary-transvection traversals give exactly +76 SL orbits in total across those separate domains. Every raw input has +its label compared with that partition and every returned map has all three +determinants and both coefficient matrices checked separately. + +| Field | Matrix shapes | Raw pencils | SL orbits | +| --- | --- | ---: | ---: | +| F2 | 2x2, 2x3, 3x2 | 8,448 | 28 | +| F3 | 2x2, 1x1, 1x2, 2x1 | 6,732 | 24 | +| F4 | 2x2, 1x1, 1x2, 2x1 | 66,064 | 24 | + +The 65,536 F4 two-by-two pencils alone give twelve SL orbits. The normal +extension phase took about 439 seconds in this session with at most four +process workers. This is verification runtime, not an algorithm benchmark. + +The larger checks have 24 fixtures over F2,F3,F4,F9, with 23 arbitrary-basis +raw-to-raw transports. They include degree-four primaries, length four, +index six, multiplicity four, a seventeen-row zero pencil, and three regular +full-projective-line families. Eleven square fixture pencils have no +invertible rational slice; three of these are regular. There are 29 malformed, +inequivalent-input and singular-map controls. The public transporter also +passes an identity and a nontrivial raw-to-raw endpoint. + +The norm phase checks 112 nonzero targets over all declared field/degree +pairs, with degrees one through eight. It uses 648 sampled residues. Separate +multiplication determinants check all returned norms and 336 lifts at lengths +one, two and four. Three invalid norm problems reject. The supplied-character +comparison covers all 180 determinant triples in fifteen declared model GL +orbits and agrees exactly on the SL partition. + +An initial proposed negative control from diag(s,t) over F3 was equivalent, +not a counterexample. It was replaced by the 1x2 pencils with stacked +coefficient determinants one and two. That independent determinant invariant +proves their inequivalence under SL1 x SL2 x SL2. No classification formula +was changed to fit that mistaken fixture expectation. + +## Final registered replay + +All five final commands pass on Python 3.12.14, followed by +PASS_REGISTERED_RESEARCH_PACKAGE. Their declared caps are 180,600,300,60,60 +seconds, for a total of 1,200 seconds. The final verifier adds the nontrivial +public-transporter control and streams irreducible-fixture candidates without +materializing all candidates. The executable classifier is unchanged from the +normal run. RESULT.json records both normal and registered receipts. + +## Sealed exported replay and publication checks + +All five phases pass from the official committed export of scientific commit +3afe93780f111c6368badd47394ce761d4421317. The export has no Git directory. +Python 3.12.14 runs with -I -O -B and an empty executable PATH. All 21 files, +including the export manifest, keep their bytes and permissions after the +read-only run. An actual changed source input fails authentication before +replay. The source is restored before the full run. RESULT.json records this +receipt. The official committed-byte and export integrity checks pass for +all twenty package files. + +The final overlap search covers all 7,676 main notes, 392 open PRs and 5,043 +Discussion records, with separate literal terms and a cached-body scan. Its +last remote refresh is 2026-10-26T08:23:49Z. It finds no competing raw-SL or +residue-norm claim within that coverage. Closed unretained work and unpublished +work are outside this search. Both consumed predecessors are released. +Canonical main was fetched again at 2026-10-26T08:35Z and has the same commit. +The final commit adds receipts and coordination metadata only; executable +sources and the proof are unchanged from the sealed replay. + +## Hosted CI and omitted obligations + +The nine earlier contributions in this session have completed hosted plan +jobs that fail the same two CurrentCiNavigationTests subcases: review and +source_manifest. Their package replay jobs are skipped. The inspected logs +include [the exact PR5707 job](https://github.com/CrocSwap/integer-mult-bounds/actions/runs/40287155528/job/121453417199). +The shared main documentation defect already has +[PR #5659](https://github.com/CrocSwap/integer-mult-bounds/pull/5659) and +[PR #5703](https://github.com/CrocSwap/integer-mult-bounds/pull/5703). +This package does not duplicate or merge those repairs. Its own hosted status +must be read separately; no hosted success is inferred from local success. + +No complete physical caller, native preparation/routing/storage/precision +invoice, selected-frontier replay, independent human review or proof-kernel +acceptance ran. The shallow checkout cannot establish the full-history +publication preflight; exact source bytes and immediate retained-source +ancestry are checked. The norm witness is exact Las Vegas sampling, with +expected polynomial cost for fixed field and no deterministic worst-case +runtime claim. Finite tests do not by themselves establish the written +unbounded theorem. No new kappa or physical speedup is claimed. diff --git a/research/raw-pencil-sl-transport/PROOF.md b/research/raw-pencil-sl-transport/PROOF.md new file mode 100644 index 0000000000..5a6c711a8f --- /dev/null +++ b/research/raw-pencil-sl-transport/PROOF.md @@ -0,0 +1,209 @@ +# Raw finite-field pencil special-linear recognition + +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. + +## Claim and source boundary + +Fix a supplied finite field K=F_q with one common element encoding. Let +m,n>0. A tensor is any ordered pair X=(A,B) of m-by-n matrices. The action is + +```text +(P,Q,S).X = (P(s11 A+s12 B)Q^T, P(s21 A+s22 B)Q^T). +``` + +This package gives a deterministic complete label for the orbits of +SL_m(K) x SL_n(K) x SL_2(K), a fixed representative for each label, and +literal determinant-one maps to that representative. It also gives a map +between two equivalent raw inputs. The decision has polynomial cost in the +factor dimensions for fixed q. Map construction has expected polynomial +cost, with exact checked residue norms. No dimension, index, primary degree, +length or multiplicity cap is imposed by the implementation. + +The field is common to both inputs. Field automorphisms, changes between +unrelated field encodings and tensors with more than two slices are outside +the claim. Zero pencils, linearly dependent slices, rectangular shapes, +zero minimal indices and pencils with no invertible rational slice are in +scope. The complete kappa calculation does not change. + +PR5692 supplies raw strict Kronecker decomposition and its actual maps. +PR5689 supplies the complete fixed-slice determinant subgroup, including +all off-diagonal mixing. Those are credited prerequisites, not new theorems +here. This package supplies their raw SL interface, basis/order determinant +handling, an executable unbounded-degree norm witness, and independent +finite SL-orbit checks. The bounded character code is only a comparison +oracle. It is neither patched nor used as an unbounded implementation. + +## Strict canonical coordinates and every determinant + +The retained extractor returns blocks, R and Q with + +```text +A Q = R A0, B Q = R B0. +``` + +Order its individual blocks by their exact type records. Apply the actual +row and column block permutations E and F. Then + +```text +g=(E R^-1, F Q^T, I2) +``` + +maps the raw pencil to the sorted block model C. Thus det(g_row)=det(E)/det(R) +and det(g_col)=det(F)det(Q). The program keeps these matrices and checks both +coefficient equations. It does not discard signs or identify equal block +orders without their actual maps. + +The raw extractor writes finite regular blocks as `(Comp(f^ell),I)` and +infinity as `(I,Comp(X^ell))`. The supplied-character source uses the opposite +slice convention. Exchanging both coefficient equations does not change +the fixed-slice stabilizer. The subgroup below therefore applies directly. +Every slice action in the new algorithm is applied to the actual matrices; +no implicit slice swap or uncharged determinant correction occurs. + +## Complete fixed-slice character subgroup + +For a sorted model C, let H(C) be the image in (K*)^2 of its row/column +stabilizer with the slices fixed. The source theorem gives the subgroup +generated by the following pairs, for every u in K*: + +```text +right index e: (u^e, u^(-e-1)), +left index e: (u^(-e-1), u^e), +regular length ell: (u^ell, u^-ell). +``` + +This includes index zero. The regular residue degree and repeated-copy +count do not replace ell. Repeated identical generators may be omitted. +The source proof uses the full Hom algebra, not a block-diagonal assumption. +Distinct singular types and singular/regular Hom maps are triangular in +an appropriate order. For a regular primary, the residue multiplicity map +of exact length ell appears on ell filtration layers. Its determinant is +Norm(det D)^ell. Off-diagonal/radical maps add no determinant factor. +This proves the upper bound. Varying one block or one multiplicity coordinate +attains each displayed generator, so the bound is exact. + +The program closes these generators in the finite group (K*)^2 by breadth +first search. It stores a generator path for each element. There are at +most (q-1)^2 elements. This is an exact finite group calculation, not a scan +of the large matrix stabilizer. + +## Complete raw SL label + +Enumerate every S in SL_2(K). For each, apply S to X, compute its sorted +strict model C_S and a strict map g_S. The full map from X is +`(g_S_row,g_S_col,S)`. Let d_S be its pair of row and column determinants. +Let l_S be the least pair in the coset d_S H(C_S), using the fixed integer +encoding of K elements. The label is the least pair + +```text +(sorted block records of C_S, l_S) +``` + +over all S, together with m,n. The associated representative is C_S with +its first row multiplied by l_S[0]^-1 and its first column multiplied by +l_S[1]^-1. Positive m,n make these diagonal maps well defined. This label +is relative to the declared common field encoding. + +First, it is independent of the extractor's coordinate choices. Two strict +maps to the same model differ by a fixed-slice stabilizer. Their determinant +pairs differ by H(C_S), so their cosets and labels agree. + +Next, suppose Y=(U,V,T).X with det U=det V=det T=1. For every slice action +S on Y, the corresponding action on X is ST. The row/column maps U,V have +determinant one. Hence the sets of strict types and determinant cosets are +the same as S ranges over SL_2. Their least labels are equal. This proves +invariance under the entire product group, including slice actions. + +Conversely, choose the winning S and d=d_S. Since l is in dH, put +h=l/d componentwise. The stored path supplies a literal fixed-slice +stabilizer (H_row,H_col) with determinants h. Let D_row,D_col have first +diagonal entries l[0]^-1,l[1]^-1 and all other entries one. Then + +```text +(D_row H_row g_row, D_col H_col g_col, S) +``` + +maps X to the stated representative. Its two determinant products are +l^-1 h d=1, and det S=1. Thus equal labels give SL maps to one identical +representative and imply equivalence. The label is complete. + +If w_X and w_Y map X and Y to that representative, the transporter from +X to Y is `w_Y^-1 w_X`, component by component. The program checks all three +determinants and both literal coefficient matrices. Different labels return +no transporter. This is a decision for all raw pencils in the stated class, +not a promised-model recognition test. + +## Exact norm witnesses without a degree cap + +For a finite primary f of degree d, choose a uniform residue polynomial a +with d coefficients in K. For nonzero a, compute + +```text +N(a)=a^((q^d-1)/(q-1)) mod f. +``` + +This is an element of K. Accept exactly when it is the requested nonzero u. +The norm map on the cyclic multiplicative group of F_(q^d) is onto K*. +Each nonzero target has (q^d-1)/(q-1) preimages among all q^d sampled residues. +The success probability is at least 1/q. Independent uniform trials therefore +terminate almost surely with expected trial count at most q. The result is +checked exactly; randomness affects runtime and the selected witness, not +correctness, the orbit label or the representative. + +On a length-ell block, use P=a(Comp(f^ell)) and Q=P^-T. The residue unit +lifts to a unit, commutes with the companion matrix and has determinant +N(a)^ell=u^ell. Infinity uses a constant unit u. Right and left blocks use +the literal scalar maps from the displayed character formulas, with empty +local factors allowed at index zero. Insert each generator in the full +block coordinates, multiply along the stored path, and check the full +fixed-slice identity. There is no enumeration of q^d residues in this code. + +The default uses SystemRandom. Reproducible verification uses specified +Random seeds. The expected-time theorem assumes independent uniform draws; +it is not a deterministic worst-case bound for a supplied random stream. + +## Positive preparation and caller limits + +There are q(q^2-1) special-linear slice actions. The code tests fewer than +q^4 candidate two-by-two matrices and invokes the retained polynomial raw +extractor on their transformed coefficients. It keeps a per-input cache of +identical transformed pencils only. Sorting, all row/column maps, determinant +calculations, character closure and all coefficient checks are paid work. +For fixed q their counts and workspace are polynomial in m+n. No discrete +logarithm or unpriced large stabilizer oracle is used. + +A norm trial uses polynomial arithmetic modulo f and an exponent with +O(d log q) bits. Verification of irreducibility uses the retained exact +factorization routine. Lifting to length ell and multiplying the full maps +has polynomial matrix cost. Each character path has fewer than (q-1)^2 +steps. The witness therefore has expected polynomial preparation cost for +fixed q. The implementation builds explicit finite-field operation tables; +no complexity polynomial in log q is claimed. The polynomial exponent and +large-field constants are not optimized. + +This preparation is an algebraic tool for the tensor-atlas interface. A +multiplication mechanism still needs native realizations, a producer and +consumer, physical moves, dirty restoration, storage, precision, repeated +preparation and a complete paid recursive bill. These costs remain unknown, +not zero. No physical caller, supplier admission, kappa improvement or +practical multiplication speedup follows from this package. + +## Evidence and attribution + +The verifier constructs independent complete small SL-orbit partitions +using elementary transvections on all three tensor factors. It compares +labels on every raw input and checks every returned map by a separate +coefficient sum and small determinant formula. Larger fixtures include +extension fields, degree-four primaries, length four, index six, multiplicity +four, dimension seventeen, zero pencils and full projective-line pencils +with no invertible rational slice. Exact norm tests extend through degree +eight and length-four lifts. The frozen supplied-model program supplies a +separate comparison for its own bounded character domain. + +These are exact finite tests plus a written all-input argument. Independent +human review, proof-kernel acceptance and a production physical bill remain +open. Credit PR5692, PR5689, Nick Petalas PR5250, apoursh PR5672, Ali Romman +PR5683, David Ganz A030/A026/A029, and the classical Kronecker, module, +centralizer and finite-field norm results retained in those sources. Original +notices remain byte-exact under vendor/. No global literature priority is +claimed. No subagents were used. diff --git a/research/raw-pencil-sl-transport/README.md b/research/raw-pencil-sl-transport/README.md new file mode 100644 index 0000000000..11a3a86251 --- /dev/null +++ b/research/raw-pencil-sl-transport/README.md @@ -0,0 +1,76 @@ +# Raw pencil special-linear recognition and transport + +This closes the raw-input boundary for finite-field two-slice tensors. +Given any two m-by-n coefficient matrices over one common finite field, +with m,n>0, it returns a complete SL_m x SL_n x SL_2 orbit label, a fixed +representative and a literal determinant-one map to it. Two equivalent raw +inputs receive an explicit transporter. No supplied block model or invertible +rational slice is required. The complete kappa calculation is unchanged. + +The [proof](PROOF.md) gives the complete-orbit argument and positive costs. +[sl.py](sl.py) contains the implementation. [RESULT.json](RESULT.json) and +[EVIDENCE.md](EVIDENCE.md) state the exact checks and limits. +[SOURCES.json](SOURCES.json) pins all eleven retained source files. + +The deterministic decision enumerates SL2 slice actions, extracts the raw +strict model, and keeps its actual row/column determinants modulo the complete +fixed-slice character subgroup. Exact general-degree norm witnesses remove +the degree-three limit of the supplied-model executable. Map construction +has expected polynomial cost for fixed field under uniform sampling; this +is not a deterministic worst-case runtime guarantee. + +The implementation accepts all finite dimensions, minimal indices, primary +degrees, lengths and multiplicities. This includes zero pencils, zero-index +singular blocks, infinity, nonsplit factors and no-invertible-slice pencils. +The common field encoding is part of the interface. Field isomorphisms and +tensors with more than two slices are outside the claim. + +## Reproduce + +Use Python 3.12 and its standard library: + +```sh +python3.12 -B scripts/research_package.py --package research/raw-pencil-sl-transport +``` + +The five phases report `PASS_RAW_PENCIL_SL_SMALL`, +`PASS_RAW_PENCIL_SL_EXTENSION`, `PASS_RAW_PENCIL_SL_FIXTURES`, +`PASS_RAW_PENCIL_SL_NORMS`, and `PASS_RAW_PENCIL_SL_CHARACTERS`. +The runner then reports `PASS_REGISTERED_RESEARCH_PACKAGE`. +The declared caps sum to 1,200 seconds. The two exhaustive phases use at +most four process workers and write no package data. VERIFY.json also gives +the exact commands for a Git-free export. + +`analyze` gives the deterministic label and representative. `canonicalize` +also gives the three determinant-one maps. `transporter` gives maps from the +first input to the second, or None for different orbits. The action convention +and all input domains are stated in PROOF.md. + +## Credit and scope + +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. No subagents. +The consumed packages use the same assistant family; this is not independent +human review. The new finite-orbit oracle does not use their classification +or character formulas. + +[PR #5692](https://github.com/CrocSwap/integer-mult-bounds/pull/5692), head +e34ae992744db135b9d4e378bfe26fd31fb82ad7, supplies raw strict extraction. +[PR #5689](https://github.com/CrocSwap/integer-mult-bounds/pull/5689), head +29172b129a7bb4dbbb3b42ac128fa32ffec1f93b, supplies complete fixed-slice +characters and the norm construction argument. The latter's bounded code +is a separate comparison oracle. All sources and notices remain byte-exact. + +Credit also Nick Petalas's +[PR #5250](https://github.com/CrocSwap/integer-mult-bounds/pull/5250), +apoursh's [PR #5672](https://github.com/CrocSwap/integer-mult-bounds/pull/5672), +Ali Romman's [PR #5683](https://github.com/CrocSwap/integer-mult-bounds/pull/5683), +David Ganz's tensor atlas and the classical Kronecker/module/centralizer/norm +lineage retained in those sources. Global literature priority is unclaimed. + +## Open next questions + +- Name a concrete native producer and consumer that uses this admissibility + tool, then price all physical preparation, routes, dirty restoration, + storage, precision and recursive work. Those costs are unknown here. +- Give a deterministic general-degree residue norm solver with its actual + cost. The present exact witness has expected polynomial runtime. diff --git a/research/raw-pencil-sl-transport/RESULT.json b/research/raw-pencil-sl-transport/RESULT.json new file mode 100644 index 0000000000..42ec79ddde --- /dev/null +++ b/research/raw-pencil-sl-transport/RESULT.json @@ -0,0 +1,2263 @@ +{ + "normal_python": "3.14.7", + "phases": { + "small": { + "domains": [ + { + "norm_trials": 0, + "pencils": 256, + "q": 2, + "sha256": "7049ccb42f28e78a64f4161b70e8906d5da61ccc1f51eae1bb8e3162af894ef6", + "shape": [ + 2, + 2 + ], + "sl_orbits": 8 + }, + { + "norm_trials": 0, + "pencils": 4096, + "q": 2, + "sha256": "e8e266da2652067166f367f7fc59c4fd29a22a92437163a6454bb250641e4968", + "shape": [ + 2, + 3 + ], + "sl_orbits": 10 + }, + { + "norm_trials": 0, + "pencils": 4096, + "q": 2, + "sha256": "b33251d90a62acf33f95e1281d5c5a61878d1c281784ef0a066ec8173e6c0f1b", + "shape": [ + 3, + 2 + ], + "sl_orbits": 10 + }, + { + "norm_trials": 6578, + "pencils": 6561, + "q": 3, + "sha256": "1bdecda6a6e1612c665b4d6698cf17acdb264f45a9fcd15dec4cc6d44de14242", + "shape": [ + 2, + 2 + ], + "sl_orbits": 14 + }, + { + "norm_trials": 0, + "pencils": 9, + "q": 3, + "sha256": "386e315ebf488c288acdf7b56bd3cfa3ab70a54caa85065ba6a435ab5d249987", + "shape": [ + 1, + 1 + ], + "sl_orbits": 2 + }, + { + "norm_trials": 59, + "pencils": 81, + "q": 3, + "sha256": "51b6d58dbf2cb65a3bff52606b2e34acbfb4e3420aec98922fe22252b81fa1cb", + "shape": [ + 1, + 2 + ], + "sl_orbits": 4 + }, + { + "norm_trials": 0, + "pencils": 81, + "q": 3, + "sha256": "3e5333c27f7c7588517e6eabd7e499fc6423a4e7cc6004da225669a211888d13", + "shape": [ + 2, + 1 + ], + "sl_orbits": 4 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_SMALL" + }, + "extension": { + "domains": [ + { + "norm_trials": 159186, + "pencils": 65536, + "q": 4, + "sha256": "272678b3cc16bcf8b384d81003c7b49465654d7a5cd329a29c5632c7e949fcf8", + "shape": [ + 2, + 2 + ], + "sl_orbits": 12 + }, + { + "norm_trials": 0, + "pencils": 16, + "q": 4, + "sha256": "3075f79d4cb7c2b3fc5c75ae3d9033269fa55788d1743eefe0750c27b9e45440", + "shape": [ + 1, + 1 + ], + "sl_orbits": 2 + }, + { + "norm_trials": 163, + "pencils": 256, + "q": 4, + "sha256": "b43828b641dceb0ec62271478ece02ec1bbeb76281a06023af79606028d550bb", + "shape": [ + 1, + 2 + ], + "sl_orbits": 5 + }, + { + "norm_trials": 0, + "pencils": 256, + "q": 4, + "sha256": "f1c8a38ae4f4cfe77ba95339e296ddff60f857dea0d11bf3226fb2dbdd2b4d49", + "shape": [ + 2, + 1 + ], + "sl_orbits": 5 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_EXTENSION" + }, + "fixtures": { + "controls": 29, + "fixtures": 24, + "larger_transports": 23, + "no_invertible_slice_cases": 11, + "records": [ + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 0, + 1, + 1 + ], + 1 + ] + ], + "q": 2, + "shape": [ + 4, + 4 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 2, + "shape": [ + 4, + 4 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 2, + "shape": [ + 7, + 7 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 2, + "shape": [ + 4, + 8 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 2, + "shape": [ + 3, + 3 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 1 + ], + [ + "finite", + [ + 1, + 1 + ], + 1 + ], + [ + "infinity", + [], + 1 + ] + ], + "q": 2, + "shape": [ + 3, + 3 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 1, + 1, + 1 + ], + 1 + ] + ], + "q": 3, + "shape": [ + 4, + 4 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 3, + "shape": [ + 4, + 4 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 3, + "shape": [ + 7, + 7 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 3, + "shape": [ + 4, + 8 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 3, + "shape": [ + 3, + 3 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 1 + ], + [ + "finite", + [ + 2, + 1 + ], + 1 + ], + [ + "finite", + [ + 1, + 1 + ], + 1 + ], + [ + "infinity", + [], + 1 + ] + ], + "q": 3, + "shape": [ + 4, + 4 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 1, + 2, + 1 + ], + 1 + ] + ], + "q": 4, + "shape": [ + 4, + 4 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 4, + "shape": [ + 4, + 4 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 4, + "shape": [ + 7, + 7 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 4, + "shape": [ + 4, + 8 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 4, + "shape": [ + 3, + 3 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 1 + ], + [ + "finite", + [ + 1, + 1 + ], + 1 + ], + [ + "finite", + [ + 2, + 1 + ], + 1 + ], + [ + "finite", + [ + 3, + 1 + ], + 1 + ], + [ + "infinity", + [], + 1 + ] + ], + "q": 4, + "shape": [ + 5, + 5 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 3, + 1, + 1 + ], + 1 + ] + ], + "q": 9, + "shape": [ + 4, + 4 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 9, + "shape": [ + 4, + 4 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 9, + "shape": [ + 7, + 7 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 9, + "shape": [ + 4, + 8 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 9, + "shape": [ + 3, + 3 + ], + "slice_actions": 720 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_FIXTURES" + }, + "norms": { + "controls": 3, + "field_degree_pairs": [ + [ + 2, + 1 + ], + [ + 2, + 2 + ], + [ + 2, + 3 + ], + [ + 2, + 4 + ], + [ + 2, + 5 + ], + [ + 2, + 6 + ], + [ + 2, + 7 + ], + [ + 2, + 8 + ], + [ + 3, + 1 + ], + [ + 3, + 2 + ], + [ + 3, + 3 + ], + [ + 3, + 4 + ], + [ + 3, + 5 + ], + [ + 3, + 6 + ], + [ + 3, + 7 + ], + [ + 3, + 8 + ], + [ + 4, + 1 + ], + [ + 4, + 2 + ], + [ + 4, + 3 + ], + [ + 4, + 4 + ], + [ + 4, + 5 + ], + [ + 4, + 6 + ], + [ + 4, + 7 + ], + [ + 4, + 8 + ], + [ + 9, + 1 + ], + [ + 9, + 2 + ], + [ + 9, + 3 + ], + [ + 9, + 4 + ], + [ + 9, + 5 + ], + [ + 9, + 6 + ], + [ + 9, + 7 + ], + [ + 9, + 8 + ] + ], + "lifted_determinants": 336, + "norm_targets": 112, + "sampled_candidates": 648, + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_NORMS" + }, + "characters": { + "determinant_triples": 180, + "models": 15, + "records": [ + { + "model": [ + [ + "R", + 1, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 0, + 1 + ], + [ + "L", + 0, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 2, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 1, + 1 + ], + [ + "I", + 1, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ], + [ + "F", + [ + 1, + 1 + ], + 1, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ] + ], + "q": 3, + "sl_orbits": 2 + }, + { + "model": [ + [ + "R", + 0, + 1 + ], + [ + "L", + 0, + 1 + ] + ], + "q": 3, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 2, + 1 + ] + ], + "q": 3, + "sl_orbits": 4 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 1, + 1 + ], + [ + "I", + 1, + 1 + ] + ], + "q": 3, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ], + [ + "F", + [ + 1, + 1 + ], + 1, + 1 + ] + ], + "q": 3, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ] + ], + "q": 4, + "sl_orbits": 3 + }, + { + "model": [ + [ + "R", + 0, + 1 + ], + [ + "L", + 0, + 1 + ] + ], + "q": 4, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 2, + 1 + ] + ], + "q": 4, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 1, + 1 + ], + [ + "I", + 1, + 1 + ] + ], + "q": 4, + "sl_orbits": 3 + }, + { + "model": [ + [ + "R", + 1, + 1 + ], + [ + "F", + [ + 1, + 1 + ], + 1, + 1 + ] + ], + "q": 4, + "sl_orbits": 1 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_CHARACTERS" + } + }, + "registered_python": "3.12.14", + "registered_phases": [ + { + "domains": [ + { + "norm_trials": 0, + "pencils": 256, + "q": 2, + "sha256": "7049ccb42f28e78a64f4161b70e8906d5da61ccc1f51eae1bb8e3162af894ef6", + "shape": [ + 2, + 2 + ], + "sl_orbits": 8 + }, + { + "norm_trials": 0, + "pencils": 4096, + "q": 2, + "sha256": "e8e266da2652067166f367f7fc59c4fd29a22a92437163a6454bb250641e4968", + "shape": [ + 2, + 3 + ], + "sl_orbits": 10 + }, + { + "norm_trials": 0, + "pencils": 4096, + "q": 2, + "sha256": "b33251d90a62acf33f95e1281d5c5a61878d1c281784ef0a066ec8173e6c0f1b", + "shape": [ + 3, + 2 + ], + "sl_orbits": 10 + }, + { + "norm_trials": 6578, + "pencils": 6561, + "q": 3, + "sha256": "1bdecda6a6e1612c665b4d6698cf17acdb264f45a9fcd15dec4cc6d44de14242", + "shape": [ + 2, + 2 + ], + "sl_orbits": 14 + }, + { + "norm_trials": 0, + "pencils": 9, + "q": 3, + "sha256": "386e315ebf488c288acdf7b56bd3cfa3ab70a54caa85065ba6a435ab5d249987", + "shape": [ + 1, + 1 + ], + "sl_orbits": 2 + }, + { + "norm_trials": 59, + "pencils": 81, + "q": 3, + "sha256": "51b6d58dbf2cb65a3bff52606b2e34acbfb4e3420aec98922fe22252b81fa1cb", + "shape": [ + 1, + 2 + ], + "sl_orbits": 4 + }, + { + "norm_trials": 0, + "pencils": 81, + "q": 3, + "sha256": "3e5333c27f7c7588517e6eabd7e499fc6423a4e7cc6004da225669a211888d13", + "shape": [ + 2, + 1 + ], + "sl_orbits": 4 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_SMALL" + }, + { + "domains": [ + { + "norm_trials": 159186, + "pencils": 65536, + "q": 4, + "sha256": "272678b3cc16bcf8b384d81003c7b49465654d7a5cd329a29c5632c7e949fcf8", + "shape": [ + 2, + 2 + ], + "sl_orbits": 12 + }, + { + "norm_trials": 0, + "pencils": 16, + "q": 4, + "sha256": "3075f79d4cb7c2b3fc5c75ae3d9033269fa55788d1743eefe0750c27b9e45440", + "shape": [ + 1, + 1 + ], + "sl_orbits": 2 + }, + { + "norm_trials": 163, + "pencils": 256, + "q": 4, + "sha256": "b43828b641dceb0ec62271478ece02ec1bbeb76281a06023af79606028d550bb", + "shape": [ + 1, + 2 + ], + "sl_orbits": 5 + }, + { + "norm_trials": 0, + "pencils": 256, + "q": 4, + "sha256": "f1c8a38ae4f4cfe77ba95339e296ddff60f857dea0d11bf3226fb2dbdd2b4d49", + "shape": [ + 2, + 1 + ], + "sl_orbits": 5 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_EXTENSION" + }, + { + "controls": 29, + "fixtures": 24, + "larger_transports": 23, + "no_invertible_slice_cases": 11, + "records": [ + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 0, + 1, + 1 + ], + 1 + ] + ], + "q": 2, + "shape": [ + 4, + 4 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 2, + "shape": [ + 4, + 4 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 2, + "shape": [ + 7, + 7 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 2, + "shape": [ + 4, + 8 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 2, + "shape": [ + 3, + 3 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 1 + ], + [ + "finite", + [ + 1, + 1 + ], + 1 + ], + [ + "infinity", + [], + 1 + ] + ], + "q": 2, + "shape": [ + 3, + 3 + ], + "slice_actions": 6 + }, + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 1, + 1, + 1 + ], + 1 + ] + ], + "q": 3, + "shape": [ + 4, + 4 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 3, + "shape": [ + 4, + 4 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 3, + "shape": [ + 7, + 7 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 3, + "shape": [ + 4, + 8 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 3, + "shape": [ + 3, + 3 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 1 + ], + [ + "finite", + [ + 2, + 1 + ], + 1 + ], + [ + "finite", + [ + 1, + 1 + ], + 1 + ], + [ + "infinity", + [], + 1 + ] + ], + "q": 3, + "shape": [ + 4, + 4 + ], + "slice_actions": 24 + }, + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 1, + 2, + 1 + ], + 1 + ] + ], + "q": 4, + "shape": [ + 4, + 4 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 4, + "shape": [ + 4, + 4 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 4, + "shape": [ + 7, + 7 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 4, + "shape": [ + 4, + 8 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 4, + "shape": [ + 3, + 3 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 1 + ], + [ + "finite", + [ + 1, + 1 + ], + 1 + ], + [ + "finite", + [ + 2, + 1 + ], + 1 + ], + [ + "finite", + [ + 3, + 1 + ], + 1 + ], + [ + "infinity", + [], + 1 + ] + ], + "q": 4, + "shape": [ + 5, + 5 + ], + "slice_actions": 60 + }, + { + "blocks": [ + [ + "finite", + [ + 1, + 0, + 3, + 1, + 1 + ], + 1 + ] + ], + "q": 9, + "shape": [ + 4, + 4 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "finite", + [ + 0, + 1 + ], + 4 + ] + ], + "q": 9, + "shape": [ + 4, + 4 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "right", + [], + 6 + ], + [ + "left", + [], + 0 + ] + ], + "q": 9, + "shape": [ + 7, + 7 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ], + [ + "right", + [], + 1 + ] + ], + "q": 9, + "shape": [ + 4, + 8 + ], + "slice_actions": 720 + }, + { + "blocks": [ + [ + "left", + [], + 0 + ], + [ + "right", + [], + 0 + ], + [ + "finite", + [ + 1, + 1 + ], + 2 + ] + ], + "q": 9, + "shape": [ + 3, + 3 + ], + "slice_actions": 720 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_FIXTURES" + }, + { + "controls": 3, + "field_degree_pairs": [ + [ + 2, + 1 + ], + [ + 2, + 2 + ], + [ + 2, + 3 + ], + [ + 2, + 4 + ], + [ + 2, + 5 + ], + [ + 2, + 6 + ], + [ + 2, + 7 + ], + [ + 2, + 8 + ], + [ + 3, + 1 + ], + [ + 3, + 2 + ], + [ + 3, + 3 + ], + [ + 3, + 4 + ], + [ + 3, + 5 + ], + [ + 3, + 6 + ], + [ + 3, + 7 + ], + [ + 3, + 8 + ], + [ + 4, + 1 + ], + [ + 4, + 2 + ], + [ + 4, + 3 + ], + [ + 4, + 4 + ], + [ + 4, + 5 + ], + [ + 4, + 6 + ], + [ + 4, + 7 + ], + [ + 4, + 8 + ], + [ + 9, + 1 + ], + [ + 9, + 2 + ], + [ + 9, + 3 + ], + [ + 9, + 4 + ], + [ + 9, + 5 + ], + [ + 9, + 6 + ], + [ + 9, + 7 + ], + [ + 9, + 8 + ] + ], + "lifted_determinants": 336, + "norm_targets": 112, + "sampled_candidates": 648, + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_NORMS" + }, + { + "determinant_triples": 180, + "models": 15, + "records": [ + { + "model": [ + [ + "R", + 1, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 0, + 1 + ], + [ + "L", + 0, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 2, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 1, + 1 + ], + [ + "I", + 1, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ], + [ + "F", + [ + 1, + 1 + ], + 1, + 1 + ] + ], + "q": 2, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ] + ], + "q": 3, + "sl_orbits": 2 + }, + { + "model": [ + [ + "R", + 0, + 1 + ], + [ + "L", + 0, + 1 + ] + ], + "q": 3, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 2, + 1 + ] + ], + "q": 3, + "sl_orbits": 4 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 1, + 1 + ], + [ + "I", + 1, + 1 + ] + ], + "q": 3, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ], + [ + "F", + [ + 1, + 1 + ], + 1, + 1 + ] + ], + "q": 3, + "sl_orbits": 1 + }, + { + "model": [ + [ + "R", + 1, + 1 + ] + ], + "q": 4, + "sl_orbits": 3 + }, + { + "model": [ + [ + "R", + 0, + 1 + ], + [ + "L", + 0, + 1 + ] + ], + "q": 4, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 2, + 1 + ] + ], + "q": 4, + "sl_orbits": 1 + }, + { + "model": [ + [ + "F", + [ + 0, + 1 + ], + 1, + 1 + ], + [ + "I", + 1, + 1 + ] + ], + "q": 4, + "sl_orbits": 3 + }, + { + "model": [ + [ + "R", + 1, + 1 + ], + [ + "F", + [ + 1, + 1 + ], + 1, + 1 + ] + ], + "q": 4, + "sl_orbits": 1 + } + ], + "source_inputs": 11, + "status": "PASS_RAW_PENCIL_SL_CHARACTERS" + } + ], + "sealed_optimized_replay": { + "readonly_files_unchanged": 21, + "optimized_git_free": true, + "empty_path": true, + "source_corruption_rejected": true, + "python": "Python 3.12.14", + "scientific_commit": "3afe93780f111c6368badd47394ce761d4421317", + "phases": [ + "PASS_RAW_PENCIL_SL_SMALL", + "PASS_RAW_PENCIL_SL_EXTENSION", + "PASS_RAW_PENCIL_SL_FIXTURES", + "PASS_RAW_PENCIL_SL_NORMS", + "PASS_RAW_PENCIL_SL_CHARACTERS" + ] + } +} diff --git a/research/raw-pencil-sl-transport/SOURCES.json b/research/raw-pencil-sl-transport/SOURCES.json new file mode 100644 index 0000000000..0d1ee8b88a --- /dev/null +++ b/research/raw-pencil-sl-transport/SOURCES.json @@ -0,0 +1,95 @@ +{ + "schema_version": 1, + "base_commit": "df0137efd35e11b4445734bf612bdd4c7ebc330c", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "581f8d87008354eb5b869f7ed9de1317ad837ce8", + "sha256": "2a0220e866417774606e0f991e41b9c1d26b1f43b97857238cf478dbc7d330b5" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "f126dd2e2dad2b669e75d1d0d0bd05c600725602", + "sha256": "f7a48bfa2659b88378282a8eee7d9fe52cdf505594124c4d1686b58510fffd72" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/INPUTS.json", + "usage": "input", + "git_blob": "846f5608d46716576a5b52d9a55b82b5a952e8c5", + "sha256": "9cdde58c67e7df0c210abab5a079a4bb5f299c7b6303b639dc59d2e8a020ccb9", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/INPUTS.json" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/NOTICE.md", + "usage": "input", + "git_blob": "6040e2df53362fcf5be34c52719af065e83e7665", + "sha256": "78d5207066ecac992ccdea3c7b613d3a8541c195cf6475e878bede2b63f90aad", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/NOTICE.md" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/PROOF.md", + "usage": "input", + "git_blob": "2ab4d4540151a7475d3bf9f3f04ffb8ca0da9b87", + "sha256": "d52266d65835b7558ecf3ff272ac086deabb232b918aeb8228436b96eaeb99ff", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/PROOF.md" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/pencils.py", + "usage": "input", + "git_blob": "45c52fbee64f7b40bd769907a027aba56545e077", + "sha256": "2fe16f51b2d6097cd4e606b607aee4e4d0c53f8bb455d4aba38ef5517c310018", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/pencils.py" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/source/REGULAR.md", + "usage": "input", + "git_blob": "20f8262d3747f28e4535ec3f928f7481f8306749", + "sha256": "ba945687c23f6e675e2c320c7e5ccf345b17090e4d4283721ff950d62da5516e", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/source/REGULAR.md" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/source/SINGULAR.md", + "usage": "input", + "git_blob": "9de07b628089ab903751ea2571b62b08dba7e524", + "sha256": "2d0b2348bb27063e7bf34769b1a43c90d593902f043ffc438d7ec887f0016295", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/source/SINGULAR.md" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/source/oracle.py", + "usage": "input", + "git_blob": "6535d1363ece5521d75a6ef218f4e68a5c2eeb5d", + "sha256": "9713ec418b158055658c3a53766f305d6e3734e7b775c8bbd365a46e525966aa", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/source/oracle.py" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/characters/source/pencil.py", + "usage": "input", + "git_blob": "6bc7fc076e6ce2418ec9ed05d85115deb3d4bdd2", + "sha256": "a714862853cc884e84eac34ba1d7ccb14a6326bcfadb630910034bb44bd305db", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/characters/source/pencil.py" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/raw/PROOF.md", + "usage": "input", + "git_blob": "0034e0b2f75d500b47cc13fcd43717015c1d9fd1", + "sha256": "c9129417a0370e051bf9fcd18c09bc923565cb49fef081b555f757ed92abd465", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/raw/PROOF.md" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/raw/decompose.py", + "usage": "input", + "git_blob": "c8c275df6668356527f2a4488598efc5268d6755", + "sha256": "c13814651f940742ddcbf0addcac2f6ce5286dcfbc6db74141cab2a7ebfbf4a6", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/raw/decompose.py" + }, + { + "path": "research/raw-pencil-sl-transport/vendor/raw/field_source.py", + "usage": "input", + "git_blob": "1066bb74c19d180bfef7d9dd1c0650ec6bbd7780", + "sha256": "6daa160346d04691c6ca3c9c820b3df8982de4320ec01e5db10e3cb932f42c00", + "pin": "head:ee3536dbba8cf627b6e65459d38cc14c86436e79:research/raw-pencil-sl-transport/vendor/raw/field_source.py" + } + ] +} diff --git a/research/raw-pencil-sl-transport/TASK.json b/research/raw-pencil-sl-transport/TASK.json new file mode 100644 index 0000000000..93b01010a8 --- /dev/null +++ b/research/raw-pencil-sl-transport/TASK.json @@ -0,0 +1,91 @@ +{ + "schema_version": 1, + "task_id": "uniform-transfer-audit", + "priority_revision": 7, + "base_commit": "df0137efd35e11b4445734bf612bdd4c7ebc330c", + "original_card": { + "id": "uniform-transfer-audit", + "question": "Does one quantified step of the proposed #4100 all-size construction hold at its actual caller?", + "starting_points": [ + "docs/research/research-family-status.md", + "certificates/selected-result.json", + "research/unconditional-batched-crt/README.md" + ], + "methods": [ + "Prove one missing implication with explicit quantified hypotheses.", + "Find an exact counterexample at the claimed interface boundary." + ], + "acceptance_gate": "Identify the proposition and what would change downstream; do not equate a finite replay with a universal proof.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read PROOF.md and AUDIT.md in #4100. Select one distinct obligation: CRT total repair, native/free-algebra lifting, precision/conditioning, or complete fixed-tape cost. This is an author-submitted proof, not an accepted unconditional theorem.", + "scope": "Source-binding orientation only; no scientific replay, theorem acceptance or supplier admission. Budget any heavy replay separately." + }, + "first_experiment": "Check live handoffs; name one proposition, its caller, quantified domain and dependency closure. Independently prove the implication or exhibit a precise gap/counterexample. Prioritize CRT.md total repair or COMPLEX.md free-algebra lift only if unclaimed. Stop at the chosen obligation; do not substitute finite samples or root arithmetic for an all-size proof, or launch the complete package by default.", + "bottleneck_link": "Finite supplier improvements are useful only under the retained transfer obligations.", + "allowed_variations": [ + "One CRT repair, native lift, precision/conditioning or tape-cost proposition, with its exact caller." + ], + "scope_change_triggers": [ + "Replacing a quantified obligation with another finite smoke test.", + "Treating archive intake, an author PASS receipt or a finite composed fixture as discharge of the universal hypotheses." + ], + "overlap_terms": [ + "uniform transfer", + "all-size", + "precision", + "4100", + "unconditional-batched-crt" + ], + "existing_checks": [ + { + "scope": "PR #4100: proposed unconditional construction and finite checks, without independent acceptance.", + "evidence": "research/unconditional-batched-crt/README.md", + "remaining": "Independent proof audit of one caller-bound all-size implication; all other premises remain explicit.", + "status": "author-checked", + "source_commit": "337d04939571a637aeab54a0f58f54fde811663a", + "selected_record_sha256": "bb2eaa58647b353f88d0aec2eafb9d30df1be53589231b23e12ceef3e4bad129" + } + ] + }, + "scope_status": "changed", + "actual_scope": "Complete raw finite-field two-slice tensor SL recognition, canonical representatives and literal determinant-one transporters, with exact general-degree norm witnesses.", + "scope_change_reason": "The live PR5692 raw extractor and PR5689 supplied character theorem leave a distinct raw-to-SL boundary. The adversarial-audit card is changed to construction and independent finite-orbit validation at that interface.", + "bottleneck_link": "The tensor atlas needs exact basis-sensitive admissibility tests on actual candidates. This completes the two-slice algebraic input contract; a physical mechanism and its complete paid bill remain open, so no kappa gain follows.", + "budget_minutes": 150, + "stop_rule": "Require a complete raw orbit argument, literal maps, independent full small orbit partitions, higher-degree and no-invertible-slice cases, source corruption and portable replay. Stop at a counterexample or exact boundary if any implication fails.", + "outcome": "completed", + "evidence": "See RESULT.json and EVIDENCE.md for the exact finite domains, environments, failures, controls and verification limits.", + "author": "Ali Romman with substantial OpenAI Codex assistance", + "ai_assistance": "Substantial OpenAI Codex assistance in mathematics, implementation, verification and prose. No subagents. The two consumed packages also use the same assistant family; no independent human or formal review is claimed.", + "open_questions": [ + { + "question": "Which concrete tensor-atlas mechanism uses these raw SL decisions to change a paid caller?", + "why_it_matters": "Algebraic admissibility alone does not improve kappa.", + "first_step": "Name the native producer and consumer and price the complete map preparation, movement, restoration and recursive work.", + "blocked_by": "No physical realization or complete caller bill is provided." + }, + { + "question": "Can general residue norm witnesses have a deterministic polynomial implementation at the same field interface?", + "why_it_matters": "The current exact construction has expected polynomial runtime under uniform sampling.", + "first_step": "Specify a deterministic norm solver with its actual finite-field cost and compare it against the retained multiplication determinants.", + "blocked_by": "No deterministic general-degree solver is implemented here." + } + ], + "discussion": "https://github.com/CrocSwap/integer-mult-bounds/discussions/5670#discussioncomment-19190746", + "expansion_decision": { + "decision": "Close the full raw two-slice SL boundary and remove the executable norm-degree cap. Do not start a physical supplier from an unpriced algebraic orbit result.", + "proved_costs": "All slice actions, raw extraction, determinants, character closure and norm preparation have positive polynomial costs in dimension for fixed field. Norm witnesses have expected, not deterministic worst-case, polynomial runtime.", + "unknowns": "Native producer/consumer, physical movement, dirty restoration, storage, precision and the complete recursive invoice." + }, + "freshness": { + "canonical_main": "df0137efd35e11b4445734bf612bdd4c7ebc330c", + "overlap_checked_utc": "2026-10-26T08:23:49Z", + "coverage": "All 7676 main notes, 392 open PRs and 5043 Discussion records. Separate literal terms and a cached-body scan found no competing raw SL or residue norm claim. The consumed predecessors are released. Main was fetched again before publication." + } +} diff --git a/research/raw-pencil-sl-transport/VERIFY.json b/research/raw-pencil-sl-transport/VERIFY.json new file mode 100644 index 0000000000..c8d7ce3a65 --- /dev/null +++ b/research/raw-pencil-sl-transport/VERIFY.json @@ -0,0 +1,76 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/raw-pencil-sl-transport/vendor/characters/INPUTS.json", + "research/raw-pencil-sl-transport/vendor/characters/NOTICE.md", + "research/raw-pencil-sl-transport/vendor/characters/PROOF.md", + "research/raw-pencil-sl-transport/vendor/characters/pencils.py", + "research/raw-pencil-sl-transport/vendor/characters/source/REGULAR.md", + "research/raw-pencil-sl-transport/vendor/characters/source/SINGULAR.md", + "research/raw-pencil-sl-transport/vendor/characters/source/oracle.py", + "research/raw-pencil-sl-transport/vendor/characters/source/pencil.py", + "research/raw-pencil-sl-transport/vendor/raw/PROOF.md", + "research/raw-pencil-sl-transport/vendor/raw/decompose.py", + "research/raw-pencil-sl-transport/vendor/raw/field_source.py" + ], + "commands": [ + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py", + "--phase", + "small" + ], + "timeout_seconds": 180, + "checks": "Complete F2/F3 raw SL orbits, literal determinant-one maps and rectangular/one-dimensional factors." + }, + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py", + "--phase", + "extension" + ], + "timeout_seconds": 600, + "checks": "Complete F4 raw SL orbits and literal maps, including all65536 two-by-two pencils." + }, + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py", + "--phase", + "fixtures" + ], + "timeout_seconds": 300, + "checks": "Larger arbitrary-basis, nonsplit, no-invertible-slice and unbounded-interface cases; raw-to-raw maps; failure controls." + }, + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py", + "--phase", + "norms" + ], + "timeout_seconds": 60, + "checks": "All declared degree1..8 residue norm targets and length1/2/4 lifted determinants; invalid norm controls." + }, + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py", + "--phase", + "characters" + ], + "timeout_seconds": 60, + "checks": "All determinant triples in fifteen supplied-model GL orbits compared with the frozen complete character oracle." + } + ] +} diff --git a/research/raw-pencil-sl-transport/sl.py b/research/raw-pencil-sl-transport/sl.py new file mode 100644 index 0000000000..71c7295f9e --- /dev/null +++ b/research/raw-pencil-sl-transport/sl.py @@ -0,0 +1,207 @@ +"""Raw finite-field pencil SL labels and maps. Apache-2.0. + +Ali Romman with substantial OpenAI Codex assistance. The retained raw +extractor and complete fixed-slice character theorem keep their credit. +""" +import hashlib +from itertools import product +import json +from pathlib import Path +import random +import sys + +ROOT=Path(__file__).resolve().parent + + +def need(ok,message): + if not ok:raise ValueError(message) + + +def authenticate(): + rows=json.loads((ROOT/'SOURCES.json').read_text())['files'];count=0 + for row in rows: + if row['usage']!='input':continue + path=ROOT/Path(row['path']).relative_to('research/raw-pencil-sl-transport') + raw=path.read_bytes() + need(hashlib.sha256(raw).hexdigest()==row['sha256'],'source hash: '+str(path)) + need(hashlib.sha1(b'blob '+str(len(raw)).encode()+b'\0'+raw).hexdigest()==row['git_blob'],'source blob') + count+=1 + return count + + +authenticate() +sys.path.insert(0,str(ROOT/'vendor/raw')) +import decompose as d +Field=d.a.Field + + +def multiply(A,B,f):return d.mm(A,B,len(B[0]) if B else 0,f) + +def transpose(A,n):return d.tr(A,n) + +def pair_product(x,y,f):return tuple(f.mul[a][b] for a,b in zip(x,y)) + + +def action(slices,maps,f): + A,B=slices;P,Q,S=maps;qt=transpose(Q,len(Q)) + return tuple(multiply(multiply(P,[[f.add[f.mul[x][a]][f.mul[y][b]] for a,b in zip(r,s)] + for r,s in zip(A,B)],f),qt,f) for x,y in S) + + +def compose(left,right,f):return tuple(multiply(a,b,f) for a,b in zip(left,right)) + + +def inverse(maps,f):return tuple(d.a.inverse(a,f) for a in maps) + + +def special_linear_two(f): + for a,b,c,e in product(range(f.q),repeat=4): + if f.add[f.mul[a][e]][f.neg[f.mul[b][c]]]==1:yield [[a,b],[c,e]] + + +def validate(slices,m,n,f): + need(isinstance(f,Field),'explicit common finite field') + need(type(m) is int and type(n) is int and m>0 and n>0,'positive factor dimensions') + need(isinstance(slices,(tuple,list)) and len(slices)==2,'two coefficient matrices') + for A in slices: + need(isinstance(A,(tuple,list)) and len(A)==m,'matrix row count') + for row in A: + need(isinstance(row,(tuple,list)) and len(row)==n and + all(type(x) is int and 0<=x=2 and poly[-1]==1 and d.factor(poly,f)==[tuple(poly)],'irreducible norm polynomial') + degree=len(poly)-1;exponent=(f.q**degree-1)//(f.q-1);trials=0 + while True: + value=[rng.randrange(f.q) for _ in range(degree)];trials+=1 + if not any(value):continue + norm=d.ppow(value,exponent,f,poly) + need(len(norm)==1,'norm belongs to the base field') + if norm[0]==target:return value,trials + + +def put(A,B,r,c): + for i,row in enumerate(B):A[r+i][c:c+len(row)]=row + + +def fixed_witness(blocks,path,m,n,f,rng): + P,Q=d.a.identity(m),d.a.identity(n);trials=0 + starts=[];r=c=0 + for block in blocks: + h,w=dimensions(block);starts.append((r,c));r+=h;c+=w + for index,u in path: + block=blocks[index];side,poly,e=block;h,w=dimensions(block);v=f.inv[u] + if side=='right': + bp=[[u if i==j else 0 for j in range(h)] for i in range(h)] + bq=[[v if i==j else 0 for j in range(w)] for i in range(w)] + elif side=='left': + bp=[[v if i==j else 0 for j in range(h)] for i in range(h)] + bq=[[u if i==j else 0 for j in range(w)] for i in range(w)] + else: + if side=='finite':coefficients,used=norm_unit(poly,u,f,rng);trials+=used + else:coefficients=[u] + J=d.companion(d.ppow(poly if side=='finite' else (0,1),e,f),f) + bp=d.peval(coefficients,J,f);bq=transpose(d.a.inverse(bp,f),w) + need((d.a.determinant(bp,f),d.a.determinant(bq,f))==character(block,u,f),'literal block character') + gp,gq=d.a.identity(m),d.a.identity(n);r,c=starts[index] + put(gp,bp,r,r);put(gq,bq,c,c) + P,Q=multiply(gp,P,f),multiply(gq,Q,f) + model=d.model(blocks,f)[:2] + need(action(model,(P,Q,d.a.identity(2)),f)==model,'complete fixed-slice stabilizer') + return (P,Q,d.a.identity(2)),trials + + +def canonicalize(slices,m,n,f,rng=None): + """Return a complete label, representative and literal SL map to it.""" + result=analyze(slices,m,n,f) + correction,trials=fixed_witness(result['blocks'],result['correction_path'],m,n,f, + random.SystemRandom() if rng is None else rng) + maps=compose(result['scale'],compose(correction,result['to_strict'],f),f) + need(all(d.a.determinant(M,f)==1 for M in maps),'three determinant-one maps') + need(action(slices,maps,f)==result['representative'],'complete canonical SL endpoint') + return dict(key=result['key'],representative=result['representative'],maps=maps, + slice_actions=result['slice_actions'],norm_trials=trials) + + +def transporter(first,second,m,n,f,rng=None): + a=canonicalize(first,m,n,f,rng);b=canonicalize(second,m,n,f,rng) + if a['key']!=b['key']:return None + maps=compose(inverse(b['maps'],f),a['maps'],f) + need(all(d.a.determinant(M,f)==1 for M in maps),'transporter determinants') + need(action(first,maps,f)==tuple(second),'raw-to-raw SL endpoint') + return maps diff --git a/research/raw-pencil-sl-transport/vendor/characters/INPUTS.json b/research/raw-pencil-sl-transport/vendor/characters/INPUTS.json new file mode 100644 index 0000000000..846f5608d4 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/INPUTS.json @@ -0,0 +1,30 @@ +[ + { + "local": "source/pencil.py", + "commit": "618fb04433927ade44ed5b507f8d30f9ede2bde5", + "path": "research/mixed-singular-kronecker-characters/source/pencil.py", + "git_blob": "6bc7fc076e6ce2418ec9ed05d85115deb3d4bdd2", + "sha256": "a714862853cc884e84eac34ba1d7ccb14a6326bcfadb630910034bb44bd305db" + }, + { + "local": "source/oracle.py", + "commit": "618fb04433927ade44ed5b507f8d30f9ede2bde5", + "path": "research/mixed-singular-kronecker-characters/oracle.py", + "git_blob": "6535d1363ece5521d75a6ef218f4e68a5c2eeb5d", + "sha256": "9713ec418b158055658c3a53766f305d6e3734e7b775c8bbd365a46e525966aa" + }, + { + "local": "source/SINGULAR.md", + "commit": "618fb04433927ade44ed5b507f8d30f9ede2bde5", + "path": "research/mixed-singular-kronecker-characters/PROOF.md", + "git_blob": "9de07b628089ab903751ea2571b62b08dba7e524", + "sha256": "2d0b2348bb27063e7bf34769b1a43c90d593902f043ffc438d7ec887f0016295" + }, + { + "local": "source/REGULAR.md", + "commit": "43142bedc7cb5c0f1f73ff3fea6d9bfd237949ee", + "path": "research/pencil-determinant-image/README.md", + "git_blob": "20f8262d3747f28e4535ec3f928f7481f8306749", + "sha256": "ba945687c23f6e675e2c320c7e5ccf345b17090e4d4283721ff950d62da5516e" + } +] diff --git a/research/raw-pencil-sl-transport/vendor/characters/NOTICE.md b/research/raw-pencil-sl-transport/vendor/characters/NOTICE.md new file mode 100644 index 0000000000..6040e2df53 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/NOTICE.md @@ -0,0 +1,7 @@ +# Attribution + +Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. + +Nick Petalas PR5250 supplies the invertible-slice theorem and the retained classical centralizer determinant proof, with Arne Storjohann and Ferrer/Mingueza/Montoro credit. apoursh PR5672 supplies the singular symmetric-power lifts and finite-field arithmetic. Ali Romman PR5683 supplies the complete singular mixing theorem and literal coefficient-equation oracle. David Ganz supplies the A030/A026/A029 atlas context. Classical Kronecker, companion-matrix and finite-field norm theory remain predecessor mathematics. + +The new contribution is the per-primary chart construction, the complete regular/singular determinant assembly, the no-rational-invertible-slice family, and the bounded exact checks. Four original source files are retained byte for byte. INPUTS.json and SOURCES.json identify their commits, paths, Git objects and SHA256 hashes. Global literature priority is not claimed. diff --git a/research/raw-pencil-sl-transport/vendor/characters/PROOF.md b/research/raw-pencil-sl-transport/vendor/characters/PROOF.md new file mode 100644 index 0000000000..2ab4d45401 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/PROOF.md @@ -0,0 +1,145 @@ +# Complete determinant images of supplied finite-field pencils + +## 1. Scope and conventions + +Let K=F_q. The input is a complete supplied Kronecker block model for a matrix pencil with positive total row and column dimensions m,n. The types are: + +- Right singular blocks R_e, of shape e by e+1, with s on the diagonal and t above it. +- Their transposes L_e. Zero indices are allowed. +- Finite regular blocks `(I,C(f^ell))`, where f is a monic irreducible polynomial over K, ell>=1, and C is the companion matrix with ones below the diagonal. +- Infinity blocks `(C(X^ell),I)`. + +Every type can have any positive multiplicity. All matrices and both tensor dimensions are finite. The model is supplied. This note does not implement its discovery from an arbitrary tensor. These are the full Kronecker types, not only semisimple or split regular blocks. + +Use the covariant action + +`(A0,A1) -> (P(a A0+b A1)Q^T, P(c A0+d A1)Q^T)`, + +where `R=[[a,b],[c,d]]` is invertible. Let Delta be the image of the stabilizer under `(det P,det Q,det R)`. Polynomial pencil identities are coefficient identities in independent indeterminates. They are not tests at only the q+1 rational directions. + +The singular Hom spaces and slice lifts are credited to PR5683 and apoursh PR5672. The regular centralizer determinant theorem is the classical result retained by Nick Petalas PR5250. New here are the per-primary chart construction, full mixed assembly and the removal of the global invertible-rational-slice premise. + +## 2. Normalize one primary block after any slice action + +Consider a finite block `(I,J)`, with J=C(f^ell). Set B=aI+bJ and D=cI+dJ. If B is invertible, put H=B^-1 D. Otherwise D is invertible: failure of both would make both linear polynomials a+bX and c+dX divisible by the same irreducible f, contrary to det R!=0. In the second case f must be linear. Put H=D^-1 B. Its only eigenvalue is zero, and its nilpotence index is ell. + +For an infinity block `(J,I)`, use B=aJ+bI and D=cJ+dI. If b!=0, B is invertible. If b=0, D is invertible and H=D^-1 B is nilpotent of index ell. Thus one chart is always available on each primary block even when no chart is invertible on the full pencil. + +In either chart H is a fractional linear function of J with nonzero determinant. Its inverse fractional expression is defined in K[J]. Hence `K[H]=K[J]`. The first coordinate vector v is cyclic for J and therefore for H. The matrix + +`S=[v,Hv,...,H^(k-1)v]` + +is invertible, where k is the block dimension. Then `S^-1 H S` is the companion matrix of the transformed monic primary polynomial. This gives a direct construction with no eigenvalue choice or extension-field embedding. + +In the finite chart take + +`P=S^-1 B^-1`, `Q=S^T`. + +The transformed block is `(I,S^-1 H S)`. In the infinity chart take `P=S^-1 D^-1`, `Q=S^T`; it is `(S^-1 H S,I)`. These formulas prove both literal identities, not only a determinant equality. The transformed primary degree and Jordan length are preserved, except that a linear finite primary can exchange with infinity. + +For a fixed R, normalize every regular block and compare the resulting multiset with the original regular multiset. Retain R exactly when the types and multiplicities match. Match equal blocks and apply the corresponding common row/column block permutation. Its determinant signs are part of the actual matrices. Combine these matrices with the credited singular slice lifts. This constructs a literal full-pencil stabilizer `(P_R,Q_R,R)` for every retained R. + +Conversely a full-pencil equivalence preserves its Kronecker types. This also follows from the Hom decomposition below: singular types remain singular with the same indices, while the regular diagonal must be a module isomorphism with equal primary lengths and multiplicities. Thus a rejected regular multiset cannot be repaired by singular/regular mixing. The retained R are exactly the possible slice actions. Let their explicit lift determinants be `(p_R,q_R,z_R)`. + +## 3. All fixed-slice mixing and its determinant image + +Set `C=Q^-T`. A fixed-slice stabilizer is precisely an automorphism satisfying `P A_i=A_i C` for both i. + +The singular Hom table from PR5683 is retained: right-to-right dimension max(e-f+1,0), left-to-left dimension max(f-e+1,0), right-to-left zero, and left-to-right dimension e+f. Its scalar recurrences include zero indices. + +For one finite regular block `(I,M)` of dimension k, comparison of the two coefficients gives: + +| Source | Destination | Hom dimension | +| --- | --- | ---: | +| R_e | regular | 0 | +| regular | R_e | k | +| regular | L_e | 0 | +| L_e | regular | k | + +For regular to R_e, the second matrix has rows `u,uM,...,uM^e`; the first consists of its first e rows. The row u is arbitrary. For L_e to regular, the first matrix has columns `v,Mv,...,M^e v`; the second consists of its first e columns. The column v is arbitrary. In the two zero directions, a zero boundary row or column propagates across the recurrence and forces every entry to zero. These formulas include e=0. Exchanging the two slices and using the singular slice lift proves the same statements for an infinity primary. Multiplicities give arbitrary matrices between multiplicity spaces. + +Order right types by increasing index, then all regular types, then left types by decreasing index. The full morphism is upper triangular between these three groups. Thus all regular/singular and singular inter-type mixing is included and has no effect on either determinant. + +Within the regular group, different projective primary points have zero Hom. For finite primaries this is the usual Bezout argument for relatively prime polynomials. For finite versus infinity, one equation gives U=M U N with N nilpotent, and iteration forces U=0. Infinity versus finite is the transpose argument. + +For one finite irreducible f of degree d, the regular module is + +`direct_sum_ell (K[X]/f^ell)^(r_ell)`. + +The filtration by powers of f has residue field E=K[X]/f. The exact-length-ell diagonal multiplicity map D_ell appears on ell successive layers. Maps between different lengths are triangular on each layer. Therefore + +`det_K P_regular = product_(f,ell) Norm_(E/K)(det_E D_(f,ell))^ell`. + +The same formula for infinity uses E=K. Each residue norm is onto K*. Conversely multiplication on one selected block by a unit lifting any residue element realizes that norm to the ell-th power. This is the credited classical centralizer theorem from PR5250, now applied separately at every projective primary point. Since Q=P^-T for this diagonal regular group, its determinant pairs are exactly `(h,h^-1)`, with + +`h in (K*)^g`, `g=gcd(all regular block lengths)`. + +The residue degree and the multiplicity do not replace the block length in g. + +For each distinct right singular index e, its multiplicity determinant gives `(u^e,u^(-e-1))`; for each left index it gives `(u^(-e-1),u^e)`. This uses the transposed parameter convention of PR5683. All u in K* occur. Hence the complete fixed-slice image F is the subgroup of `(K*)^2` generated by + +`(u^e,u^(-e-1))` for every right type, + +`(u^(-e-1),u^e)` for every left type, + +`(u^ell,u^-ell)` for every regular block length, + +for all u in K*. Repeated copies do not add generators. No block-diagonal assumption is used in the upper bound: the full Hom analysis gives it. + +For a mixed model with at least one singular type, choose its primitive vector v0 and the primitive row eta annihilating it as in PR5683. Then F is equivalently the condition + +`x^eta1 y^eta2 in (K*)^d`, + +where d is the gcd of all singular values `eta dot v_i` and all regular lengths. This follows because eta1-eta2 is 1 or -1. It explains why a regular semisimple block removes the row/column obstruction, while a length-two regular block need not do so. + +## 4. Complete image, labels and literal correction + +**Theorem.** For the supplied model over F_q, + +`Delta = union_(retained R) {(p_R x,q_R y,z_R) : (x,y) in F}`. (1) + +For necessity, divide any stabilizer by the constructed lift with its exact slice action R. The quotient fixes the slices, so its determinants lie in F by section 3. For sufficiency, compose the lift with a fixed-slice witness. This proves (1), attainment and independence from all block-matching choices. Different R with the same determinant can give different cosets. The algorithm must keep that union; it cannot choose one arbitrary representative per determinant. + +The ambient determinant map from `GL_m x GL_n x GL_2` onto `(K*)^3` is surjective because m,n>0. Its kernel is the product of the three special linear groups. Thus the SL orbits in the GL orbit are exactly `(K*)^3/Delta`. The executable returns the smallest triple in each finite coset as its label. Their number is `(q-1)^3/|Delta|`. + +If a supplied GL map g has determinant triple in Delta, take the literal stabilizer h with the same triple. Then `g h^-1` has three determinant-one factors and the same tensor image as g. A prescribed slice action can be requested only when its particular coset admits the triple; global membership does not imply membership for every R of the same determinant. + +A supplied change of coordinates to the model conjugates the stabilizer. Conjugation leaves all three determinants fixed. The formula therefore applies to any pencil with that supplied decomposition and checked factor maps. It does not discover those maps. + +## 5. A closed family with no invertible rational slice + +Take one length-ell Jordan primary at every point of P1(F_q), with common multiplicity r. Every rational slice is singular, but the homogeneous determinant polynomial is a nonzero scalar multiple of + +`(s^q t-s t^q)^(r ell)`. + +Thus the pencil is regular. Every GL2 action permutes these equally weighted primary types and is admitted. Write `H=(K*)^ell`. Then the exact character image is + +`Delta = {(x,y,z): x in H and x*y*z^(r ell)=1}`. (2) + +In particular y is also in H. There are exactly `(q-1)*gcd(q-1,ell)` SL orbits. For ell=1 this gives q-1, including the binary diag(s,t,s+t) case. For F5 with ell=2 there are eight, not four. For F4 with ell=3 there are nine. + +Here is the extra determinant argument needed for nonsemisimple lengths. The fixed-slice first determinant group is H. Therefore `R -> p_R mod H` is a group homomorphism. Every elementary unipotent in SL2 has p-power order, where p is the characteristic; K*/H has order prime to p. SL2 is generated by those elementary matrices, so its image is trivial. + +It remains to evaluate `R=diag(z,1)`. On each of the q finite primary blocks, the cyclic basis is diagonal with entries `1,z^-1,...,z^(-(ell-1))`. Its P determinant is `z^(ell(ell-3)/2)`. On infinity it is `z^(-ell(ell-1)/2)`. The common block permutation has a sign raised to r ell, which lies in H. The total exponent is + +`r*((q-1)*ell*(ell-3)/2-ell)`. + +Since ell(ell-3)/2 is an integer and z^(q-1)=1, this is an ell-th power. Hence p_R lies in H for every R. Conversely all x in H can be supplied by the regular fixed-slice group. Finally, `s^q t-s t^q` transforms by det R, so determinants of the pencil identity force `xy=z^(-r ell)`. This proves (2). A determinant-polynomial comparison alone would miss the condition x in H. + +## 6. Algorithm and cost boundary + +For fixed q and a supplied complete model, equation (1) gives deterministic polynomial-time image and label extraction in the total factor dimensions. Enumerate the fewer than q^4 matrices in GL2, normalize each companion block by matrix arithmetic, match its exact transformed companion polynomial, and compute F from the displayed exponent generators in the at most (q-1)^2-element group. No large matrix stabilizer is enumerated. The quotient has at most (q-1)^3 elements. The exact polynomial exponent is not optimized. + +The singular witnesses use the credited characteristic-safe symmetric powers. A regular witness needs a residue element of a specified norm. Existence is proved above. Uniform sampling in the finite residue field gives an exact Las Vegas construction: test the norm and accept only the required value. Its expected trial count is at most q, and each trial has polynomial field-operation cost. Deterministic enumeration also terminates, but no polynomial bound is claimed for that norm search in unbounded residue degree. The bounded executable enumerates residues of degree at most three. It does not implement the randomized general solver or claim polynomial complexity in log(q). + +The finite verifier uses F2/F3/F4/F5, singular indices 0..5, regular lengths 1..3, residue degrees 1..3, multiplicities 1..3, and total dimensions at most sixteen. Its declared models cover strict subdomains of those bounds; it does not enumerate every admissible model. The written theorem has no such dimension, length, degree or field-size restriction. + +A separate coefficient-equation oracle imports no lift or character formula. For each declared slice action it solves all `P B_i=A_i C` equations, enumerates every vector in that solution space, and retains exactly invertible P,C. Large fixtures explicitly mark a selected action set; the other fixtures cover all GL2. Literal witnesses cover every admitted GL2 action in every declared model. Malformed inputs, wrong determinant restrictions and corrupt literal maps reject. + +## 7. Use, limits and credit + +This completes the determinant-character interface for supplied finite-field pencil models, including nonsplit primary factors, all Jordan lengths, infinity, both singular orientations and zero indices. It resolves the missing global-slice premise in PR5250 and the regular/singular coupling question from PR5672/5683. It is not an arbitrary-tensor recognizer, a general tensor-atlas solution, a proof-assistant certificate or independent human acceptance. + +A multiplication use still needs a concrete native producer and consumer. Native maps, dirty ownership, movement, restoration, storage, precision, repeated preparation and the complete recursive bill remain unknown. They are not free. No new kappa or selected-frontier change follows from this algebraic result. + +Ali Romman with substantial OpenAI Codex assistance. Credit Nick Petalas PR5250 and its Arne Storjohann and Ferrer/Mingueza/Montoro lineage; apoursh PR5672; Ali Romman PR5683; David Ganz A030/A026/A029; and classical Kronecker, companion-matrix and finite-field norm theory. Original source notices remain under source/. The new assembly and checks are Apache-2.0. Global literature priority is unclaimed. diff --git a/research/raw-pencil-sl-transport/vendor/characters/pencils.py b/research/raw-pencil-sl-transport/vendor/characters/pencils.py new file mode 100644 index 0000000000..45c52fbee6 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/pencils.py @@ -0,0 +1,280 @@ +"""Exact determinant maps for bounded supplied finite-field pencil models. + +Credit the retained Kronecker lifts and field arithmetic. The regular block +normalization and mixed character assembly are new in this package. +Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. +""" +from hashlib import sha256 +from itertools import product +from pathlib import Path +import importlib.util +import json + +ROOT = Path(__file__).resolve().parent +for item in json.loads((ROOT / 'INPUTS.json').read_text()): + if sha256((ROOT / item['local']).read_bytes()).hexdigest() != item['sha256']: + raise ValueError('Frozen source differs: ' + item['local']) +spec = importlib.util.spec_from_file_location('credited_pencil', ROOT / 'source/pencil.py') +old = importlib.util.module_from_spec(spec) +spec.loader.exec_module(old) +Field = old.Field +need = old.require + + +def poly_mul(a, b, f): + out = [0] * (len(a) + len(b) - 1) + for i, x in enumerate(a): + for j, y in enumerate(b): + out[i+j] = f.add(out[i+j], f.mul(x, y)) + return out + + +def poly_power(a, n, f): + out = [1] + for _ in range(n): + out = poly_mul(out, a, f) + return out + + +def remainder(a, b, f): + a = list(a) + while len(a) >= len(b): + x = f.mul(a[-1], f.inv(b[-1])); offset = len(a)-len(b) + for j, y in enumerate(b): + a[offset+j] = f.sub(a[offset+j], f.mul(x, y)) + a.pop() + return a + + +def irreducible(a, f): + for degree in range(1, (len(a)-1)//2+1): + for low in product(range(f.q), repeat=degree): + if not any(remainder(a, list(low)+[1], f)): + return False + return True + + +def companion(poly, f): + n = len(poly)-1 + out = [[0]*n for _ in range(n)] + for i in range(1, n): + out[i][i-1] = 1 + for i in range(n): + out[i][-1] = f.neg(poly[i]) + return out + + +def matrix_sum(a, b, x, y, f): + return [[f.add(f.mul(x, u), f.mul(y, v)) for u, v in zip(row, other)] + for row, other in zip(a, b)] + + +def evaluate(poly, matrix, f): + n = len(matrix); out = [[0]*n for _ in range(n)]; power = old.identity(n) + for coefficient in poly: + out = matrix_sum(out, power, 1, coefficient, f) + power = old.multiply(power, matrix, f) + return out + + +def normalized(model, f): + need(isinstance(model, (list, tuple)) and model, 'Nonempty supplied model') + out = []; total_m = total_n = 0; keys = set() + for block in model: + need(isinstance(block, (list, tuple)) and block, 'Block record') + side = block[0] + if side in ('R', 'L'): + need(len(block) == 3, 'Singular record arity') + _, e, r = block + need(type(e) is int and 0 <= e <= 5 and type(r) is int and 1 <= r <= 3, 'Singular bounds') + key = (side, e); m = (e+(side == 'L'))*r; n = (e+(side == 'R'))*r + out.append(dict(side=side, e=e, r=r, m=m, n=n, row=total_m, col=total_n, key=key)) + else: + need(side in ('F', 'I'), 'Known block type') + need(len(block) == (4 if side == 'F' else 3), 'Regular record arity') + if side == 'F': + _, poly, length, r = block + need(isinstance(poly, (tuple, list)) and 2 <= len(poly) <= 4 and poly[-1] == 1 and + all(type(x) is int and 0 <= x < f.q for x in poly), 'Monic bounded polynomial') + need(irreducible(poly, f), 'Irreducible regular primary') + poly = tuple(poly) + else: + _, length, r = block; poly = (0, 1) + need(type(length) is int and 1 <= length <= 3 and type(r) is int and 1 <= r <= 3, 'Regular bounds') + key = (side, poly, length); degree = (len(poly)-1)*length + m = n = degree*r + out.append(dict(side=side, poly=poly, length=length, r=r, degree=degree, + m=m, n=n, row=total_m, col=total_n, key=key)) + need(key not in keys, 'Combine identical block types in the supplied model') + keys.add(key); total_m += m; total_n += n + need(0 < total_m <= 16 and 0 < total_n <= 16, 'Positive total dimensions at most sixteen') + return out, total_m, total_n + + +def regular_instances(parts, f): + out = [] + for part in parts: + if part['side'] in ('F', 'I'): + poly = poly_power(part['poly'], part['length'], f) + j = companion(poly, f); identity = old.identity(len(j)) + a, b = (identity, j) if part['side'] == 'F' else (j, identity) + key = (part['side'], tuple(poly)) + for i in range(part['r']): + out.append(dict(a=a, b=b, key=key, part=part, row=part['row']+i*len(j), col=part['col']+i*len(j))) + return out + + +def put(matrix, block, row, col): + for i, values in enumerate(block): + matrix[row+i][col:col+len(values)] = values + + +def slices(parts, m, n, f): + a = [[0]*n for _ in range(m)]; b = [[0]*n for _ in range(m)] + for part in parts: + if part['side'] in ('R', 'L'): + for i in range(part['e']): + for j in range(part['r']): + x = part['row']+i*part['r']+j; y = part['col']+i*part['r']+j + a[x][y] = 1 + if part['side'] == 'R': b[x][y+part['r']] = 1 + else: b[x+part['r']][y] = 1 + for item in regular_instances(parts, f): + put(a, item['a'], item['row'], item['col']); put(b, item['b'], item['row'], item['col']) + return a, b + + +def singular_lift(part, action, determinant, f): + d = old.identity(part['r']); d[0][0] = determinant + if part['e']: p, q, _ = old.lift(part['e'], part['r'], action, d, f) + else: p, q = [], old.transpose(old.inverse(d, f)) + return (q, p) if part['side'] == 'L' else (p, q) + + +def cyclic_normalize(a, b, action, f): + """Use one primary block's affine chart and its cyclic vector.""" + first = matrix_sum(a, b, *action[0], f); second = matrix_sum(a, b, *action[1], f) + finite = old.determinant(first, f) != 0 + base, other = (first, second) if finite else (second, first) + need(old.determinant(base, f) != 0, 'A regular primary block has an invertible chart') + inverse = old.inverse(base, f); h = old.multiply(inverse, other, f); n = len(h) + v = [[int(i == 0)] for i in range(n)]; columns = [] + for _ in range(n): + columns.append([row[0] for row in v]); v = old.multiply(h, v, f) + krylov = old.transpose(columns); need(old.determinant(krylov, f) != 0, 'The fractional transform keeps the cyclic vector') + ki = old.inverse(krylov, f); canonical = old.multiply(old.multiply(ki, h, f), krylov, f) + poly = tuple(f.neg(row[-1]) for row in canonical)+(1,) + need(canonical == companion(poly, f), 'Literal companion normalization') + if not finite: need(poly == (0,)*n+(1,), 'The infinity chart is nilpotent') + return ('F' if finite else 'I', poly), old.multiply(ki, inverse, f), old.transpose(krylov) + + +def slice_lift(parts, m, n, action, f): + ps = [[0]*m for _ in range(m)]; qs = [[0]*n for _ in range(n)] + for part in parts: + if part['side'] in ('R', 'L'): + p, q = singular_lift(part, action, 1, f) + put(ps, p, part['row'], part['row']); put(qs, q, part['col'], part['col']) + instances = regular_instances(parts, f); unused = set(range(len(instances))) + for source in instances: + key, p, q = cyclic_normalize(source['a'], source['b'], action, f) + target = next((i for i in sorted(unused) if instances[i]['key'] == key), None) + if target is None: return None + unused.remove(target); dest = instances[target] + put(ps, p, dest['row'], source['row']); put(qs, q, dest['col'], source['col']) + return ps, qs, action + + +def norm_unit(poly, target, f): + """Bounded exhaustive residue search; no general fast norm solver is claimed.""" + small = companion(poly, f) + for coefficients in product(range(f.q), repeat=len(poly)-1): + if old.determinant(evaluate(coefficients, small, f), f) == target: + return coefficients + raise ValueError('Finite field norm must be onto') + + +def fixed_generators(parts, m, n, f): + out = [] + for part in parts: + for u in range(1, f.q): + p, q = old.identity(m), old.identity(n) + if part['side'] in ('R', 'L'): + bp, bq = singular_lift(part, old.identity(2), u, f) + else: + poly = poly_power(part['poly'], part['length'], f); j = companion(poly, f) + coefficients = norm_unit(part['poly'], u, f) if part['side'] == 'F' else [u] + bp = evaluate(coefficients, j, f); bq = old.transpose(old.inverse(bp, f)) + need(old.determinant(bp, f) == f.power(u, part['length']), 'Norm and length determinant') + put(p, bp, part['row'], part['row']); put(q, bq, part['col'], part['col']) + out.append((p, q)) + return out + + +def pair_mul(a, b, f): + return tuple(f.mul(x, y) for x, y in zip(a, b)) + + +def compile_model(model, f): + parts, m, n = normalized(model, f); a, b = slices(parts, m, n, f) + fixed = {(1, 1): (old.identity(m), old.identity(n))}; queue = [(1, 1)] + generators = [(tuple(old.determinant(x, f) for x in pair), pair) for pair in fixed_generators(parts, m, n, f)] + for key in queue: + for char, pair in generators: + target = pair_mul(key, char, f) + if target not in fixed: + fixed[target] = tuple(old.multiply(x, y, f) for x, y in zip(fixed[key], pair)); queue.append(target) + image = {}; lifts = []; actions = 0 + for action in old.general_linear_two(f): + actions += 1; lift = slice_lift(parts, m, n, action, f) + if lift is None: continue + need(old.fixes(a, b, lift, f), 'Literal regular and singular slice lift') + char = tuple(old.determinant(x, f) for x in lift); lifts.append((char, lift)) + for key, pair in fixed.items(): + triple = pair_mul(char, key+(1,), f) + image.setdefault(triple, (pair, lift)) + return dict(model=model, parts=parts, dimensions=(m, n), slices=(a, b), fixed=fixed, lifts=lifts, + image=image, slice_actions=actions, field=f) + + +def witness(compiled, triple, action=None): + f = compiled['field']; triple = tuple(triple) + need(len(triple) == 3 and all(type(x) is int and 0 < x < f.q for x in triple), 'Nonzero determinant triple') + need(triple in compiled['image'], 'Excluded determinant triple') + pair, lift = compiled['image'][triple] + if action is not None: + choices = [(char, candidate) for char, candidate in compiled['lifts'] if candidate[2] == action] + need(choices, 'Excluded prescribed slice action') + char, lift = choices[0] + need(char[2] == triple[2], 'Prescribed slice determinant') + key = tuple(f.mul(x, f.inv(y)) for x, y in zip(triple[:2], char[:2])) + need(key in compiled['fixed'], 'Excluded prescribed slice coset') + pair = compiled['fixed'][key] + result = tuple(old.multiply(x, y, f) for x, y in zip(pair, lift[:2]))+(lift[2],) + need(old.fixes(*compiled['slices'], result, f), 'Literal determinant witness') + need(tuple(old.determinant(x, f) for x in result) == triple, 'Requested determinant witness') + return result + + +def tensor_image(slices, maps, f): + a, b = slices; p, q, action = maps + return tuple(old.multiply(old.multiply(p, matrix_sum(a, b, x, y, f), f), old.transpose(q), f) for x, y in action) + + +def correct_map(compiled, maps): + f = compiled['field']; triple = tuple(old.determinant(x, f) for x in maps) + h = witness(compiled, triple) + result = tuple(old.multiply(g, old.inverse(x, f), f) for g, x in zip(maps, h)) + need(all(old.determinant(x, f) == 1 for x in result), 'Three determinant-one factors') + need(tensor_image(compiled['slices'], maps, f) == tensor_image(compiled['slices'], result, f), 'Unchanged tensor image') + return result + + +def orbit_labels(compiled): + f = compiled['field']; labels = {} + for triple in product(range(1, f.q), repeat=3): + if triple not in labels: + for delta in compiled['image']: + labels[pair_mul(triple, delta, f)] = triple + need(len(labels) == (f.q-1)**3 and len(set(labels.values()))*len(compiled['image']) == len(labels), 'Finite quotient cardinality') + return labels diff --git a/research/raw-pencil-sl-transport/vendor/characters/source/REGULAR.md b/research/raw-pencil-sl-transport/vendor/characters/source/REGULAR.md new file mode 100644 index 0000000000..20f8262d37 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/source/REGULAR.md @@ -0,0 +1,221 @@ +# Exact determinant images for invertible-slice matrix pencils + +This contribution was produced by Nick Petalas. Apache-2.0. + +**Claim type: scoped written proof with exact finite corroboration.** +For every fixed finite field, the stabilizer determinant image of a square +matrix-pencil tensor with an invertible slice has an explicit formula and a +deterministic polynomial-time extraction algorithm. This settles that subclass +of David Ganz's [atlas A030](../pure-math-atlas-400/volumes/01-algebra.md#a030), +from [PR #2849](https://github.com/CrocSwap/integer-mult-bounds/pull/2849). +The general arbitrary-tensor proposal remains open. No new kappa, physical +supplier, selected-frontier change or complete multiplication theorem is claimed. +Global literature priority is unclaimed. + +The new step is the complete determinant-coset assembly over the slice actions, +including the similarity witness's determinant. Frobenius canonical forms, +centralizer structure and the atlas's character compression are predecessors. +The centralizer identity below is classical; it is not claimed as a new theorem +or offered as an audit of its authors. + +## Convention and theorem + +Let K=F_q, n>=1 and M in Mat_n(K). The tensor has ordered matrix slices (I,M), +with action + +```text +(P,Q,R): (I,M) -> (P(aI+bM)Q^T, P(cI+dM)Q^T), +R = [[a,b],[c,d]] in GL_2(K), P,Q in GL_n(K). +``` + +Write Delta_M for the image of its stabilizer under +`(P,Q,R) -> (det P, det Q, det R)`. +For each monic irreducible f, write the K[t]-module associated to M as + +```text +V_f = direct sum over e>=1 of (K[t]/f^e)^(m_f,e). +g = gcd(q-1, every e for which some m_f,e > 0). +H = {x^g : x in K*}. +``` + +For each R in GL_2(K), put B_R=aI+bM. Retain R precisely when B_R is invertible +and `N_R=(cI+dM) B_R^-1` is similar to M. Choose any P_R such that +`P_R N_R P_R^-1=M`, and set z_R=det P_R and b_R=det B_R. Then + +```text +Delta_M = union over retained R of + {(z_R h, (b_R z_R h)^-1, det R) : h in H}. (1) +``` + +Every triple on the right occurs, and no others occur. The answer is independent +of the choices of P_R. Scalar M and linearly dependent slices are included. +If an invertible slice exists but is not first, a search of the q+1 slice +directions finds one and a GL_2 action puts it first. For slices (A0,A1) with +A0 invertible, use M=A0^-1 A1. Normalization +is a GL tensor action. Conjugation of the stabilizer preserves each determinant, +so (1) gives the same determinant image in the original coordinates. + +## Proof + +The first stabilizer equation forces B_R invertible and +`Q^T=B_R^-1 P^-1`. Substitution into the second gives +`P N_R P^-1=M`. Conversely those two conditions and that definition of Q satisfy +both original equations. Thus retained R are exactly the feasible slice actions. +All admissible P for one retained R are `C P_R`, where C is an invertible +centralizer of M. Their determinants are exactly `z_R det(C)`. Taking the +determinant of the forced Q gives the second entry of (1). + +It remains to identify `det(C_GL_n(K)(M))` as H. Here are the module details, +including nonsplit primary factors. Distinct f-primary summands have no +intertwiners, by Bezout's identity, so their determinants multiply independently. +Fix f of degree d, put E=K[t]/f, and filter V_f by powers of f. Each quotient +`f^(k-1)V_f/f^k V_f` is an E-vector space with one group of m_f,e coordinates +for each e>=k. An intertwiner from a length-s summand to a length-e summand +has image divisible by `f^max(e-s,0)`. Consequently its induced matrix on +that quotient is triangular when the summands are ordered by length. Its +exact-length-e diagonal matrix U_f,e over E is the same on every layer k<=e. +Invertibility forces every U_f,e invertible. Multiplicativity of determinant +along this invariant filtration therefore gives + +```text +det_K C = product over f,e of Norm_(E/K)(det_E U_f,e)^e. (2) +``` + +For the reverse inclusion, choose one copy of K[t]/f^e and multiply it by any +unit lifting u in E*. This commutes with M, fixes the other copies, and has +K-determinant `Norm_(E/K)(u)^e`. The norm on finite fields is surjective: on +cyclic E* it is the power `(q^d-1)/(q-1)`, with image of order q-1. Hence the +centralizer determinant image contains every e-th power in K*. Equation (2) +gives the reverse containment in the subgroup generated by those powers. +Cyclicity of K* identifies that subgroup with H. This proves (1) and its +attainment statement. A different P_R differs by a centralizer element, so +it changes z_R only by an element of H. + +The Jordan/Weyr version of (2) is classical. See Josep Ferrer, David Mingueza +and M. Eulalia Montoro, *Determinant of any matrix that belongs to Z(J)*, +[EACA 2014, Theorem 4.3, printed pages 111-114](https://www.maia.ub.edu/~sombra/publications/EACA2014/2014_EACA_Conference_Proceedings.pdf#page=113). +The filtration above explains the finite-field norm needed here. + +## Deterministic extraction for each fixed q + +1. Compute a Frobenius form of M with its transformation matrix. This is a + deterministic polynomial-time subroutine over arbitrary fields, due to + [Arne Storjohann, FOCS 2001](https://doi.org/10.1109/SFCS.2001.959911). + The [Pernet-Storjohann primary paper, introduction](https://cs.uwaterloo.ca/~astorjoh/cpoly.pdf) + also records the deterministic result; its separate randomized large-field + algorithm is not the premise used here. +2. Squarefree-decompose each invariant-factor polynomial h of M and take the + gcd of q-1 and every multiplicity that occurs. This computes g without + irreducible factorization. Indeed those multiplicities are exactly the + elementary-divisor exponents appearing in h. Derivatives and polynomial + gcds separate unequal multiplicities. When a residual derivative vanishes, + take its characteristic-p-th root and multiply subsequent multiplicities + by p. Finite fields are perfect. Each such root lowers the positive degree, + so this procedure uses polynomially many field operations for fixed q. +3. Enumerate GL_2(K), at most q^4 matrices. Form B_R and N_R. Compare Frobenius + forms, and obtain P_R from their transformation matrices when they agree. + For `S_M^-1 M S_M = S_N^-1 N_R S_N`, take `P_R=S_M S_N^-1`. +4. Evaluate (1). At most `|GL_2(K)| |H|` triples are inserted. For fixed q + this is constant output size, independent of n. The algorithm enumerates + neither GL_n(K) nor the centralizer's units nor the tensor stabilizer. +5. If A030's equation-table output is wanted, enumerate the at most `(q-1)^3` + monomial characters and retain those equal to one on every output triple. + Their common kernel is Delta_M, by finite abelian duality. The annihilator + is generated by at most three characters, as in atlas A026/A029, so choose + a generating triple by a constant-size search and pad with zero rows. + +These steps prove deterministic polynomial time in n for each fixed q. They +make no uniform polynomial-in-log(q) claim. The general-size Frobenius and +squarefree-decomposition implementations are not supplied or benchmarked here; +they are established subroutines in this written reduction. The executable +below is an independent finite corroborator, not that polynomial-time program. + +## First discriminator and bounded evidence + +For `M=[[0,1],[0,0]]` over F3, g=2 and H={1}. The retained R have c=0 and +nonzero a,d. One may take `P_R=diag(a/d,1)`, giving z_R=a/d and b_R=a^2. +Equation (1) yields exactly + +```text +Delta_M = {(1,1,1), (2,2,2)}. +``` + +Replacing H by all of F3* or omitting z_R gives a different answer. Both are +explicit rejection controls in the verifier. + +The verifier uses no predecessor executable or external package. It enumerates +every P,Q,R literally on every 2-by-2 matrix M over F2 and F3, and compares +that determinant image with a separately implemented version of (1). + +- F2: 16 slices, 3,456 literal triples tested, 96 stabilizers. +- F3: 81 slices, 8,957,952 literal triples tested, 6,912 stabilizers. The image + sizes are 2 on 24 slices, 4 on 3 slices, and 8 on 54 slices. +- Eleven independent centralizer fixtures include repeated unequal block + lengths, coprime block-length gcd, scalar matrices, and nonsplit irreducible + degree-two blocks with exponents one and two. Their centralizer vector spaces + are enumerated exactly; the largest has 19,683 elements. + +These are finite corroboration of the written proof, not an exhaustive check +of all fields or dimensions. The centralizer checks support this new formula; +re-checking a predecessor result is not the deliverable. + +## Reproduce + +From the repository root, using CPython 3.12 and its standard library: + +```sh +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -B research/pencil-determinant-image/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -O -W error -B research/pencil-determinant-image/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/research_package.py --package research/pencil-determinant-image +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/check_research_commit.py --package research/pencil-determinant-image --check-source-history +``` + +Any CPython 3.12 interpreter path may replace the absolute path. The direct +marker is `PASS_PENCIL_DETERMINANT_IMAGE fields=2,3 tensor_slices=97 controls=2`. +A generated JSON receipt binds the five package files and exact enumerated +results. The program writes no files, uses explicit checks that survive `-O`, +and needs no Git for direct replay. Each registered command has a 120-second +limit; local replay is below five seconds on the recorded environment. + +## Scope, engineering and credit + +The result requires a square pencil and an invertible slice over K. It does +not cover singular Kronecker blocks or regular pencils without a K-rational +invertible slice. The general arbitrary-tensor extraction proposal, transporter +height bounds and GL-to-SL compilation remain separate questions. There is no +physical access, dirty-state, routing, precision, recursive-invoice or supplier +admission result. Independent human and formal proof-kernel review are unclaimed. +No Lean build, selected cold replay or complete multiplication theorem was run. + +This package changes the formal-interface-lemma card to a mathematical tensor +side question explicitly left open in the atlas. It does not formalize a Lean +statement or resolve a selected-supplier hypothesis. Exact historical card and +source pins are in SOURCES.json; they are provenance, not live replay inputs. + +Engineering uses a fixed finite domain, pure arithmetic functions and explicit +invariant failures. Each loop has a finite bound from those fixtures; centralizer +enumeration enforces a 25,000-element cap before allocating combinations. No +function exceeds 60 lines. Python's managed allocation is a Power-of-Ten rule-3 +deviation: matrix tables have at most 81 entries per axis, module dimension is +at most five, and at most 19,683 centralizer candidates are generated one at a +time. Static inspection and both registered replays check these bounds. A future +CLI accepting general inputs must introduce explicit input/resource bounds before +reusing this finite verifier. No compiler diagnostics exist for this Python file; +warning-strict normal and optimized execution are the applicable checks. + +David Ganz retains credit for atlas A030, the determinant-image formulation, +A026/A029 and the atlas's cited tensor/stabilizer lineage. Arne Storjohann and +the cited canonical-form authors retain their algorithm credit. Ferrer, Mingueza +and Montoro retain the classical centralizer determinant credit. Only the +restricted extraction reduction and exact image assembly are claimed here. + +## Open next questions + +- Extend the determinant-image assembly to regular square pencils having no + invertible K-rational slice. The binary homogeneous elementary divisors offer + a first step; the missing issue is a coordinate-independent replacement for + B_R inverse. This would remove the rational-slice restriction. +- Handle singular Kronecker blocks and rectangular pencils. Begin with the + determinant characters of one left/right minimal-index block and its + multiplicity space. Couplings between block types and slice transformations + remain the obstruction to extending this proof. diff --git a/research/raw-pencil-sl-transport/vendor/characters/source/SINGULAR.md b/research/raw-pencil-sl-transport/vendor/characters/source/SINGULAR.md new file mode 100644 index 0000000000..9de07b6280 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/source/SINGULAR.md @@ -0,0 +1,146 @@ +# Determinant characters for all purely singular Kronecker sums + +## 1. Scope and action + +Let K be any field. Let R_e be the e by e+1 pencil with s on the diagonal and t above it, and let L_e=R_e^T be its left orientation. The predecessor calls the right block L_e; this note uses R and L to mark the two orientations. Minimal indices e can be zero. Thus R_0 has shape 0 by 1 and L_0 has shape 1 by 0. + +Let T be a finite direct sum of these blocks with positive multiplicities. Combine repeated equal types. Both total row and column dimensions m,n must be positive. The result does not include a regular block. The model is supplied; extraction from an arbitrary tensor is a separate task. + +Use exactly the predecessor's covariant action + +`(A0,A1) -> (P(a A0+b A1)Q^T, P(c A0+d A1)Q^T)`, + +where `R=[[a,b],[c,d]]` is the slice factor. Let Delta(T) be the image of its stabilizer under `(det P,det Q,det R)`. The right factor is Q^T, not Q^-1. All pencil equations are coefficient identities in two independent indeterminates, including over finite fields. + +The source is apoursh PR5672 at `81c0577b83cdafa73346da8ade1261b0b202e45f`, following Nick Petalas PR5250. Its single-type theorem, characteristic-safe slice lift and exact action convention remain predecessor work. This note supplies the complete mixed singular extension. + +## 2. Explicit intertwiner spaces + +A morphism from a source block to a destination block is a pair U,C with + +`U T_source(s,t)=T_destination(s,t) C`. + +For a source with shape ms by ns and destination with shape md by nd, U has shape md by ms and C has shape nd by ns. Comparing the s and t coefficients gives the following complete table: + +| Source | Destination | Dimension | Form | +| --- | --- | ---: | --- | +| R_e | R_f | max(e-f+1,0) | Rectangular upper Toeplitz | +| L_e | L_f | max(f-e+1,0) | Transpose dual of the preceding row | +| R_e | L_f | 0 | Zero | +| L_e | R_f | e+f | Rectangular Hankel | + +Here are explicit bases and completeness arguments. For R_e to R_f with e>=f, choose coefficients a_0,...,a_(e-f). Put `C_(i,j)=a_(j-i)` for `0<=i<=f`, `0<=j<=e`, with coefficients outside that range zero. Use the same rule for U on `0<=i=0`. + +The gcd of an all-zero list is zero. Define + +`chi(x,y,z)=x^ell1 y^ell2 z^(-ell1 A-ell2 B)`. + +**Theorem.** For every field K, + +`Delta(T) = {(x,y,z) in (K*)^3 : chi(x,y,z) in (K*)^d}`. (2) + +Here `(K*)^0={1}`. This convention recovers the exact equality for a single distinct block type. + +For necessity, apply chi to (1). Its value is `product_i u_i^c_i`, which is a d-th power when d>0 and is one when d=0. + +For sufficiency with d>0, let `w^d=chi(x,y,z)`. Choose integer Bezout coefficients b_i with `sum_i b_i c_i=d`, and set `u_i=w^b_i`. Remove the slice shifts and these u_i contributions from x,y, leaving X,Y with `X^ell1 Y^ell2=1`. For either base orientation, `a=(XY)^-1` supplies exactly the residual pair through `a^v0`. Multiply a into u_0. Equation (1) and the explicit block lifts now construct the requested stabilizer. When d=0, start with every u_i=1 and make the same kernel correction. No root is then needed. + +Over an arbitrary field, membership in the power subgroup includes the existence of w; a constructive witness can take w as input. The theorem does not assume an algorithm that extracts arbitrary roots in K. The bounded finite-field executable finds w by enumerating the at most q-1 nonzero elements. + +The kernel correction is elementary. For a right base, `X^(e0+1)Y^e0=1` gives `(XY)^(-e0)=X` and `(XY)^(e0+1)=Y`. For a left base, exchange X and Y. These formulas include e0=0. + +The primitive vector v0 can be completed to an integral basis. Hence d is also the gcd of all two-by-two minors of the type vectors. These minors are, up to sign, + +- Differences of two right indices. +- Differences of two left indices. +- Sums e+f+1 for a right index e and a left index f. + +This is a direct criterion using the full type list. It is independent of multiplicities. Multiplicities still affect A,B and therefore the actual character label; they cannot be dropped from the slice shift. + +## 6. Special-linear orbit labels and constructive correction + +Because m,n are positive, the determinant map from `GL_m(K) x GL_n(K) x GL_2(K)` onto `(K*)^3` is surjective, with kernel the product of the three special linear groups. Its orbits inside one GL orbit are therefore the cosets of Delta(T). + +The map chi is surjective onto K*: for a right base use `(x,y,z)=(u,u^-1,1)`, and for a left base exchange x,y. Equation (2) gives a complete label group + +`K*/(K*)^d`. + +Over F_q, the exact number of special-linear orbits is + +`gcd(q-1,d)`, with `gcd(q-1,0)=q-1`. + +For example, consecutive right indices give d=1 and one SL orbit. R_1 plus L_1 has d=3 and gives three SL orbits over F4. R_1 plus L_2 has d=4 and gives four over F5. Zero-index factors are included whenever both full factor dimensions are positive. In particular, a sum of R_0 and L_0 is a zero pencil with full determinant image, as d=1 requires. + +If a supplied GL map g has determinant triple in Delta(T), choose the stabilizer witness h with that same triple. Then `g h^-1` has determinant one in every factor and has the same action on T as g. This gives a literal SL correction when the model and map are supplied. It does not discover a canonical model or a GL map from an arbitrary tensor. Equal labels similarly give an SL transporter between two supplied presentations by composing their maps and the appropriate stabilizer witness. + +## 7. Verification boundary and use + +The exact verifier checks the Hom formulas against literal coefficient equations for every ordered pair of orientations and indices zero through three over F2, F3, F4 and F5. It then solves the full mixed stabilizer equations in twelve declared domains, enumerates every vector in each resulting linear solution space, and retains precisely invertible P,C. It uses neither the character formula nor the symmetric-power lift in that oracle. Cases marked with all_slice_actions cover every GL2 action. The other cases cover one representative for every nonzero slice determinant, with every GL2 action separately checked by literal constructed lifts. + +The finite evidence supports the all-field proof. It is not an exhaustive enumeration over all indices, dimensions or fields. The executable restricts indices to zero through five, combined multiplicities to one through three, fields to F2/F3/F4/F5, and both total factor dimensions to at most sixteen. The written proof has no such bounds. + +This closes the supplied purely singular determinant-character interface in the tensor atlas. Native realization, dirty-state ownership, movement, restoration, storage, precision and the complete recursive cost remain unknown. Regular blocks, arbitrary-tensor extraction and a paid multiplication consumer are outside the result. No new kappa, selected-frontier change, human acceptance or proof-kernel verification is claimed. + +New proof and checks: Ali Romman with substantial OpenAI Codex assistance. Credit apoursh PR5672; Nick Petalas PR5250; David Ganz's A030/A026/A029 atlas and the classical Kronecker and symmetric-power lineage. The source notice and action conventions remain unchanged. diff --git a/research/raw-pencil-sl-transport/vendor/characters/source/oracle.py b/research/raw-pencil-sl-transport/vendor/characters/source/oracle.py new file mode 100644 index 0000000000..6535d1363e --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/source/oracle.py @@ -0,0 +1,71 @@ +"""Literal linear-equation oracle for mixed pencil stabilizers. + +No character formula, Hom recurrence or symmetric-power lift is used here. +The supplied field operations are shared exact arithmetic. +Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. +""" +from itertools import product + + +def nullspace(rows,columns,field): + a=[row[:]for row in rows];pivots=[];at=0 + for col in range(columns): + pivot=next((i for i in range(at,len(a))if a[i][col]),None) + if pivot is None:continue + a[at],a[pivot]=a[pivot],a[at];scale=field.inv(a[at][col]);a[at]=[field.mul(scale,x)for x in a[at]] + for i in range(len(a)): + if i!=at and a[i][col]: + scale=a[i][col];a[i]=[field.sub(x,field.mul(scale,y))for x,y in zip(a[i],a[at])] + pivots.append(col);at+=1 + out=[] + for free in sorted(set(range(columns))-set(pivots)): + v=[0]*columns;v[free]=1 + for i,p in enumerate(pivots):v[p]=field.neg(a[i][free]) + out.append(v) + return out + + +def equations(source,target,src_dims,dst_dims,field): + ms,ns=src_dims;md,nd=dst_dims;columns=md*ms+nd*ns;rows=[] + for a,b in zip(source,target): + for i in range(md): + for j in range(ns): + row=[0]*columns + for k in range(ms):row[i*ms+k]=a[k][j] + for k in range(nd):row[md*ms+k*ns+j]=field.neg(b[i][k]) + rows.append(row) + return rows,columns + + +def stabilizer_space(first,second,action,field): + m,n=len(first),len(first[0]);mixed=[] + for x,y in action:mixed.append([[field.add(field.mul(x,a),field.mul(y,b))for a,b in zip(row,other)]for row,other in zip(first,second)]) + rows,columns=equations(mixed,(first,second),(m,n),(m,n),field) + return nullspace(rows,columns,field) + + +def determinant(a,field): + """Row elimination for complete literal matrix domains.""" + rows=[row[:]for row in a];out=1 + for k in range(len(rows)): + pivot=next((i for i in range(k,len(rows))if rows[i][k]),None) + if pivot is None:return 0 + if pivot!=k:rows[k],rows[pivot]=rows[pivot],rows[k];out=field.neg(out) + diagonal=rows[k][k];out=field.mul(out,diagonal);inv=field.inv(diagonal) + for i in range(k+1,len(rows)): + factor=field.mul(rows[i][k],inv) + for j in range(k,len(rows)):rows[i][j]=field.sub(rows[i][j],field.mul(factor,rows[k][j])) + return out + + +def enumerate_space(basis,m,n,field,limit=60000): + if field.q**len(basis)>limit:raise ValueError('explicit oracle domain exceeds enumeration limit') + columns=m*m+n*n;image=set();invertible=0 + for coefficients in product(range(field.q),repeat=len(basis)): + v=[0]*columns + for a,row in zip(coefficients,basis): + if a:v=[field.add(x,field.mul(a,y))for x,y in zip(v,row)] + p=[v[i*m:(i+1)*m]for i in range(m)];offset=m*m;c=[v[offset+i*n:offset+(i+1)*n]for i in range(n)] + x,z=determinant(p,field),determinant(c,field) + if x and z:image.add((x,field.inv(z)));invertible+=1 + return image,invertible diff --git a/research/raw-pencil-sl-transport/vendor/characters/source/pencil.py b/research/raw-pencil-sl-transport/vendor/characters/source/pencil.py new file mode 100644 index 0000000000..6bc7fc076e --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/characters/source/pencil.py @@ -0,0 +1,195 @@ +"""Bounded exact witnesses for the written Kronecker determinant theorem. + +The implementation is deliberately limited to small fixtures; PROOF.md supplies +the arbitrary-field/dimension argument. apoursh with OpenAI Codex; Apache-2.0. +""" +from itertools import product + + +def require(ok, message): + if not ok: + raise ValueError(message) + + +class Field: + """F2, F3, F5, or F4=F2[w]/(w^2+w+1), encoded 0,1,w,w+1.""" + def __init__(self, order): + require(type(order) is int and order in (2, 3, 4, 5), 'unsupported field') + self.q = order + self.p = 2 if order == 4 else order + + def add(self, a, b): + return a ^ b if self.q == 4 else (a + b) % self.q + + def neg(self, a): + return a if self.q == 4 else -a % self.q + + def sub(self, a, b): + return self.add(a, self.neg(b)) + + def mul(self, a, b): + if self.q != 4: + return a * b % self.q + value = 0 + for bit in range(2): + if (b >> bit) & 1: + value ^= a << bit + return value ^ 7 if value & 4 else value + + def power(self, a, exponent): + if exponent < 0: + require(a != 0, 'inverse of zero') + exponent %= self.q - 1 + value = 1 + for _ in range(exponent): + value = self.mul(value, a) + return value + + def inv(self, a): + require(a != 0, 'inverse of zero') + return self.power(a, self.q - 2) + + +def identity(n): + return [[int(i == j) for j in range(n)] for i in range(n)] + + +def transpose(a): + return [list(row) for row in zip(*a)] + + +def multiply(a, b, field): + require(len(a[0]) == len(b), 'matrix dimension mismatch') + result = [[0] * len(b[0]) for _ in a] + for i, row in enumerate(a): + for k, value in enumerate(row): + if value: + for j, other in enumerate(b[k]): + result[i][j] = field.add(result[i][j], field.mul(value, other)) + return result + + +def mix(a, b, x, y, field): + return [[field.add(field.mul(x, u), field.mul(y, v)) + for u, v in zip(row, other)] for row, other in zip(a, b)] + + +def determinant(a, field): + rows = [row[:] for row in a] + result = 1 + for col in range(len(rows)): + pivot = next((i for i in range(col, len(rows)) if rows[i][col]), None) + if pivot is None: + return 0 + if pivot != col: + rows[col], rows[pivot] = rows[pivot], rows[col] + result = field.neg(result) + result = field.mul(result, rows[col][col]) + inv = field.inv(rows[col][col]) + for i in range(col + 1, len(rows)): + scale = field.mul(rows[i][col], inv) + rows[i] = [field.sub(x, field.mul(scale, y)) + for x, y in zip(rows[i], rows[col])] + return result + + +def inverse(a, field): + n = len(a) + rows = [row[:] + unit for row, unit in zip(a, identity(n))] + for col in range(n): + pivot = next((i for i in range(col, n) if rows[i][col]), None) + require(pivot is not None, 'singular matrix') + rows[col], rows[pivot] = rows[pivot], rows[col] + inv = field.inv(rows[col][col]) + rows[col] = [field.mul(inv, value) for value in rows[col]] + for i in range(n): + if i != col: + scale = rows[i][col] + rows[i] = [field.sub(x, field.mul(scale, y)) + for x, y in zip(rows[i], rows[col])] + return [row[n:] for row in rows] + + +def tensor(a, b, field): + return [[field.mul(x, y) for x in row for y in other] + for row in a for other in b] + + +def slices(e, r): + require(type(e) is int and type(r) is int and 1 <= e <= 5 and 1 <= r <= 3, + 'outside bounded positive-index fixture domain') + return ([[int(j == i) for j in range((e + 1) * r)] for i in range(e * r)], + [[int(j == i + r) for j in range((e + 1) * r)] for i in range(e * r)]) + + +def symmetric_power(k, action, field): + """Ordinary monomial substitution, using convolution without factorials.""" + require(type(k) is int and 0 <= k <= 5, 'unsupported degree') + columns = [] + for i in range(k + 1): + coefficients = [1] + for linear in [action[0]] * (k - i) + [action[1]] * i: + result = [0] * (len(coefficients) + 1) + for j, value in enumerate(coefficients): + result[j] = field.add(result[j], field.mul(value, linear[0])) + result[j + 1] = field.add(result[j + 1], field.mul(value, linear[1])) + coefficients = result + columns.append(coefficients) + return transpose(columns) + + +def general_linear_two(field): + for entries in product(range(field.q), repeat=4): + action = [list(entries[:2]), list(entries[2:])] + if determinant(action, field): + yield action + + +def lift(e, r, action, multiplicity, field): + slices(e, r) + require(len(action) == 2 and all(len(row) == 2 for row in action), + 'slice action dimension mismatch') + require(len(multiplicity) == r and all(len(row) == r for row in multiplicity), + 'multiplicity dimension mismatch') + require(all(type(x) is int and 0 <= x < field.q + for matrix in (action, multiplicity) for row in matrix for x in row), + 'matrix entry outside field') + require(determinant(action, field) != 0, 'singular slice action') + require(determinant(multiplicity, field) != 0, 'singular multiplicity action') + p = tensor(transpose(symmetric_power(e - 1, action, field)), multiplicity, field) + q = tensor(inverse(symmetric_power(e, action, field), field), + transpose(inverse(multiplicity, field)), field) + return p, q, action + + +def fixes(first, second, witness, field): + p, q, action = witness + for row, target in zip(action, (first, second)): + mixed = mix(first, second, *row, field) + if multiply(multiply(p, mixed, field), transpose(q), field) != target: + return False + return True + + +def character(e, r, triple, field, left=False): + x, y, z = triple + if left: + x, y = y, x + return field.mul(field.mul(field.power(x, e + 1), field.power(y, e)), + field.power(z, r * e * (e + 1) // 2)) + + +def witness_for_triple(e, r, triple, field, left=False): + slices(e, r) + require(len(triple) == 3, 'determinant triple dimension mismatch') + require(all(type(x) is int and 0 < x < field.q for x in triple), + 'determinants must be nonzero field elements') + require(character(e, r, triple, field, left) == 1, 'character excludes triple') + x, y, z = triple + if left: + x, y = y, x + u = field.mul(field.inv(field.mul(x, y)), field.power(z, -r * e)) + d = identity(r) + d[0][0] = u + p, q, action = lift(e, r, [[z, 0], [0, 1]], d, field) + return (q, p, action) if left else (p, q, action) diff --git a/research/raw-pencil-sl-transport/vendor/raw/PROOF.md b/research/raw-pencil-sl-transport/vendor/raw/PROOF.md new file mode 100644 index 0000000000..0034e0b2f7 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/raw/PROOF.md @@ -0,0 +1,165 @@ +# Raw finite-field pencil decomposition + +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. + +## Claim and interface + +Let K be a supplied finite field. For any two m by n matrices A and B over K, +the algorithm returns the full Kronecker block list and invertible matrices +R and Q such that A Q = R A0 and B Q = R B0. Thus the strict action is +(R^-1, Q); the slice map is the identity. Zero rows, zero columns, zero-index +blocks, dependent slices and the zero pencil are allowed. There is no need +for an invertible slice over K. + +The output uses these models for s A0 + t B0: + +- Right index e: e by e+1, A0 has a unit diagonal and B0 a unit superdiagonal. +- Left index e: the transpose of that right block. +- Finite primary (f,e): (companion(f^e), I), with monic irreducible f. +- Infinity of length e: (I, companion(x^e)). + +The code gives a deterministic algorithm polynomial in m+n for each fixed K. +It uses field tables and exact row reduction. A coarse bound is +O_K((m+n+1)^10) field operations and O_K((m+n+1)^4) live field entries. +No bound polynomial in log(|K|), fast canonical-form bound, or numerical +stability claim is made. The executable shares the usual finite memory and +Python recursion limits. The written algorithm has no dimension bound. + +This completes the raw-input boundary for the supplied-model character +interface. It does not compute the character formulas of that interface. +It does not prove a physical supplier, native map, route, restoration schedule, +precision bound, repeated preparation cost or complete kappa improvement. +The selected .00310045 result and its main-transform bottleneck are unchanged. + +## 1. Shortest chains and singular blocks + +A polynomial right kernel vector of degree e has coefficients v0,...,ve with +A v0=0, A vi+B v(i-1)=0 and B ve=0. Solve this homogeneous linear system in +increasing e. If a right block exists, the first nonzero solution occurs at +its least minimal index. Search through min(m,n-1); a right block of index e +uses e rows and e+1 columns, so this range is complete. + +Use the classical Kronecker decomposition to justify the splitting step. +A shortest chain has zero component on every regular or left block, and on +every right block with larger index. There is no smaller right block. On each +right block with the least index, it is a scalar multiple of its generator: +a nonconstant multiplier would increase the degree. At least one scalar is +nonzero. A change among equal-index copies makes this chain one direct +summand. This also proves that its e+1 domain vectors and e image vectors +are independent. No search through all vectors of K^n is required. + +Set ui=(-1)^i v(e-i), and wi=A ui for 0<=i 1 and p[-1] == 0: + p.pop() + return p + + +def padd(p, q, f): + return trim([f.add[p[i] if i < len(p) else 0][q[i] if i < len(q) else 0] + for i in range(max(len(p), len(q)))]) + + +def pmul(p, q, f): + r = [0] * (len(p)+len(q)-1) + for i, x in enumerate(p): + for j, y in enumerate(q): + r[i+j] = f.add[r[i+j]][f.mul[x][y]] + return trim(r) + + +def pdiv(p, q, f): + p, q = trim(p), trim(q) + if q == [0]: + raise ValueError('zero divisor') + out = [0] * max(1, len(p)-len(q)+1) + while p != [0] and len(p) >= len(q): + j = len(p)-len(q) + c = f.mul[p[-1]][f.inv[q[-1]]] + out[j] = c + for i, x in enumerate(q): + p[i+j] = f.add[p[i+j]][f.neg[f.mul[c][x]]] + p = trim(p) + return trim(out), p + + +def pgcd(p, q, f): + while q != [0]: + p, q = q, pdiv(p, q, f)[1] + return [f.mul[f.inv[p[-1]]][x] for x in p] + + +def ppow(p, k, f, modulus=None): + r = [1] + while k: + if k & 1: + r = pmul(r, p, f) + if modulus is not None: + r = pdiv(r, modulus, f)[1] + p = pmul(p, p, f) + if modulus is not None: + p = pdiv(p, modulus, f)[1] + k //= 2 + return r + + +def factor(p, f): + """Use deterministic Berlekamp splitting, with inseparable recursion.""" + p = trim(p) + if len(p) == 1: + return [] + p = [f.mul[f.inv[p[-1]]][x] for x in p] + derivative = trim([f.mul[i % f.p][p[i]] for i in range(1, len(p))] or [0]) + if derivative == [0]: + root = [f.power(p[i], f.q // f.p) for i in range(0, len(p), f.p)] + return sorted(factor(root, f) * f.p) + g = pgcd(p, derivative, f) + if len(g) > 1: + return sorted(factor(g, f) + factor(pdiv(p, g, f)[0], f)) + d = len(p)-1 + cols = [] + for j in range(d): + v = ppow([0, 1], f.q*j, f, p) + v += [0] * (d-len(v)) + v[j] = f.add[v[j]][f.neg[1]] + cols.append(v) + basis = a.kernel(a.columns(cols, d), d, f) + parts = [p] + for b in basis: + for c in range(f.q): + h = b[:] + h[0] = f.add[h[0]][f.neg[c]] + nxt = [] + for part in parts: + g = pgcd(part, trim(h), f) + nxt += [g, pdiv(part, g, f)[0]] if 1 < len(g) < len(part) else [part] + parts = nxt + if len(parts) != len(basis): + raise ArithmeticError('Berlekamp split incomplete') + return sorted(tuple(x) for x in parts) + + +def peval(p, T, f): + n = len(T) + out = [[0]*n for _ in range(n)] + for c in reversed(p): + out = mm(out, T, n, f) + for i in range(n): + out[i][i] = f.add[out[i][i]][c] + return out + + +def minpoly(T, f): + n = len(T) + powers, P = [], a.identity(n) + for d in range(n+1): + flat = sum(P, []) + ker = a.kernel(a.columns(powers + [flat], n*n), d+1, f) + if ker: + v = next(x for x in ker if x[-1]) + return [f.mul[f.inv[v[-1]]][x] for x in v] + powers.append(flat) + P = mm(P, T, n, f) + raise ArithmeticError('minimal polynomial absent') + + +def companion(p, f): + n = len(p)-1 + C = [[int(i == j+1) for j in range(n)] for i in range(n)] + for i in range(n): + C[i][-1] = f.neg[p[i]] + return C + + +def primary(T, p, f): + n = len(T) + if not n: + return [], [] + N = peval(p, T, f) + power, previous, e = a.identity(n), None, 0 + while any(any(r) for r in power): + previous, power = power, mm(power, N, n, f) + e += 1 + j = next(j for j in range(n) if any(a.column(previous, j))) + v = a.column(a.identity(n), j) + vs = [] + d = (len(p)-1)*e + for _ in range(d): + vs.append(v) + v = a.mv(T, v, f) + U = a.columns(vs, n) + C = companion(ppow(p, e, f), f) + X, _, R, Q = split(T, a.identity(n), n, n, U, U, C, a.identity(d), d, d, f) + if R != Q: + raise ArithmeticError('operator split differs') + blocks, V = primary(sub(X, d, d), p, f) + return [(tuple(p), e)] + blocks, compose(Q, d, V, f) + + +def operator(T, f): + n = len(T) + if not n: + return [], [] + fac = factor(minpoly(T, f), f) + spaces, blocks = [], [] + for p in sorted(set(fac)): + N = peval(ppow(p, fac.count(p), f), T, f) + basis = a.kernel(N, n, f) + V = a.columns(basis, n) + d = len(basis) + equations = [] + for v in basis: + target = a.mv(T, v, f) + equations.append(solve([row + [x] for row, x in zip(V, target)], d, f)) + restricted = a.columns(equations, d) + bs, U = primary(restricted, p, f) + spaces += [a.column(mm(V, U, d, f), j) for j in range(d)] + blocks += bs + return blocks, a.columns(spaces, n) + + +def compose(Q, d, V, f): + n = len(Q) + E = [[int(i == j) if i < d and j < d else + V[i-d][j-d] if i >= d and j >= d else 0 for j in range(n)] for i in range(n)] + return mm(Q, E, n, f) + + +def regular(A, B, f): + n = len(A) + basis = [] + while True: + V = a.columns(basis, n) + AV = mm(A, V, len(basis), f) + eq = [r + [f.neg[x] for x in s] for r, s in zip(B, AV)] + nxt = span([v[:n] for v in a.kernel(eq, n+len(basis), f)], n, f) + if len(nxt) == len(basis): + break + basis = nxt + d = len(basis) + V = a.columns(basis, n) + W = mm(A, V, d, f) + BV = mm(B, V, d, f) + N = a.columns([solve([r+[x] for r, x in zip(W, a.column(BV, j))], d, f) + for j in range(d)], d) + X, Y, R, Q = split(A, B, n, n, V, W, a.identity(d), N, d, d, f) + inf, U = primary(N, (0, 1), f) + residualB = sub(Y, d, d) + T = mm(a.inverse(residualB, f), sub(X, d, d), n-d, f) + finite, Z = operator(T, f) + localQ = [[U[i][j] if i < d and j < d else Z[i-d][j-d] + if i >= d and j >= d else 0 for j in range(n)] for i in range(n)] + BZ = mm(residualB, Z, n-d, f) + localR = [[U[i][j] if i < d and j < d else BZ[i-d][j-d] + if i >= d and j >= d else 0 for j in range(n)] for i in range(n)] + return [('infinity', (), e) for _, e in inf] + [('finite', p, e) for p, e in finite], mm(R, localR, n, f), mm(Q, localQ, n, f) + + +def extract(A, B, m, n, f): + hit = chain(A, B, m, n, f) + if hit: + e, (X, Y, R, Q) = hit + c, b, tag = e, e+1, 'right' + else: + hit = chain(tr(A, n), tr(B, n), n, m, f) + if not hit: + if m != n: + raise ArithmeticError('regular residue is not square') + return regular(A, B, f) + e, (Xt, Yt, Rt, Qt) = hit + X, Y = tr(Xt, m), tr(Yt, m) + R, Q = tr(a.inverse(Qt, f), m), tr(a.inverse(Rt, f), n) + c, b, tag = e+1, e, 'left' + blocks, R2, Q2 = extract(sub(X, c, b), sub(Y, c, b), m-c, n-b, f) + return [(tag, (), e)] + blocks, compose(R, c, R2, f), compose(Q, b, Q2, f) + + +def model(blocks, f): + pieces = [] + for tag, p, e in blocks: + if tag in ('left', 'right'): + A = [[int(i == j) for j in range(e+1)] for i in range(e)] + B = [[int(i+1 == j) for j in range(e+1)] for i in range(e)] + m, n = e, e+1 + if tag == 'left': + A, B, m, n = tr(A, n), tr(B, n), n, m + else: + C = companion(ppow(p if tag == 'finite' else (0, 1), e, f), f) + m = n = len(C) + A, B = (C, a.identity(n)) if tag == 'finite' else (a.identity(n), C) + pieces.append((A, B, m, n)) + m, n = sum(x[2] for x in pieces), sum(x[3] for x in pieces) + A, B = [[0]*n for _ in range(m)], [[0]*n for _ in range(m)] + r = c = 0 + for X, Y, h, w in pieces: + for i in range(h): + A[r+i][c:c+w], B[r+i][c:c+w] = X[i], Y[i] + r, c = r+h, c+w + return A, B, m, n + + +def check(A, B, m, n, cert, f): + blocks, R, Q = cert + X, Y, h, w = model(blocks, f) + return ((h, w) == (m, n) and len(R) == m and all(len(r) == m for r in R) + and len(Q) == n and all(len(r) == n for r in Q) + and a.determinant(R, f) != 0 and a.determinant(Q, f) != 0 + and mm(A, Q, n, f) == mm(R, X, n, f) + and mm(B, Q, n, f) == mm(R, Y, n, f)) + + +def decompose(A, B, m, n, f): + if not isinstance(f, a.Field) or any(type(x) is not int or x < 0 for x in (m, n)): + raise ValueError('explicit field and nonnegative dimensions required') + if any(len(M) != m or any(len(r) != n or any(type(x) is not int or not 0 <= x < f.q + for x in r) for r in M) for M in (A, B)): + raise ValueError('invalid coefficient matrix') + cert = extract(A, B, m, n, f) + if not check(A, B, m, n, cert, f): + raise ArithmeticError('coefficient identity failed') + return cert diff --git a/research/raw-pencil-sl-transport/vendor/raw/field_source.py b/research/raw-pencil-sl-transport/vendor/raw/field_source.py new file mode 100644 index 0000000000..1066bb74c1 --- /dev/null +++ b/research/raw-pencil-sl-transport/vendor/raw/field_source.py @@ -0,0 +1,370 @@ +"""Exact finite-field tensor recognition. Ali Romman with OpenAI Codex. Apache-2.0.""" +from itertools import product +from math import gcd, isqrt + + +class Field: + """Use base-p digits and a monic polynomial, in constant-first order.""" + + def __init__(self, p, modulus): + if type(p) is not int or p < 2 or any(p % d == 0 for d in range(2, isqrt(p) + 1)): + raise ValueError('p must be prime') + if (not isinstance(modulus, (tuple, list)) or len(modulus) < 2 + or modulus[-1] != 1 + or any(type(c) is not int or not 0 <= c < p for c in modulus)): + raise ValueError('modulus must be monic with canonical prime-field coefficients') + self.p, self.e = p, len(modulus) - 1 + self.modulus = tuple(modulus) + self.q = p ** self.e + digits = [[(a // p ** i) % p for i in range(self.e)] for a in range(self.q)] + self.add = [[sum(((x + y) % p) * p ** i for i, (x, y) in enumerate(zip(a, b))) + for b in digits] for a in digits] + self.neg = [sum((-x % p) * p ** i for i, x in enumerate(a)) for a in digits] + self.mul = [] + for a in digits: + row = [] + for b in digits: + c = [0] * (2 * self.e - 1) + for i, x in enumerate(a): + for j, y in enumerate(b): + c[i + j] = (c[i + j] + x * y) % p + for k in range(len(c) - 1, self.e - 1, -1): + for j in range(self.e): + c[k - self.e + j] = (c[k - self.e + j] - c[k] * modulus[j]) % p + row.append(sum(c[i] * p ** i for i in range(self.e))) + self.mul.append(row) + self.inv = [0] + [self.power(a, self.q - 2) for a in range(1, self.q)] + if any(self.mul[a][self.inv[a]] != 1 for a in range(1, self.q)): + raise ValueError('modulus is reducible') + + def power(self, a, n): + if n < 0: + raise ValueError('negative exponent') + r = 1 + while n: + if n & 1: + r = self.mul[r][a] + a = self.mul[a][a] + n //= 2 + return r + + def total(self, xs): + r = 0 + for x in xs: + r = self.add[r][x] + return r + + +def identity(n): + return [[int(i == j) for j in range(n)] for i in range(n)] + + +def columns(xs, n): + return [[v[i] for v in xs] for i in range(n)] + + +def column(a, j): + return [r[j] for r in a] + + +def rref(a, width, f): + rows = [r[:] for r in a] + pivots = [] + k = 0 + for j in range(width): + pivot = next((i for i in range(k, len(rows)) if rows[i][j]), None) + if pivot is None: + continue + rows[k], rows[pivot] = rows[pivot], rows[k] + rows[k] = [f.mul[f.inv[rows[k][j]]][x] for x in rows[k]] + for i in range(len(rows)): + if i != k and rows[i][j]: + c = f.neg[rows[i][j]] + rows[i] = [f.add[x][f.mul[c][y]] for x, y in zip(rows[i], rows[k])] + pivots.append(j) + k += 1 + if k == len(rows): + break + return rows, pivots + + +def rank(a, f): + return len(rref(a, len(a[0]) if a else 0, f)[1]) + + +def kernel(a, width, f): + rows, pivots = rref(a, width, f) + out = [] + for j in range(width): + if j in pivots: + continue + v = [0] * width + v[j] = 1 + for i, p in enumerate(pivots): + v[p] = f.neg[rows[i][j]] + out.append(v) + return out + + +def inverse(a, f): + n = len(a) + rows, pivots = rref([r + e for r, e in zip(a, identity(n))], n, f) + if len(pivots) != n: + raise ValueError('singular matrix') + return [r[n:] for r in rows] + + +def mv(a, v, f): + return [f.total(f.mul[x][y] for x, y in zip(r, v)) for r in a] + + +def mm(a, b, f): + return columns([mv(a, column(b, j), f) for j in range(len(b[0]))], len(a)) + + +def determinant(a, f): + rows = [r[:] for r in a] + d = 1 + for j in range(len(rows)): + k = next((i for i in range(j, len(rows)) if rows[i][j]), None) + if k is None: + return 0 + if k != j: + rows[k], rows[j] = rows[j], rows[k] + d = f.neg[d] + c = rows[j][j] + d = f.mul[d][c] + for i in range(j + 1, len(rows)): + z = f.neg[f.mul[rows[i][j]][f.inv[c]]] + rows[i] = [f.add[x][f.mul[z][y]] for x, y in zip(rows[i], rows[j])] + return d + + +def tensor_value(t, u, v, f): + n = len(t) + out = [0] * n + for i, x in enumerate(u): + if x: + for j, y in enumerate(v): + if y: + c = f.mul[x][y] + out = [f.add[z][f.mul[c][a]] for z, a in zip(out, t[i][j])] + return out + + +def algebra_power(t, u, exponent, unit, f): + r = unit[:] + while exponent: + if exponent & 1: + r = tensor_value(t, r, u, f) + u = tensor_value(t, u, u, f) + exponent //= 2 + return r + + +def model(heights, f): + bounds = [f.p ** h for h in heights] + exponents = list(product(*(range(b) for b in bounds))) + ix = {v: i for i, v in enumerate(exponents)} + n = len(exponents) + t = [[[0] * n for _ in range(n)] for _ in range(n)] + for i, a in enumerate(exponents): + for j, b in enumerate(exponents): + c = tuple(x + y for x, y in zip(a, b)) + if all(x < bound for x, bound in zip(c, bounds)): + t[i][j][ix[c]] = 1 + return t, exponents + + +def semilinear_kernel(t, unit, h, f): + """Return ker(a -> a^(p^h)), with the coefficient twist removed.""" + n = len(t) + c = columns([algebra_power(t, v, f.p ** h, unit, f) for v in identity(n)], n) + untwist = f.p ** ((-h) % f.e) + return [[f.power(x, untwist) for x in v] for v in kernel(c, n, f)] + + +def validate_tensor(t, f): + if not isinstance(f, Field): + raise ValueError('field contract required') + if not isinstance(t, (list, tuple)) or not t: + raise ValueError('positive square tensor required') + n = len(t) + if any(not isinstance(a, (list, tuple)) or len(a) != n for a in t): + raise ValueError('input dimensions differ') + for a in t: + for b in a: + if not isinstance(b, (list, tuple)) or len(b) != n: + raise ValueError('output dimension differs') + if any(type(x) is not int or not 0 <= x < f.q for x in b): + raise ValueError('noncanonical field entry') + + +def check_certificate(t, cert, f): + """Check the factor maps by all basis products, without nucleus tests.""" + n = len(t) + mu, _ = model(cert['heights'], f) + if len(mu) != n: + return False + u, v, w = (cert[k] for k in ('U', 'V', 'W')) + if any(determinant(a, f) == 0 for a in (u, v, w)): + return False + for i in range(n): + for j in range(n): + if tensor_value(t, column(u, i), column(v, j), f) != mv(w, mu[i][j], f): + return False + return True + + +def recognize(t, f): + """Return (certificate, None), or (None, mathematical rejection reason).""" + validate_tensor(t, f) + n = len(t) + equations = [] + for i, j, k in product(range(n), repeat=3): + row = [0] * (2 * n * n) + for a in range(n): + row[a * n + i] = f.add[row[a * n + i]][t[a][j][k]] + index = n * n + k * n + a + row[index] = f.add[row[index]][f.neg[t[i][j][a]]] + equations.append(row) + basis = kernel(equations, 2 * n * n, f) + if len(basis) != n: + return None, 'nucleus dimension' + xb = [[b[i * n:(i + 1) * n] for i in range(n)] for b in basis] + yb = [[b[n * n + i * n:n * n + (i + 1) * n] for i in range(n)] for b in basis] + if rank([b[:n*n] for b in basis], f) != n or rank([b[n*n:] for b in basis], f) != n: + return None, 'nucleus projection' + if any(mm(a, b, f) != mm(b, a, f) for a in yb for b in yb): + return None, 'noncommutative nucleus' + right = [[t[i][j][k] for j in range(n)] for i in range(n) for k in range(n)] + if rank(right, f) != n: + return None, 'right kernel' + flat = [sum(a, []) for a in yb] + _, positions = rref(flat, n * n, f) + coord_inverse = inverse([[a[j] for a in flat] for j in positions], f) + + def coordinates(a): + v = sum(a, []) + c = mv(coord_inverse, [v[j] for j in positions], f) + if [f.total(f.mul[c[k]][flat[k][j]] for k in range(n)) for j in range(n*n)] != v: + raise ArithmeticError('nucleus closure') + return c + + table = [[coordinates(mm(a, b, f)) for b in yb] for a in yb] + unit = coordinates(identity(n)) + exponent = 1 + while exponent < n: + exponent *= f.q + qmap = columns([algebra_power(table, v, exponent, unit, f) for v in identity(n)], n) + radical = kernel(qmap, n, f) + if len(radical) != n - 1: + return None, 'residue field or number of components' + + def cyclic(module): + actions = [[[f.total(f.mul[c[k]][module[k][i][j]] for k in range(n)) + for j in range(n)] for i in range(n)] for c in radical] + jm = [column(a, j) for a in actions for j in range(n)] + if rank(jm, f) != n - 1: + return None + seed = next(v for v in identity(n) if rank(jm + [v], f) == n) + return columns([mv(a, seed, f) for a in module], n), seed + + ux, wy = cyclic(xb), cyclic(yb) + if ux is None or wy is None: + return None, 'nonregular nucleus module' + u, u0 = ux + w, _ = wy + phi = columns([tensor_value(t, u0, e, f) for e in identity(n)], n) + v = mm(inverse(phi, f), w, f) + span = [tensor_value(table, a, b, f) for a in radical for b in radical] + current = rank(span, f) + generators, heights = [], [] + h, power = 0, 1 + while power < n: + h += 1 + power *= f.p + for a in semilinear_kernel(table, unit, h, f): + new_rank = rank(span + [a], f) + if new_rank > current: + span.append(a) + generators.append(a) + heights.append(h) + current = new_rank + if f.p ** sum(heights) != n: + return None, 'height dimension' + mu, exponents = model(heights, f) + images = [] + for exps in exponents: + value = unit[:] + for g, e in zip(generators, exps): + value = tensor_value(table, value, algebra_power(table, g, e, unit, f), f) + images.append(value) + c = columns(images, n) + if determinant(c, f) == 0: + raise ArithmeticError('height criterion did not produce a basis') + cert = {'heights': heights, 'U': mm(u, c, f), 'V': mm(v, c, f), 'W': mm(w, c, f)} + if not check_certificate(t, cert, f): + raise ArithmeticError('transported product mismatch') + index = gcd(f.q - 1, *(n * (f.p ** h - 1) // 2 for h in heights)) + detu, detv, detw = (determinant(cert[k], f) for k in ('U', 'V', 'W')) + delta = f.mul[detw][f.inv[f.mul[detu][detv]]] + cert['sl_orbit_count'] = index + cert['sl_orbit_label'] = f.power(delta, (f.q - 1) // index) + return cert, None + + +def bezout(a, b): + x, y, u, v = 1, 0, 0, 1 + while b: + quotient, remainder = divmod(a, b) + a, b = b, remainder + x, u = u, x - quotient * u + y, v = v, y - quotient * v + return a, x, y + + +def sl_transporter(first, second, f): + """Return determinant-one maps F,G,H with second(Fu,Gv)=H first(u,v).""" + a, why = recognize(first, f) + if a is None: + return None, 'first tensor: ' + why + b, why = recognize(second, f) + if b is None: + return None, 'second tensor: ' + why + if a['heights'] != b['heights'] or a['sl_orbit_label'] != b['sl_orbit_label']: + return None, 'different special-linear orbits' + n, m = len(first), f.q - 1 + du, dv, dw = [f.mul[determinant(a[k], f)][f.inv[determinant(b[k], f)]] + for k in ('U', 'V', 'W')] + z = f.mul[f.mul[du][dv]][f.inv[dw]] + primitive = next(c for c in range(1, f.q) + if len({f.power(c, i) for i in range(m)}) == m) + logz = next(i for i in range(m) if f.power(primitive, i) == z) + g, coefficients = m, [] + for h in a['heights']: + g, x, y = bezout(g, n * (f.p ** h - 1) // 2) + coefficients = [x * c for c in coefficients] + [y] + if logz % g: + raise ArithmeticError('orbit label disagrees with determinant image') + scalars = [f.power(primitive, (c * (logz // g)) % m) for c in coefficients] + _, exponents = model(a['heights'], f) + diagonal = [1] * n + for j, es in enumerate(exponents): + for c, e in zip(scalars, es): + diagonal[j] = f.mul[diagonal[j]][f.power(c, e)] + inverse_n = pow(n, -1, m) + unit_a = f.power(f.mul[du][f.inv[z]], inverse_n) + unit_b = f.power(f.mul[dv][f.inv[z]], inverse_n) + factors = [unit_a, unit_b, f.mul[unit_a][unit_b]] + out = {} + for key, target, scalar in zip(('U', 'V', 'W'), ('F', 'G', 'H'), factors): + middle = [[f.mul[scalar][diagonal[i]] if i == j else 0 for j in range(n)] for i in range(n)] + out[target] = mm(mm(b[key], middle, f), inverse(a[key], f), f) + if determinant(out[target], f) != 1: + raise ArithmeticError('determinant correction failed') + for i in range(n): + for j in range(n): + if tensor_value(second, column(out['F'], i), column(out['G'], j), f) != mv(out['H'], first[i][j], f): + raise ArithmeticError('special-linear product mismatch') + return out, None diff --git a/research/raw-pencil-sl-transport/verify.py b/research/raw-pencil-sl-transport/verify.py new file mode 100644 index 0000000000..31a6e0a73e --- /dev/null +++ b/research/raw-pencil-sl-transport/verify.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python3 +"""Independent finite SL orbits, exact maps and unbounded-interface fixtures.""" +import argparse +from concurrent.futures import ProcessPoolExecutor +import hashlib +import importlib.util +from itertools import permutations,product +import json +from pathlib import Path +import random +import sys + +ROOT=Path(__file__).resolve().parent +sys.path.insert(0,str(ROOT)) +import sl + + +def authenticate():return sl.authenticate() + +def need(ok,message): + if not ok:raise ValueError(message) + + +def matrices(values,m,n): + return tuple([list(values[k*m*n+i*n:k*m*n+(i+1)*n]) for i in range(m)] for k in (0,1)) + + +def determinant(A,f): + total=0 + for p in permutations(range(len(A))): + v=1 + for i,j in enumerate(p):v=f.mul[v][A[i][j]] + if sum(p[i]>p[j] for i in range(len(p)) for j in range(i+1,len(p)))%2:v=f.neg[v] + total=f.add[total][v] + return total + + +def literal(first,second,maps,f,small=True): + P,Q,S=maps;m,n=len(P),len(Q) + det=determinant if small else sl.d.a.determinant + if any(det(M,f)!=1 for M in maps):return False + for k,i,j in product(range(2),range(m),range(n)): + total=0 + for t,a,b in product(range(2),range(m),range(n)): + total=f.add[total][f.mul[f.mul[f.mul[S[k][t]][P[i][a]]][Q[j][b]]][first[t][a][b]]] + if total!=second[k][i][j]:return False + return True + + +def digits(code,q,width): + out=[] + for _ in range(width):out.append(code%q);code//=q + return out + + +def neighbors(code,m,n,f): + width=2*m*n;v=digits(code,f.q,width);powers=[f.q**i for i in range(width)] + for axis,size in ((0,m),(1,n),(2,2)): + for i in range(size): + for j in range(size): + if i==j:continue + for c in range(1,f.q): + target=code + for k,r,s in product(range(2),range(m),range(n)): + if (r,s,k)[axis]!=i:continue + t,a,b=(j,r,s) if axis==2 else (k,j,s) if axis==0 else (k,r,j) + dest=k*m*n+r*n+s;source=t*m*n+a*n+b + value=f.add[v[dest]][f.mul[c][v[source]]] + target+=(value-v[dest])*powers[dest] + yield target + + +def orbit_ids(m,n,f): + count=f.q**(2*m*n);ids=[-1]*count;components=0 + for start in range(count): + if ids[start]>=0:continue + ids[start]=components;queue=[start] + for current in queue: + for following in neighbors(current,m,n,f): + if ids[following]<0:ids[following]=components;queue.append(following) + components+=1 + return ids,components + + +def batch(args): + p,modulus,m,n,lo,hi=args;f=sl.Field(p,modulus);out=[];trials=0 + for code in range(lo,hi): + first=matrices(digits(code,f.q,2*m*n),m,n) + cert=sl.canonicalize(first,m,n,f,random.Random(code+817)) + need(literal(first,cert['representative'],cert['maps'],f),'independent literal SL map') + out.append(cert['key']);trials+=cert['norm_trials'] + return lo,out,trials + + +def exhaustive(p,modulus,m,n,workers): + f=sl.Field(p,modulus);ids,components=orbit_ids(m,n,f);count=len(ids) + tasks=[(p,modulus,m,n,i,min(i+128,count)) for i in range(0,count,128)] + labels=[None]*count;trials=0 + if workers==1:answers=map(batch,tasks);pool=None + else:pool=ProcessPoolExecutor(max_workers=workers);answers=pool.map(batch,tasks,chunksize=1) + try: + for start,keys,used in answers:labels[start:start+len(keys)]=keys;trials+=used + finally: + if pool is not None:pool.shutdown() + by_orbit={};by_label={} + for code,key in enumerate(labels): + component=ids[code] + need(by_orbit.setdefault(component,key)==key,'label constant on independent SL orbit') + need(by_label.setdefault(key,component)==component,'distinct independent SL orbits separated') + need(len(by_label)==components,'complete finite orbit partition') + digest=hashlib.sha256(repr(labels).encode()).hexdigest() + return dict(q=f.q,shape=[m,n],pencils=count,sl_orbits=components,norm_trials=trials,sha256=digest) + + +def first_irreducible(degree,f): + constants=range(1,f.q) if degree>1 else range(f.q) + for constant in constants: + for tail in product(range(f.q),repeat=degree-1): + p=(constant,)+tuple(tail)+(1,) + if sl.d.factor(p,f)==[p]:return p + raise ValueError('no irreducible polynomial') + + +def random_sl(n,f,rng): + M=sl.d.a.identity(n) + if n==1:return M + for _ in range(3*n+2): + i,j=rng.sample(range(n),2);c=rng.randrange(1,f.q) + M[i]=[f.add[x][f.mul[c][y]] for x,y in zip(M[i],M[j])] + return M + + +def fixtures(): + rng=random.Random(92841);records=[];transports=controls=no_slice=0 + for p,modulus in ((2,(0,1)),(3,(0,1)),(2,(1,1,1)),(3,(1,0,1))): + f=sl.Field(p,modulus) + specs=[(('finite',first_irreducible(4,f),1),), + (('finite',(0,1),4),), + (('right',(),6),('left',(),0)), + (('right',(),1),)*4, + (('left',(),0),('right',(),0),('finite',(1,1),2))] + if f.q<=4:specs.append(tuple(('finite',(f.neg[a],1),1) for a in range(f.q))+(('infinity',(),1),)) + for blocks in specs: + A,B,m,n=sl.d.model(blocks,f);raw=(A,B) + maps=(random_sl(m,f,rng),random_sl(n,f,rng),random_sl(2,f,rng)) + changed=sl.action(raw,maps,f) + first=sl.canonicalize(raw,m,n,f,rng);second=sl.canonicalize(changed,m,n,f,rng) + need(first['key']==second['key'],'larger arbitrary-basis SL invariance') + need(literal(raw,first['representative'],first['maps'],f,False),'larger first literal map') + need(literal(changed,second['representative'],second['maps'],f,False),'larger second literal map') + transport=sl.compose(sl.inverse(second['maps'],f),first['maps'],f) + need(literal(raw,changed,transport,f,False),'larger raw-to-raw map');transports+=1 + if m==n: + invertible=any(sl.d.a.determinant([[f.add[f.mul[x][u]][f.mul[y][v]] for u,v in zip(r,s)] for r,s in zip(A,B)],f) + for x,y in product(range(f.q),repeat=2) if x or y) + no_slice+=int(not invertible) + bad=tuple([row[:] for row in M] for M in first['maps']);bad[0][0]=[0]*m + need(not literal(raw,first['representative'],bad,f,False),'singular map mutant rejected');controls+=1 + records.append(dict(q=f.q,shape=[m,n],blocks=blocks,slice_actions=first['slice_actions'])) + f=sl.Field(2,(0,1));raw=([[0] for _ in range(17)],[[0] for _ in range(17)]) + cert=sl.canonicalize(raw,17,1,f,rng) + need(literal(raw,cert['representative'],cert['maps'],f,False),'dimension above source bounded interface') + f=sl.Field(3,(0,1));x=([[1,0]],[[0,1]]);y=([[2,0]],[[0,1]]) + need(determinant(x[0]+x[1],f)==1 and determinant(y[0]+y[1],f)==2,'independent stacked determinant separation') + need(sl.transporter(x,y,1,2,f,rng) is None,'inequivalent raw pencils rejected');controls+=1 + good=sl.transporter(x,x,1,2,f,rng);need(literal(x,x,good,f),'public transporter identity') + native=([[1,0],[0,1]],[[0,1],[0,0]]) + changed=sl.action(native,([[1,1],[0,1]],sl.d.a.identity(2),sl.d.a.identity(2)),f) + public=sl.transporter(native,changed,2,2,f,rng) + need(native!=changed and literal(native,changed,public,f),'public nontrivial raw-to-raw transporter') + invalid=[(([],[]),1,1),(([[0]],[[0]]),0,1),(([[3]],[[0]]),1,1),(([[True]],[[0]]),1,1),(([[0,0]],[[0]]),1,1)] + for raw,m,n in invalid: + try:sl.analyze(raw,m,n,f) + except ValueError:controls+=1 + else:raise ValueError('invalid raw tensor accepted') + return dict(fixtures=len(records)+1,larger_transports=transports,no_invertible_slice_cases=no_slice, + controls=controls,records=records) + + +def norms(): + rng=random.Random(72619);checks=trials=0;degrees=[] + for p,modulus in ((2,(0,1)),(3,(0,1)),(2,(1,1,1)),(3,(1,0,1))): + f=sl.Field(p,modulus) + for degree in range(1,9): + poly=first_irreducible(degree,f);J=sl.d.companion(poly,f) + for target in range(1,f.q): + value,used=sl.norm_unit(poly,target,f,rng);trials+=used + need(sl.d.a.determinant(sl.d.peval(value,J,f),f)==target,'independent multiplication determinant norm') + for length in (1,2,4): + C=sl.d.companion(sl.d.ppow(poly,length,f),f) + need(sl.d.a.determinant(sl.d.peval(value,C,f),f)==f.power(target,length),'all-length lifted norm determinant') + checks+=1 + degrees.append([f.q,degree]) + controls=0;f=sl.Field(3,(0,1)) + for poly,target in (((0,0,1),1),((1,1),0),((1,),1)): + try:sl.norm_unit(poly,target,f,rng) + except ValueError:controls+=1 + else:raise ValueError('invalid norm problem accepted') + return dict(norm_targets=checks,sampled_candidates=trials,lifted_determinants=3*checks,field_degree_pairs=degrees,controls=controls) + + +def characters(): + path=ROOT/'vendor/characters/pencils.py';spec=importlib.util.spec_from_file_location('retained_characters',path) + old=importlib.util.module_from_spec(spec);spec.loader.exec_module(old) + rng=random.Random(717);records=[];triples=0 + specs=[(('R',1,1),),(('R',0,1),('L',0,1)),(('F',(0,1),2,1),), + (('F',(0,1),1,1),('I',1,1)),(('R',1,1),('F',(1,1),1,1))] + for q,p,modulus in ((2,2,(0,1)),(3,3,(0,1)),(4,2,(1,1,1))): + f=sl.Field(p,modulus);g=old.Field(q) + need(all(f.add[a][b]==g.add(a,b) and f.mul[a][b]==g.mul(a,b) for a,b in product(range(q),repeat=2)),'common field encoding') + for model in specs: + compiled=old.compile_model(model,g);m,n=compiled['dimensions'];raw=compiled['slices'];prior=old.orbit_labels(compiled) + our_to_prior={};prior_to_our={} + for triple in product(range(1,q),repeat=3): + maps=(sl.diagonal(m,triple[0]),sl.diagonal(n,triple[1]),sl.diagonal(2,triple[2])) + changed=sl.action(raw,maps,f);cert=sl.canonicalize(changed,m,n,f,rng) + need(literal(changed,cert['representative'],cert['maps'],f,False),'character comparison literal map') + label=prior[triple];key=cert['key'] + need(our_to_prior.setdefault(key,label)==label and prior_to_our.setdefault(label,key)==key,'complete supplied/raw SL quotient agreement') + triples+=1 + records.append(dict(q=q,model=model,sl_orbits=len(our_to_prior))) + return dict(models=len(records),determinant_triples=triples,records=records) + + +def main(): + parser=argparse.ArgumentParser();parser.add_argument('--phase',choices=('small','extension','fixtures','norms','characters'),required=True) + parser.add_argument('--workers',type=int,default=4);args=parser.parse_args();need(1<=args.workers<=4,'bounded worker count') + inputs=authenticate() + if args.phase=='small': + result={'domains':[exhaustive(p,mod,m,n,args.workers) for p,mod,m,n in ((2,(0,1),2,2),(2,(0,1),2,3),(2,(0,1),3,2),(3,(0,1),2,2),(3,(0,1),1,1),(3,(0,1),1,2),(3,(0,1),2,1))]} + elif args.phase=='extension':result={'domains':[exhaustive(2,(1,1,1),m,n,args.workers) for m,n in ((2,2),(1,1),(1,2),(2,1))]} + else:result=globals()[args.phase]() + print(json.dumps(dict(status='PASS_RAW_PENCIL_SL_'+args.phase.upper(),source_inputs=inputs,**result),sort_keys=True,indent=2),flush=True) + + +if __name__=='__main__':main()