From ee736b4b11bbd63b04d94c8edafb3790161ebdea Mon Sep 17 00:00:00 2001 From: Aaron Wang Date: Wed, 14 Oct 2026 06:57:33 -0400 Subject: [PATCH] Research: quaternion alphabet central commutator pairs cost their direct bill (no new kappa) Scoped exact minima in formal F2[Q8]: diag([z],[z]) and diag([xy],[yx]) at r=2 and diag([z],[z],[e]) at r=3 all have minimum four paid calls, equal to the direct bill. Complete BFS to depth 3 excludes shorter words; two independent engines replay every witness. Package research/q8-central-commutator-pair with registered replay. Contributor: Aaron Wang, with help from opencode. Apache-2.0. --- .../CERTIFICATE.json | 140 ++++++ .../q8-central-commutator-pair/PR-BODY.md | 94 ++++ research/q8-central-commutator-pair/README.md | 130 +++++ .../q8-central-commutator-pair/SOURCES.json | 36 ++ .../q8-central-commutator-pair/TASK-CARD.md | 50 ++ research/q8-central-commutator-pair/TASK.json | 66 +++ .../q8-central-commutator-pair/VERIFY.json | 23 + research/q8-central-commutator-pair/verify.py | 467 ++++++++++++++++++ 8 files changed, 1006 insertions(+) create mode 100644 research/q8-central-commutator-pair/CERTIFICATE.json create mode 100644 research/q8-central-commutator-pair/PR-BODY.md create mode 100644 research/q8-central-commutator-pair/README.md create mode 100644 research/q8-central-commutator-pair/SOURCES.json create mode 100644 research/q8-central-commutator-pair/TASK-CARD.md create mode 100644 research/q8-central-commutator-pair/TASK.json create mode 100644 research/q8-central-commutator-pair/VERIFY.json create mode 100644 research/q8-central-commutator-pair/verify.py diff --git a/research/q8-central-commutator-pair/CERTIFICATE.json b/research/q8-central-commutator-pair/CERTIFICATE.json new file mode 100644 index 0000000000..2c805c49d2 --- /dev/null +++ b/research/q8-central-commutator-pair/CERTIFICATE.json @@ -0,0 +1,140 @@ +{ + "controls": 4, + "endpoints": { + "diag_xy_yx_r2": { + "direct": [ + 2, + 8, + 6, + 0 + ], + "minimum": 4, + "proven": "complete BFS to depth 3 excludes words of length <= 3", + "registers": 2, + "witness": [ + 2, + 8, + 6, + 0 + ] + }, + "diag_z_z_e_r3": { + "direct": [ + 4, + 4, + 0, + 0 + ], + "minimum": 4, + "proven": "complete BFS to depth 3 excludes words of length <= 3", + "registers": 3, + "witness": [ + 4, + 4, + 0, + 0 + ] + }, + "diag_z_z_r2": { + "direct": [ + 2, + 2, + 0, + 0 + ], + "minimum": 4, + "proven": "complete BFS to depth 3 excludes words of length <= 3", + "registers": 2, + "witness": [ + 2, + 2, + 0, + 0 + ] + } + }, + "gl2_order": 6, + "gl3_order": 168, + "group_order": 8, + "independent_engine_b": true, + "new_kappa": false, + "omission_controls": 12, + "r2_ball_sha256": "c7935c78bd5e9424f36145760f2cc9b9925341ddb786b88a16e45cfb37bd201e", + "r2_generators": [ + [ + 1, + 1, + 1 + ], + [ + 1, + 1, + 3 + ], + [ + 1, + 2, + 2 + ], + [ + 1, + 2, + 3 + ], + [ + 1, + 3, + 1 + ], + [ + 1, + 3, + 2 + ], + [ + 2, + 1, + 1 + ], + [ + 2, + 1, + 3 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 3 + ], + [ + 2, + 3, + 1 + ], + [ + 2, + 3, + 2 + ] + ], + "r2_layers": [ + 1, + 12, + 110, + 936 + ], + "r3_ball_sha256": "1fac1d4f01e6cffbc06ebff3d94a1e0b5c51b0df69dba01770ab823f603c45f2", + "r3_generator_count": 56, + "r3_layers": [ + 1, + 56, + 2324, + 89574 + ], + "status": "PASS_Q8_CENTRAL_COMMUTATOR" +} diff --git a/research/q8-central-commutator-pair/PR-BODY.md b/research/q8-central-commutator-pair/PR-BODY.md new file mode 100644 index 0000000000..a31e391661 --- /dev/null +++ b/research/q8-central-commutator-pair/PR-BODY.md @@ -0,0 +1,94 @@ +# PR: Quaternion alphabet: central commutator pairs still cost their direct bill (no new kappa) + +## Scope + +Track `bit-mechanisms`, task card `bit-new-register-model` (scope key `7f5f4426ef796683c485`, +chooser OS nonce `73aa3cb4cec915ba6c0a1125abe1e410`, priority revision 3), scope **refined** +to the card's allowed variation "a specified nonabelian operation family", instantiated as +the quaternion group `Q8`. Exact base `0b1cccf86e2f5132ed286a26ef0a681a495740ea`; +selected-record SHA-256 `10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32`. + +The scoped three-register obstruction (`research/bit-three-register-lower-bound`) and the +dihedral predecessor (`research/bit-dihedral-commutator`, +https://github.com/CrocSwap/integer-mult-bounds/pull/1443) both fix their address group and +state that other address groups are not excluded. This package changes exactly that one +hypothesis: address group `Q8 = {+-1, +-i, +-j, +-k}` instead of `M_3(Q)` / `UT3(F2) = D8`. +The commutator arithmetic differs: `z = xyxy = x^2 = y^2 = -1` is a paid-label square, so +the direct bill is 4 rather than the dihedral 8. + +Model: formal `F2[Q8]`, paid labels `x = i`, `y = j` only, paid factors +`D_N(g) = I + ([g]+1)N` with `N = u v^T`, `v^T u = 1`, over `r` scalar registers (6 N / 12 +generators at r = 2, 28 N / 56 at r = 3), free scalar `GL_r(F2)` mixing normalized by +augmentation (predecessor's argument; its finite GL-conjugation closure step is rechecked), +arbitrary dirty register inputs, every call charged, no free address maps, no COPY/ERASE, no +clean ancilla. Acceptance is equality in every coefficient of the full group algebra. + +## Result + +| endpoint | direct bill | exact minimum | +|---|---:|---:| +| r = 2: `diag([z],[z])`, `z = xyxy = x^2 = y^2` | 4 | **4** | +| r = 2: `diag([xy],[yx])` (noncommuting pair, both orderings) | 4 | **4** | +| r = 3: `diag([z],[z],[e])` with one restored dirty register | 4 | **4** | + +Scoped negative: no cross-register sharing compression exists in this alphabet. Complete BFS +layer expansion to depth 3 (layers `1,12,110,936` at r = 2 and `1,56,2324,89574` at r = 3, +ball SHA-256 digests in `CERTIFICATE.json`) excludes every word of length at most 3; the +direct four-call word attains 4. Unlike the dihedral generators the Q8 factors are not +involutions (`D_N(x)^2 = D_N(x^2) = D_N(z)` is checked for all generators), so no split +argument is needed. + +## Evidence and reproduction + +Package: `research/q8-central-commutator-pair/`. Registered replay passes: + +```sh +python3.12 scripts/research_package.py --package research/q8-central-commutator-pair +# PASS_REGISTERED_RESEARCH_PACKAGE research/q8-central-commutator-pair outcome=completed +python -I -O -B research/q8-central-commutator-pair/verify.py +# PASS_Q8_CENTRAL_COMMUTATOR diag_z_z_r2:4 diag_xy_yx_r2:4 diag_z_z_e_r3:4 +# r2_layers=[1, 12, 110, 936] r3_layers=[1, 56, 2324, 89574] no_new_kappa +``` + +The verifier recomputes everything from scratch (stdlib only) and checks: Q8 group laws +exhaustively plus agreement of two independent quaternion multiplications; rank-one +idempotent counts 6 / 28 and idempotence; `D_N(g)^2 = D_N(g^2)`; `GL_2(F2)` (order 6) and +`GL_3(F2)` (order 168) conjugation closure of the generator sets; complete BFS layer sizes +and ball digests; engine A (bitmask convolution) and engine B (independent frozenset formal +matrices with Hamilton 4-tuple multiplication) agree on every witness and direct word; +omission controls (every single-call deletion of each direct word misses, 12 controls); +known-distance controls (`I` at 0, `diag([x],[e])` at 1, `diag([z],[e])` at 2); mutated-target +failure control; certificate equality. `scripts/research_package.py --check-only` reports +`PASS_PACKAGE_METADATA_AND_PINS`. The `tests/test_research_*.py` suite passes (42 tests OK, +2 skipped). + +## Limitations (stated, not checked) + +No kappa, supplier, moment or frontier change is claimed; the bit side does not bind and no +physical invoice, native replay, hosting, precision or analytic obligation is invoked. The +result is exact only for this alphabet (labels `x, y`, these endpoints, r in {2,3}): a failed +search is a result about the searched domain, not an impossibility theorem. Not a +proof-assistant verification. The free-mixing augmentation normalization is inherited from +the predecessors; only its finite closure step is rechecked here. + +## Overlap + +Refreshed `scripts/find_overlap.py` with the concrete object terms (2026-10-14T10:53Z, +complete pagination): no `Q8` object in open PRs, discussions or local packages besides +this one. Deliberately distinct from the `F2[GL2(F2)]` coordinate-CNOT/SWAP line (order-six +group, isomorphic to `S3`), the `UT3/D8` commutator line (closed at `4k` for all registers; +third dirty register closed negatively), and the `S4`/`S5`/`AGL2`/`GL3` target searches of +2026-10-14. Coordination claim: +https://github.com/CrocSwap/integer-mult-bounds/discussions/1317#discussioncomment-18921583. + +## Credit + +Prepared by **Aaron Wang**, with help from opencode (substantial AI assistance disclosed; no +independent human review). Apache-2.0. Model, normalization and presentation follow +woklerx's `research/bit-dihedral-commutator` +(https://github.com/CrocSwap/integer-mult-bounds/pull/1443), which explicitly leaves other +address groups open. Scalar-idempotent register model: eumemic's PR 288 section 1.2; the +register-model lineage credits Ali Romman (https://github.com/CrocSwap/integer-mult-bounds/pull/468), +Gareth Davidson (https://github.com/CrocSwap/integer-mult-bounds/pull/1333) and the pinned +three-register note (`research/bit-three-register-lower-bound`). Frozen sources and +`upstream/` are unchanged. diff --git a/research/q8-central-commutator-pair/README.md b/research/q8-central-commutator-pair/README.md new file mode 100644 index 0000000000..7a6277dc86 --- /dev/null +++ b/research/q8-central-commutator-pair/README.md @@ -0,0 +1,130 @@ +# Quaternion alphabet: central commutator pairs still cost their direct bill + +**Scoped finite search result in a fresh nonabelian alphabet; no new kappa.** In the formal +`F2[Q8]` register model below, cross-register sharing cannot compress three central or +noncommuting pair targets below their direct four-call bill. The exact minimum is **four** +paid calls for each endpoint, at `r = 2` and at `r = 3` with one restored dirty register. +The bit supplier, the selected result and `upstream/` are unchanged; the bit side does not +bind. + +## Changed hypothesis and full price + +The scoped three-register obstruction (`research/bit-three-register-lower-bound`) works in +the abelian rational frame group `M_3(Q)`. Its model and the dihedral predecessor +(`research/bit-dihedral-commutator`, woklerx, +[PR 1443](https://github.com/CrocSwap/integer-mult-bounds/pull/1443)) both state that they +do not cover other address groups. This note changes exactly that hypothesis: + +* **Address group.** `Q8 = {+-1, +-i, +-j, +-k}`, the quaternion group. Write `x = i`, + `y = j`, `z = xyxy = x^2 = y^2 = -1` (the commutator, central of order two). Unlike the + dihedral case the central commutator is a *paid-label square*, so the direct bill is 4 + rather than 8. +* **Counted roles.** `r = 2` arbitrary dirty scalar registers; the secondary endpoint uses + `r = 3` with the third register restored exactly. Every paid call is charged; there are + no free address maps, no COPY/ERASE, no clean ancilla and no unpriced `z` primitive. +* **Alphabet.** Paid labels are `x` and `y` only (no inverse labels). Each paid factor is + `D_N(g) = I + ([g]+1)N`, `N = u v^T` a binary rank-one idempotent (`v^T u = 1`) on `r` + scalar registers: six `N` and twelve generators at `r = 2`, twenty-eight `N` and + fifty-six generators at `r = 3`. Free scalar `GL_r(F2)` basis changes are free and + normalized by augmentation, exactly as in the predecessor: conjugating by a free scalar + map conjugates `N` within the rank-one idempotents (this closure is rechecked for every + `S` in `GL_2(F2)` and `GL_3(F2)`), free maps move through the paid factors, and + augmentation `[g] -> 1` maps every paid factor to `I`, forcing the residual scalar map + to the identity. The generator search therefore covers arbitrary interleaved free + scalar mixing. This normalization argument is inherited from + `research/bit-dihedral-commutator` and eumemic's PR 288 section 1.2; only its finite + closure step is reproved here. + +**Uniform identity standard.** Acceptance is equality in every coefficient of the full +eight-element group algebra `F2[Q8]`, not equality at one finite address size. A word that +equals `diag([g_1],...,[g_r])` in `M_r(F2[Q8])` is an identity on arbitrary dirty register +inputs. + +## Exact results + +| endpoint | direct bill | exact minimum | certificate | +|---|---:|---:|---| +| `r = 2`: `diag([z],[z])`, `z = xyxy = x^2 = y^2` | 4 | **4** | complete BFS to depth 3 misses; direct word attains | +| `r = 2`: `diag([xy],[yx])` (noncommuting pair, both orderings) | 4 | **4** | same | +| `r = 3`: `diag([z],[z],[e])`, third register dirty and restored | 4 | **4** | same | + +The BFS layer sizes (new states per distance) are `1, 12, 110, 936` at `r = 2` and +`1, 56, 2324, 89574` at `r = 3`; ball digests are in `CERTIFICATE.json`. Because the state +of the formal matrix monoid determines every continuation, complete layer expansion to +depth 3 excludes all words of length at most 3, and the direct four-call word +(`z` on one register = two `x` calls on that register's idempotent) attains 4. No split +argument is needed; unlike the dihedral generators, the `Q8` factors `D_N(x)` are not +involutions (`D_N(x)^2 = D_N(x^2) = D_N(z)` is checked for every generator). + +## Evidence + +`python -I -O -B research/q8-central-commutator-pair/verify.py` (stdlib only, about 25 s) +recomputes everything and compares with `CERTIFICATE.json`: + +* Q8 group laws exhaustively (associativity over all 512 triples, `x^2 = y^2 = z = xyxy`, + `z` central, `[x,y] = z`), plus agreement of two independent quaternion multiplications; +* rank-one idempotent counts 6 / 28 and idempotence; +* the generator identity `D_N(g)^2 = D_N(g^2)` for all 12 / 56 generators; +* `GL_2(F2)` (order 6) and `GL_3(F2)` (order 168) conjugation closure of the generator set; +* complete BFS layer sizes and ball SHA-256 digests to depth 3 for both register counts; +* engine A (bitmask group-algebra convolution) and engine B (independent frozenset formal + matrices with Hamilton 4-tuple quaternion multiplication) agree on every witness and + direct word; +* omission controls: every single-call deletion of each direct word misses the endpoint + (12 controls); +* known-distance controls: `I` at 0, `diag([x],[e])` at 1, `diag([z],[e])` at 2; +* mutated-target failure control: the certified word does not verify a target with one + flipped coefficient. + +## Scope and what is not claimed + +* **No kappa, no supplier, no frontier change.** This is a scoped obstruction in one + explicit finite alphabet. It says nothing about the rational-frame model, other address + groups, inverse or larger label sets (the labels are `x, y` only), `r >= 3` active + targets, or the multiplication exponent. +* **Failed search is not an impossibility theorem.** The statement is exact only for this + alphabet and these endpoints: no word of length at most 3 exists in the 12/56-generator + alphabets, and length 4 suffices. +* **Not a proof-assistant verification.** Two independent Python engines and finite + exhaustions; no Lean or native C++ replay was run. +* The `a < D/E` moment diagnostic does not apply: there is no candidate improvement to + price, and the scalar-cost relaxation here is more optimistic than any physical invoice. + +## Reproduce + +```sh +python -I -O -B research/q8-central-commutator-pair/verify.py +python -I -B research/q8-central-commutator-pair/verify.py +python3.12 scripts/research_package.py --package research/q8-central-commutator-pair +``` + +Expected: + +```text +PASS_Q8_CENTRAL_COMMUTATOR diag_z_z_r2:4 diag_xy_yx_r2:4 diag_z_z_e_r3:4 r2_layers=[1, 12, 110, 936] r3_layers=[1, 56, 2324, 89574] no_new_kappa +``` + +## Open next questions + +* **Does a label set including the inverses (`x, x^-1, y, y^-1`) compress any pair target?** + It changes the word-length pricing and is the first alphabet variant neither this note nor + the dihedral one covers. First step: the same BFS with 24 generators at `r = 2` against + `diag([z],[z])` and `diag([xy],[yx])`. Blocker: none technical; bounded follow-up. +* **Is the minimum still 4 for `diag([z],[z],[z])` at `r = 3` (direct bill 6)?** Three + active roles would test whether sharing scales beyond pairs. First step: depth-3 + meet-in-the-middle with layer digests and a memory cap. Blocker: state-space growth. + +## Credit and disclosure + +Prepared by **Aaron Wang**, with help from opencode. Apache-2.0; no independent human +review claimed. The model, the free-mixing normalization and the exact-minimum presentation +follow woklerx's `research/bit-dihedral-commutator` +([PR 1443](https://github.com/CrocSwap/integer-mult-bounds/pull/1443)), which fixes address +group `UT3(F2) = D8` and explicitly leaves other address groups open. The scalar-idempotent +register model is eumemic's PR 288 section 1.2; the register-model lineage credits Ali +Romman (PR 468), Gareth Davidson (PR 1333) and the pinned three-register note. Concurrent +work this is deliberately distinct from: the `F2[GL2(F2)]` coordinate-CNOT/SWAP line +(order-six group, isomorphic to `S3`), the `UT3/D8` commutator line (closed at `4k` for all +registers; third dirty register closed negatively), and the `S4`/`S5`/`AGL2`/`GL3` target +searches of October 14, 2026. The refreshed overlap survey (2026-10-14T10:17Z, complete +pagination) found no `Q8` object. diff --git a/research/q8-central-commutator-pair/SOURCES.json b/research/q8-central-commutator-pair/SOURCES.json new file mode 100644 index 0000000000..92dd2e9fde --- /dev/null +++ b/research/q8-central-commutator-pair/SOURCES.json @@ -0,0 +1,36 @@ +{ + "schema_version": 1, + "base_commit": "0b1cccf86e2f5132ed286a26ef0a681a495740ea", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "ae6a99f28aa468649eb66a361e764d769363bf11", + "sha256": "10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "06c96f5579bb67ed1b86d334e78fbed7da6945f1", + "sha256": "6686ad58f1fbdbc87134a78901b60fd53a20d3984355e91defbbebc9e9fa8075" + }, + { + "path": "research/bit-dihedral-commutator/TASK.json", + "usage": "input", + "git_blob": "9a745d3086918d21c143716cce1669d3324524c5", + "sha256": "aeed63deb60eba7aa17d738bb7d46682bf0ae510a18c1a9b1beada17ffbfa57c" + }, + { + "path": "research/bit-dihedral-commutator/README.md", + "usage": "input", + "git_blob": "b7619a5d56f32daf7f48d6cc3a0e260c5a333510", + "sha256": "4f3f9df6d6d96a26ccb0fcd2ef947cce5d53b0d992da22e866f1e025be4c0492" + }, + { + "path": "research/bit-three-register-lower-bound/README.md", + "usage": "provenance", + "git_blob": "25e41c370c101a33a6deb978de08b03ed7539b79", + "sha256": "c12b33ef388deece0cbf891505a2ce2c0779a0c3a6cf1f0f7f7039bab59cbebd" + } + ] +} diff --git a/research/q8-central-commutator-pair/TASK-CARD.md b/research/q8-central-commutator-pair/TASK-CARD.md new file mode 100644 index 0000000000..792cbe7994 --- /dev/null +++ b/research/q8-central-commutator-pair/TASK-CARD.md @@ -0,0 +1,50 @@ +# Task card (autoresearch.md section 3) + +Task ID / proposed scope key: bit-new-register-model / scope key 7f5f4426ef796683c485, +refined: `q8-central-commutator-pair` (F2[Q8], r=2 and r=3, central commutator pair). +Base commit; exact predecessor and dependency heads: base 0b1cccf86e2f5132ed286a26ef0a681a495740ea; +selected-record SHA-256 10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32. +Predecessor package research/bit-dihedral-commutator (woklerx, PR 1443) at the base commit. + +Concrete object and question: formal F2[Q8], Q8 = {±1, ±i, ±j, ±k}; paid labels x = i, y = j +only; paid factors D_N(g) = I + ([g]+1)N with N = uv^T, v^T u = 1, in M_r(F2); free scalar +GL_r(F2) mixing normalized by augmentation (predecessor's normalization); arbitrary dirty +register inputs. Target diag([z],[z]) with z = xyxy = x^2 = y^2 = −1 (the commutator, central +of order two). Question: exact minimum paid-call count; direct bill is four; can rank-one +idempotent sharing compress below four? Secondary endpoint: r = 3, target diag([z],[z],[e]) +with one restored dirty register. + +Scope status: refined. Reason: the card's allowed variation "a specified nonabelian operation +family" is instantiated as the quaternion group; the predecessor fixes address group +UT3(F2) ≅ D8 and states "No larger register count or different address group is excluded". + +Existing restriction being changed: the address group of the formal register model +(D8 → Q8). Note the arithmetic difference: in Q8 the central commutator is a paid-label +square (z = x^2 = y^2), so the direct bill is 4 rather than the dihedral 8. + +Method; explicit parameter ranges/candidate alphabet: complete BFS over the formal matrix +monoid M_r(F2[Q8]) with all generators; r = 2 has 6 rank-one idempotents x 2 labels = 12 +generators, r = 3 has 28 x 2 = 56. Exact formal group-algebra equality in every coefficient +(no finite-address tests). BFS depth ≤ direct bill − 1 decides compression; a found word of +length d plus complete depth-(d−1) coverage certifies the minimum. + +Nearest overlapping PRs and why this adds something: PR 1443 (D8 central pair min 8, +different group and different commutator arithmetic); PR 1742 (D8 third dirty register, +negative); PR 1478/1573 (UT3 commutator closed at 4k for all registers); the F2[GL2(F2)] +coordinate-CNOT/SWAP line (PR 1333/1414/1491/1495/1496; order-six group ≅ S3); S4/S5 target +PRs (1716/1720/1734/1749); AGL2/GL3 claims of 1337isnot1337. No Q8 object found in the +overlap survey (find_overlap.py, refreshed 2026-10-14T10:17Z). + +Optimistic full cost budget; required observable improvement: no kappa claim is possible +(bit side does not bind). Observable: exact minimum versus the direct bill of 4 in the +optimistic scalar-cost relaxation, with all interface hypotheses named. + +Success evidence; falsification test; time/compute cap: BFS layer counts + literal witness +word re-multiplied by an independent engine; controls: mutated targets rejected, each +single-call omission of a witness rejected, group-law checks for Q8. Compute cap 20 minutes. + +Predecessor authors; intended artifact and reproduction command: woklerx (PR 1443); +eumemic PR 288 section 1.2 (scalar-idempotent model); Ali Romman PR 468; Gareth Davidson +PR 1333 (augmentation normalization). Artifact: research/q8-central-commutator-pair/ with +`python -I -O -B research/q8-central-commutator-pair/verify.py`. Contributor: Aaron Wang, +with help from opencode. diff --git a/research/q8-central-commutator-pair/TASK.json b/research/q8-central-commutator-pair/TASK.json new file mode 100644 index 0000000000..a409c33835 --- /dev/null +++ b/research/q8-central-commutator-pair/TASK.json @@ -0,0 +1,66 @@ +{ + "schema_version": 1, + "task_id": "bit-new-register-model", + "priority_revision": 3, + "base_commit": "0b1cccf86e2f5132ed286a26ef0a681a495740ea", + "original_card": { + "id": "bit-new-register-model", + "question": "Can an explicitly larger or nonabelian register model escape the scoped three-register obstruction?", + "starting_points": [ + "research/bit-three-register-lower-bound/README.md", + "certificates/selected-result.json" + ], + "methods": [ + "Construct the smallest exact identity in a newly specified legal operation alphabet.", + "Derive a target-specific relaxation bound for that same explicit alphabet." + ], + "acceptance_gate": "Name the changed hypothesis, all counted roles and a uniform identity; finite column tests alone do not certify it.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read Model section 1 of the three-register bound and identify the exact excluded free operations.", + "scope": "Positive control / source-bound orientation only; this is not a new construction or full cold replay." + }, + "first_experiment": "Write a complete operation alphabet outside one named premise and price a baseline before searching identities.", + "bottleneck_link": "A small-width completed saving changes the bit primitive; a finite-address identity alone is insufficient.", + "allowed_variations": [ + "Choose a fixed larger register count or a specified nonabelian operation family." + ], + "scope_change_triggers": [ + "Remaining inside the already-excluded three-register abelian model." + ], + "overlap_terms": [ + "three-register", + "nonabelian", + "group algebra" + ] + }, + "scope_status": "refined", + "actual_scope": "Formal F2[Q8] on two dirty registers (and r=3 with one restored dirty register), paid labels x=i, y=j only, free scalar GL_r(F2) mixing normalized by augmentation, targets diag([z],[z]) with z=xyxy=x^2=y^2=-1, and the anti-diagonal pair diag([xy],[yx]); exact minimum paid-call counts.", + "scope_change_reason": "Instantiates the card's allowed variation 'a specified nonabelian operation family' as the quaternion group. The predecessor research/bit-dihedral-commutator fixes address group UT3(F2)=D8 and states that no different address group is excluded. Q8 differs in the key arithmetic: the central commutator is a paid-label square (z=x^2=y^2), so the direct bill is 4 rather than the dihedral 8.", + "bottleneck_link": "Scoped negative result for the bit primitive: no cross-register sharing compression exists in this nonabelian alphabet either, so the quaternion alphabet does not by itself change the paid recursive profile. No kappa claim is possible (the bit side does not bind).", + "budget_minutes": 60, + "stop_rule": "Complete BFS to depth 3 against the direct four-call upper bound for each endpoint; stop once each minimum is decided exactly. No pivot beyond the three named endpoints.", + "outcome": "completed", + "evidence": "CERTIFICATE.json (minima, layer sizes, ball hashes, generators) and verify.py (two independent engines, GL closure, omission and mutated-target controls); written argument in README.md.", + "author": "Aaron Wang", + "ai_assistance": "Substantial AI assistance (opencode); no independent human review.", + "open_questions": [ + { + "question": "Does a two-register alphabet with paid labels x, x^-1, y, y^-1 compress any central-pair target below its direct bill in F2[Q8]?", + "why_it_matters": "The inverse labels change the word-length pricing and are the first alphabet variant not covered by this result or the dihedral one.", + "first_step": "Re-run the same BFS with the four-label generator list (24 generators at r=2) against diag([z],[z]) and diag([xy],[yx]).", + "blocked_by": "Nothing technical; a bounded follow-up search of the same shape." + }, + { + "question": "Is the exact minimum still 4 for diag([z],[z],[z]) at r=3 (direct bill 6)?", + "why_it_matters": "Three active roles test whether sharing scales beyond pairs in the quaternion alphabet.", + "first_step": "Meet-in-the-middle over depth-3 balls with the 56 generators; memory cap and layer digests as here.", + "blocked_by": "State space growth; depth-5 coverage needs a meet, not a plain BFS." + } + ] +} diff --git a/research/q8-central-commutator-pair/VERIFY.json b/research/q8-central-commutator-pair/VERIFY.json new file mode 100644 index 0000000000..e338f3ddd2 --- /dev/null +++ b/research/q8-central-commutator-pair/VERIFY.json @@ -0,0 +1,23 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/bit-dihedral-commutator/README.md", + "research/bit-dihedral-commutator/TASK.json" + ], + "commands": [ + { + "argv": [ + "{python}", + "-I", + "-O", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 600, + "checks": "Q8 group laws, rank-one idempotent counts and idempotence, D_N(g)^2 = D_N(g^2), GL_r(F2) conjugation closure of the generator set, complete BFS layer digests to depth 3 at r=2 and r=3, three endpoints at their exact minimum, independent engine-B replay of every witness and direct word, omission controls for every witness call, mutated-target failure control, and certificate equality." + } + ] +} diff --git a/research/q8-central-commutator-pair/verify.py b/research/q8-central-commutator-pair/verify.py new file mode 100644 index 0000000000..f9aacc3d00 --- /dev/null +++ b/research/q8-central-commutator-pair/verify.py @@ -0,0 +1,467 @@ +"""Exact paid-call minima for central commutator targets in formal F2[Q8]. + +Model (see README): G = Q8 = {+-1, +-i, +-j, +-k}, paid labels x = i, y = j +only, paid factors D_N(g) = I + ([g]+1)N with N = u v^T, v^T u = 1, over +F2^r. Free scalar GL_r(F2) mixing is normalized by augmentation (predecessor +research/bit-dihedral-commutator argument; closure is checked below). + +Engine A (BFS): formal r x r matrices over F2[Q8] with 8-bit coefficient +masks and a precomputed 256x256 convolution table. Engine B (independent): +frozenset-of-group-elements formal matrices and Hamilton 4-tuple quaternion +multiplication. Acceptance is equality in every coefficient of the full +group algebra, not equality in one finite address representation. + +Stdlib only. python -I -O -B research/q8-central-commutator-pair/verify.py +""" +import hashlib +import json +import os +import sys + +# ---------------------------------------------------------------- Q8, engine A +# element index = 4*sign + unit: 0=+1, 1=+i, 2=+j, 3=+k, 4=-1, 5=-i, 6=-j, 7=-k +_UNIT_MUL = [ + [0, 1, 2, 3], + [1, 0, 3, 2], + [2, 3, 0, 1], + [3, 2, 1, 0], +] +_UNIT_SIGN = [ + [0, 0, 0, 0], + [0, 1, 0, 1], + [0, 1, 1, 0], + [0, 0, 1, 1], +] + + +def qmul(a, b): + sa, ua = divmod(a, 4) + sb, ub = divmod(b, 4) + s = (sa + sb + _UNIT_SIGN[ua][ub]) & 1 + return 4 * s + _UNIT_MUL[ua][ub] + + +G_TAB = [[qmul(a, b) for b in range(8)] for a in range(8)] + +MASK_MUL = [[0] * 256 for _ in range(256)] +for _a in range(256): + for _b in range(256): + _r = 0 + _bb = _b + while _bb: + _lb = _bb & -_bb + _h = _lb.bit_length() - 1 + _aa = _a + while _aa: + _la = _aa & -_aa + _g = _la.bit_length() - 1 + _r ^= 1 << G_TAB[_g][_h] + _aa ^= _la + _bb ^= _lb + MASK_MUL[_a][_b] = _r + + +def mat_mul(A, B, r): + C = [0] * (r * r) + for i in range(r): + for k in range(r): + a = A[i * r + k] + if a: + m = MASK_MUL[a] + for j in range(r): + C[i * r + j] ^= m[B[k * r + j]] + return tuple(C) + + +def identity_state(r): + return tuple(1 if i == j else 0 for i in range(r) for j in range(r)) + + +def gen_state(g, N, r): + lab = (1 << g) | 1 + cells = [0] * (r * r) + for idx, bit in enumerate(N): + if bit: + cells[idx] ^= lab + for i in range(r): + cells[i * r + i] ^= 1 + return tuple(cells) + + +def diag_state(entries, r): + cells = [0] * (r * r) + for i, g in enumerate(entries): + cells[i * r + i] = 1 << g + return tuple(cells) + + +# ------------------------------------------------------- rank-one idempotents +def rank_one_idempotents(r): + out = [] + for u in range(1, 1 << r): + for v in range(1, 1 << r): + if (u & v).bit_count() & 1: + N = tuple( + ((u >> i) & 1) * ((v >> j) & 1) + for i in range(r) + for j in range(r) + ) + out.append((u, v, N)) + out.sort() + return out + + +# -------------------------------------------------------------------- BFS +def bfs_ball(gens, r, max_depth): + I0 = identity_state(r) + seen = {I0: 0} + parents = {I0: None} + layers = [[I0]] + frontier = [I0] + for _d in range(1, max_depth + 1): + nxt = [] + for s in frontier: + for gi, g in enumerate(gens): + t = mat_mul(g, s, r) + if t not in seen: + seen[t] = _d + parents[t] = (s, gi) + nxt.append(t) + layers.append(nxt) + frontier = nxt + if not frontier: + break + return layers, parents + + +def state_digest(layers): + h = hashlib.sha256() + for layer in layers: + for s in sorted(layer): + h.update(bytes(s)) + return h.hexdigest() + + +def word_to(parents, target): + """Application-order generator index list, or None if outside the ball.""" + if target not in parents: + return None + word = [] + s = target + while parents[s] is not None: + s, gi = parents[s] + word.append(gi) + return list(reversed(word)) + + +def product_equals(gens, word, r, T): + acc = identity_state(r) + for gi in word: + acc = mat_mul(gens[gi], acc, r) + return acc == T + + +# ------------------------------------------------- engine B (independent replay) +def ham_mul(a, b): + aw, ax, ay, az = a + bw, bx, by, bz = b + return ( + aw * bw - ax * bx - ay * by - az * bz, + aw * bx + ax * bw + ay * bz - az * by, + aw * by - ax * bz + ay * bw + az * bx, + aw * bz + ax * by - ay * bx + az * bw, + ) + + +_HAM = [ + (1, 0, 0, 0), + (0, 1, 0, 0), + (0, 0, 1, 0), + (0, 0, 0, 1), + (-1, 0, 0, 0), + (0, -1, 0, 0), + (0, 0, -1, 0), + (0, 0, 0, -1), +] +_HAM_TO_IDX = {t: i for i, t in enumerate(_HAM)} + + +def ham_index(a, b): + return _HAM_TO_IDX[ham_mul(_HAM[a], _HAM[b])] + + +def b_mat_mul(A, B, r): + C = [set() for _ in range(r * r)] + for i in range(r): + for k in range(r): + if A[i * r + k]: + for j in range(r): + if B[k * r + j]: + base = C[i * r + j] + for ga in A[i * r + k]: + for gb in B[k * r + j]: + gh = ham_index(ga, gb) + if gh in base: + base.remove(gh) # F2 addition: pairs cancel + else: + base.add(gh) + return tuple(frozenset(s) for s in C) + + +def b_state(g, N, r): + lab = {g, 0} + cells = [set() for _ in range(r * r)] + for idx, bit in enumerate(N): + if bit: + cells[idx] ^= lab + for i in range(r): + cells[i * r + i] ^= {0} + return tuple(frozenset(s) for s in cells) + + +def b_diag(entries, r): + cells = [frozenset() for _ in range(r * r)] + for i, g in enumerate(entries): + cells[i * r + i] = frozenset({g}) + return tuple(cells) + + +def replay_word(gens_b, word, r): + acc = identity_state(r) + acc = tuple(frozenset({0}) if i == j else frozenset() + for i in range(r) for j in range(r)) + for gi in word: + acc = b_mat_mul(gens_b[gi], acc, r) + return acc + + +# ------------------------------------------------------- GL_r(F2) normalisation +def det2(M, r): + if r == 2: + return M[0] * M[3] ^ M[1] * M[2] + d = 0 + d ^= M[0] * (M[4] * M[8] ^ M[5] * M[7]) + d ^= M[1] * (M[3] * M[8] ^ M[5] * M[6]) + d ^= M[2] * (M[3] * M[7] ^ M[4] * M[6]) + return d + + +def gl_elements(r): + out = [] + for bits in range(1 << (r * r)): + M = tuple((bits >> t) & 1 for t in range(r * r)) + if det2(M, r): + out.append(M) + return out + + +def gl_invert(M, r): + a = [list(M[i * r:(i + 1) * r]) for i in range(r)] + inv = [[1 if i == j else 0 for j in range(r)] for i in range(r)] + for col in range(r): + piv = next(rw for rw in range(col, r) if a[rw][col]) + a[col], a[piv] = a[piv], a[col] + inv[col], inv[piv] = inv[piv], inv[col] + for rw in range(r): + if rw != col and a[rw][col]: + for k in range(r): + a[rw][k] ^= a[col][k] + inv[rw][k] ^= inv[col][k] + return tuple(x for row in inv for x in row) + + +# ------------------------------------------------------------------- checks +def expect(name, cond, msg=""): + if not cond: + print("FAIL", name, msg) + raise SystemExit(1) + + +ELEM = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7} + + +def group_laws(): + for a in range(8): + for b in range(8): + for c in range(8): + expect("assoc", qmul(qmul(a, b), c) == qmul(a, qmul(b, c))) + for a in range(8): + for b in range(8): + expect("ham-agree", ham_index(a, b) == qmul(a, b)) + x, y, z = 1, 2, 4 # i, j, -1 + expect("x2=z", qmul(x, x) == z) + expect("y2=z", qmul(y, y) == z) + expect("xyxy=z", qmul(qmul(qmul(x, y), x), y) == z) + expect("z2=e", qmul(z, z) == 0) + for a in range(8): + expect("z-central", qmul(z, a) == qmul(a, z)) + xi, yi = 5, 6 # -i, -j + expect("commutator", qmul(qmul(qmul(x, y), xi), yi) == z) + expect("k2=z", qmul(3, 3) == z) + + +def main(): + group_laws() + idem2 = rank_one_idempotents(2) + idem3 = rank_one_idempotents(3) + expect("idem2-count", len(idem2) == 6, str(len(idem2))) + expect("idem3-count", len(idem3) == 28, str(len(idem3))) + for u, v, N in idem2 + idem3: + r = 2 if len(N) == 4 else 3 + expect("idempotent", mat_mul(N, N, r) == N) + + x, y, z = 1, 2, 4 + here = os.path.dirname(os.path.abspath(__file__)) + cert_path = os.path.join(here, "CERTIFICATE.json") + + results = {} + for r, idem, depth in ((2, idem2, 3), (3, idem3, 3)): + gen_triples = [[g, u, v] for g in (x, y) for (u, v, N) in idem] + gens = [gen_state(g, N, r) for g in (x, y) for (u, v, N) in idem] + expect("gen-count", len(gens) == (12 if r == 2 else 56)) + for (g_lbl, u, v) in gen_triples: + N = next(N for (u2, v2, N) in idem if (u2, v2) == (u, v)) + expect( + "D-square", + mat_mul(gen_state(g_lbl, N, r), gen_state(g_lbl, N, r), r) + == gen_state(qmul(g_lbl, g_lbl), N, r), + ) + gls = gl_elements(r) + gen_set = set(gens) + for S in gls: + Sinv = gl_invert(S, r) + SD = mat_mul(S, gens[0], r) # warm path only + for g in gens: + conj = mat_mul(mat_mul(S, g, r), Sinv, r) + expect("gl-closure", conj in gen_set) + layers, parents = bfs_ball(gens, r, depth) + results[r] = dict( + generators=gen_triples, + layer_sizes=[len(L) for L in layers], + ball_sha256=state_digest(layers), + gl_order=len(gls), + parents=parents, + gens=gens, + idem=idem, + ) + + T1 = diag_state([z, z], 2) + T3 = diag_state([qmul(x, y), qmul(y, x)], 2) + T2 = diag_state([z, z, 0], 3) + C0 = identity_state(2) + Cx = diag_state([x, 0], 2) + Cz = diag_state([z, 0], 2) + + p2 = results[2]["parents"] + p3 = results[3]["parents"] + expect("control-I", word_to(p2, C0) == []) + w_Cx = word_to(p2, Cx) + w_Cz = word_to(p2, Cz) + expect("control-x", w_Cx is not None and len(w_Cx) == 1, str(w_Cx)) + expect("control-z", w_Cz is not None and len(w_Cz) == 2, str(w_Cz)) + + def direct_pair(entries, r): + word = [] + gen_triples = results[r]["generators"] + idx = {tuple(t): i for i, t in enumerate(gen_triples)} + letters = { + z: [x, x], + x: [x], + y: [y], + qmul(x, y): [x, y], + qmul(y, x): [y, x], + } + for pos, g in enumerate(entries): + if g == 0: + continue + u = v = 1 << pos + for let in letters[g]: + word.append(idx[(let, u, v)]) + return list(reversed(word)) + + direct = { + "diag_z_z_r2": direct_pair([z, z], 2), + "diag_xy_yx_r2": direct_pair([qmul(x, y), qmul(y, x)], 2), + "diag_z_z_e_r3": direct_pair([z, z, 0], 3), + } + targets = {"diag_z_z_r2": (T1, 2), "diag_xy_yx_r2": (T3, 2), "diag_z_z_e_r3": (T2, 3)} + + endpoints = {} + for name, (T, r) in targets.items(): + expect("direct-" + name, + product_equals(results[r]["gens"], direct[name], r, T)) + w = word_to(results[r]["parents"], T) + if w is None: + minimum = len(direct[name]) + witness_word = direct[name] + proven = "complete BFS to depth 3 excludes words of length <= 3" + else: + minimum = len(w) + witness_word = w + proven = "BFS distance is exact" + endpoints[name] = dict( + minimum=minimum, + witness=witness_word, + direct=direct[name], + proven=proven, + registers=r, + ) + gens_b = [b_state(g, N, r) for g in (x, y) for (u, v, N) in results[r]["idem"]] + Tb = b_diag([g for g in ([z, z] if name == "diag_z_z_r2" else + ([qmul(x, y), qmul(y, x)] if name == "diag_xy_yx_r2" + else [z, z, 0]))], r) + expect("indep-witness", replay_word(gens_b, witness_word, r) == Tb, name) + expect("indep-direct", replay_word(gens_b, direct[name], r) == Tb, name) + for pos in range(len(witness_word)): + sub = witness_word[:pos] + witness_word[pos + 1:] + expect("omission", not product_equals(results[r]["gens"], sub, r, T), + f"{name} del {pos}") + + mut = list(T1) + mut[0] ^= 1 + mut = tuple(mut) + expect("mutated-not-target", mut != T1) + expect("mutated-witness-fails", + not product_equals(results[2]["gens"], endpoints["diag_z_z_r2"]["witness"], 2, mut)) + + out = dict( + status="PASS_Q8_CENTRAL_COMMUTATOR", + group_order=8, + endpoints=endpoints, + r2_layers=results[2]["layer_sizes"], + r3_layers=results[3]["layer_sizes"], + r2_ball_sha256=results[2]["ball_sha256"], + r3_ball_sha256=results[3]["ball_sha256"], + r2_generators=results[2]["generators"], + r3_generator_count=len(results[3]["generators"]), + gl2_order=results[2]["gl_order"], + gl3_order=results[3]["gl_order"], + omission_controls=sum(len(v["witness"]) for v in endpoints.values()), + controls=4, + independent_engine_b=True, + new_kappa=False, + ) + + if "--emit" in sys.argv: + with open(cert_path, "w", encoding="utf-8") as fh: + json.dump(out, fh, indent=2, sort_keys=True) + fh.write("\n") + print("EMITTED", cert_path) + + with open(cert_path, "r", encoding="utf-8") as fh: + cert = json.load(fh) + for key, val in out.items(): + expect("cert-" + key, cert.get(key) == val, + f"{key}: cert={cert.get(key)!r} got={val!r}") + + print( + "PASS_Q8_CENTRAL_COMMUTATOR", + " ".join(f"{k}:{v['minimum']}" for k, v in endpoints.items()), + f"r2_layers={results[2]['layer_sizes']}", + f"r3_layers={results[3]['layer_sizes']}", + "no_new_kappa", + ) + + +if __name__ == "__main__": + main()