From 0cee0e104b68ce6f06bf84af03f46ac30680e64c Mon Sep 17 00:00:00 2001 From: Nick Petalas Date: Wed, 28 Oct 2026 00:27:57 +0000 Subject: [PATCH] feat(research): prove the conjugate-pair four-call floor in every group Corner sandwiches with the first and last projectors replace the group-specific support filter of #4089 and #4093, so the floor holds for every noncommuting pair, coefficient field and width. --- research/conjugate-pair-every-group/PROOF.md | 151 ++++++++ research/conjugate-pair-every-group/README.md | 106 ++++++ .../conjugate-pair-every-group/SOURCES.json | 36 ++ research/conjugate-pair-every-group/TASK.json | 70 ++++ .../conjugate-pair-every-group/VERIFY.json | 32 ++ research/conjugate-pair-every-group/verify.py | 355 ++++++++++++++++++ 6 files changed, 750 insertions(+) create mode 100644 research/conjugate-pair-every-group/PROOF.md create mode 100644 research/conjugate-pair-every-group/README.md create mode 100644 research/conjugate-pair-every-group/SOURCES.json create mode 100644 research/conjugate-pair-every-group/TASK.json create mode 100644 research/conjugate-pair-every-group/VERIFY.json create mode 100644 research/conjugate-pair-every-group/verify.py diff --git a/research/conjugate-pair-every-group/PROOF.md b/research/conjugate-pair-every-group/PROOF.md new file mode 100644 index 0000000000..46d33fc3b9 --- /dev/null +++ b/research/conjugate-pair-every-group/PROOF.md @@ -0,0 +1,151 @@ +# The conjugate-pair target needs four calls in every group + +**Scoped written theorem in a formal group-algebra model; no new κ.** + +## Model + +Let `G` be any group, `F` any field and `x, y ∈ G` with `xy ≠ yx`. Fix a +width `r ≥ 2`. A paid factor is + +```text +D_N(g) = I + ([g] - [e]) N, g ∈ {x, y}, +``` + +where `N ∈ M_r(F)` is a rank-one idempotent, `N = u vᵀ` with `vᵀu = 1`. +Over `F = F2` this is exactly the factor `I + ([g]+[e])N` of +[#4089](https://github.com/CrocSwap/integer-mult-bounds/pull/4089). Roles +beyond the first two are arbitrary dirty spectators that must return to `[e]`. +The target is + +```text +T = diag([xy], [yx], [e], …, [e]) ∈ M_r(F[G]). +``` + +**Theorem.** The minimum number of paid factors whose chronological product +equals `T` is exactly four. + +The direct word `D_{E00}(x) D_{E00}(y) D_{E11}(y) D_{E11}(x)` attains `T` for +every `G`, `F` and `r ≥ 2`. The rest of this file excludes every shorter word. + +## Expansion + +Write `N̄ = I - N`. Then `D_N(g) = [g] N + N̄`. Hence, for labels +`g_1, …, g_k` and idempotents `N_1, …, N_k`, + +```text +D_{N_1}(g_1) ⋯ D_{N_k}(g_k) = Σ_{U ⊆ {1..k}} [g_U] P_U, +P_U = X_1 ⋯ X_k, X_i = N_i if i ∈ U, else N̄_i, +``` + +where `g_U` is the ordered product of the labels in `U`. Since the elements +`[w] E_ij` form an `F`-basis of `M_r(F[G])`, the word realizes `T` if and only +if, for every `w ∈ G`, + +```text +Σ_{U : g_U = w} P_U = T_w, +``` + +with `T_xy = E00`, `T_yx = E11`, `T_e = I - E00 - E11` and `T_w = 0` otherwise. +These are well defined because `xy`, `yx` and `e` are distinct (below). + +**Facts about the pair.** Each item follows by cancellation, and each +violation would make `x` and `y` commute: + +* (F1) `x, y ∉ {e, xy, yx}` and `x ≠ y`; +* (F2) `xy, yx ∉ {e, x, y, x², y²}`; +* (F3) `x²y ≠ xy`, `xy² ≠ xy`, `y²x ≠ yx`, `yx² ≠ yx`, `xyx ∉ {xy, yx}`, + `yxy ∉ {xy, yx}`, and `x³, y³` cannot both equal `xy` and `yx`. + +For example, `xy = x²` gives `y = x`, and `xyx = xy` gives `x = e`. + +## Words of length at most two + +For `k ≤ 1` the only values `g_U` are `e` and one label, so by (F1) and (F2) +`T_xy = E00 ≠ 0` cannot be produced. For `k = 2`, the values are `e`, `g_1`, +`g_2` and `g_1 g_2`. By (F2) only `g_1 g_2` can equal `xy` or `yx`, and it +equals at most one of them. One of the nonzero coefficients `E00`, `E11` is +therefore missing. + +## Words of length three + +From `N² = N` and `N N̄ = N̄ N = 0`: + +```text +N_1 P_U = P_U if 1 ∈ U, else 0; N̄_1 P_U = P_U if 1 ∉ U, else 0; +P_U N_3 = P_U if 3 ∈ U, else 0; P_U N̄_3 = P_U if 3 ∉ U, else 0. +``` + +So each sandwich `A T_w B`, with `A ∈ {N_1, N̄_1}` and `B ∈ {N_3, N̄_3}`, keeps +exactly the subsets `U` with `g_U = w` in one corner. The four corners are +`{∅, {2}}`, `{{1}, {1,2}}`, `{{3}, {2,3}}` and `{{1,3}, {1,2,3}}`. Also +`T_w = (N_1 + N̄_1) T_w (N_3 + N̄_3)`. + +**Lemma 1.** `P_{1} = P_{2} = P_{3} = 0`. + +*Proof.* In corner `(N_1, N̄_3)` the values are `g_1` and `g_1 g_2 ≠ g_1`, so +`N_1 T_{g_1} N̄_3 = P_{1}`; by (F1), `T_{g_1} = 0`. In the same way +`N̄_1 T_{g_3} N_3 = P_{3}` (values `g_3`, `g_2 g_3 ≠ g_3`) and +`N̄_1 T_{g_2} N̄_3 = P_{2}` (values `e`, `g_2 ≠ e`). ∎ + +**Lemma 2.** For `w ∈ {xy, yx}`, `N̄_1 T_w N̄_3 = 0`. + +*Proof.* That corner has values `e` and `g_2`, neither of which is `w` by +(F1) and (F2). ∎ + +**Lemma 3.** `P_{12}` and `P_{23}` are not both nonzero. + +*Proof.* Write `N_i = u_i v_iᵀ`. Then `P_{12} = u_1 (v_1ᵀu_2)(v_2ᵀ N̄_3)`, +`P_{23} = (N̄_1 u_2)(v_2ᵀu_3) v_3ᵀ` and `P_{2} = (N̄_1 u_2)(v_2ᵀ N̄_3)`. If both +are nonzero, then `v_2ᵀ N̄_3 ≠ 0` and `N̄_1 u_2 ≠ 0`. Their outer product +`P_{2}` is then nonzero, contrary to Lemma 1. ∎ + +Now go through the eight label patterns. Write `E_a = e_a e_aᵀ`. + +**`xxx`, `yyy`.** The subsets of size at least two have values `x², x³` +(or `y², y³`). By (F2) and (F3) they cannot supply both `xy` and `yx`. + +**`xyx`, `yxy`.** For `xyx`, `g_{12} = xy`, `g_{23} = yx`, `g_{13} = x²` and +`g_{123} = xyx`. By (F2) and (F3), only `{1,2}` has value `xy` and only `{2,3}` +has value `yx`. Using the corner split and Lemma 2, `E00 = T_xy = P_{12}` and +`E11 = T_yx = P_{23}`. Both are nonzero, contradicting Lemma 3. The pattern +`yxy` is identical with `E00` and `E11` exchanged. + +**`xxy`, `yyx`.** For `xxy`, `g_{12} = x²`, `g_{13} = g_{23} = xy` and +`g_{123} = x²y ≠ xy`. The value `yx` can only come from `{1,2,3}`, so the word +fails unless `x²y = yx`; assume this. Put `a = 0`, `b = 1`; then +`T_xy = E_a` is carried by `{1,3}, {2,3}` and `T_yx = E_b` by `{1,2,3}` alone. +For `yyx` the same holds with `a = 1`, `b = 0` (and `y²x = xy` assumed). + +* `E_b` lies only in corner `(N_1, N_3)`, so `E_b = N_1 E_b N_3 + = u_1 (v_1ᵀ E_b u_3) v_3ᵀ`. Hence `u_1` and `v_3` are nonzero multiples of + `e_b`. +* `N_1 E_a N̄_3 = 0` because `{1,2}` has value `x²` (resp. `y²`). Therefore + `N_1 E_a = N_1 E_a N_3 = P_{13} = u_1 (v_1ᵀ N̄_2 u_3) v_3ᵀ`, a multiple of + `e_b e_bᵀ`. But `N_1 E_a = u_1 (v_1ᵀ e_a) e_aᵀ` is a multiple of `e_b e_aᵀ`. + So `N_1 E_a = 0` and `N̄_1 E_a = E_a`. +* Lemma 2 gives `0 = N̄_1 E_a N̄_3 = E_a N̄_3`, so + `E_a = E_a N_3 = e_a (e_aᵀ u_3) v_3ᵀ`, a multiple of `e_a e_bᵀ`. This is false. + +**`xyy`, `yxx`.** For `xyy`, `g_{12} = g_{13} = xy`, `g_{23} = y²` and +`g_{123} = xy² ≠ xy`. Then `yx` can only come from `{1,2,3}`; assume +`xy² = yx`. With `a = 0`, `b = 1` (for `yxx`: `a = 1`, `b = 0`): + +* As before, `E_b = N_1 E_b N_3`, so `u_1` and `v_3` are multiples of `e_b`. +* `N̄_1 E_a N_3 = 0` because `{2,3}` has value `y²` (resp. `x²`). Therefore + `E_a N_3 = N_1 E_a N_3 = P_{13}`, a multiple of `e_b e_bᵀ`, while + `E_a N_3 = e_a (e_aᵀ u_3) v_3ᵀ` is a multiple of `e_a e_bᵀ`. So + `E_a N_3 = 0` and `E_a N̄_3 = E_a`. +* Lemma 2 gives `0 = N̄_1 E_a N̄_3 = N̄_1 E_a`, so + `E_a = N_1 E_a = u_1 (v_1ᵀ e_a) e_aᵀ`, a multiple of `e_b e_aᵀ`. False. + +Every pattern fails, so no word of length three realizes `T`. ∎ + +## What is used and what is not + +The proof uses only the coefficient equations, `xy ≠ yx` and rank one of each +`N_i`. It uses no generation hypothesis, perfectness, element orders, support +filter or finite census. The noncommuting hypothesis is necessary: for +`y = x⁻¹` the target is `I` and is met by the empty word. + +This is a formal group-algebra theorem. It prices no native address +operation and does not change the selected κ. diff --git a/research/conjugate-pair-every-group/README.md b/research/conjugate-pair-every-group/README.md new file mode 100644 index 0000000000..47bb74c139 --- /dev/null +++ b/research/conjugate-pair-every-group/README.md @@ -0,0 +1,106 @@ +# The conjugate-pair target needs four calls in every group + +**Scoped written theorem in a formal group-algebra model, with finite +corroboration; no new κ.** This contribution was produced by Nick Petalas. +New work is Apache-2.0. + +Let `G` be any group, `F` any field and `x, y ∈ G` with `xy ≠ yx`. In the +rank-one-idempotent register model of +[#4089](https://github.com/CrocSwap/integer-mult-bounds/pull/4089), with paid +factors `I + ([g]-[e])N` for `g ∈ {x, y}`, the target + +```text +T = diag([xy], [yx], [e], …, [e]) ∈ M_r(F[G]) +``` + +has exact paid-call minimum **four** at every width `r ≥ 2`. Extra dirty +spectator roles never lower the bill. + +This answers Open next question 2 of Wentao Li's +[#4089](https://github.com/CrocSwap/integer-mult-bounds/pull/4089) +(`research/a5-conjugate-any-registers`) for every conjugate-pair alphabet at +once. #4089 proves the A5 case over F2 and Wentao Li's +[#4093](https://github.com/CrocSwap/integer-mult-bounds/pull/4093) proves +PSL(2,7). Both use a support filter specific to their group: they check that +only `xyx` and `yxy` can carry both `xy` and `yx`. In a general group, +coincidences such as `x²y = yx` defeat that filter. The new proof handles them. + +## The new step + +[PROOF.md](PROOF.md) has the full argument. Each factor is written as +`[g]N + (I-N)`, so a three-call product is `Σ_U [g_U] P_U` with +`P_U = X_1 X_2 X_3` and `X_i ∈ {N_i, I-N_i}`. Multiplying a coefficient on the +left by `N_1` or `I-N_1` and on the right by `N_3` or `I-N_3` isolates one +corner of subsets. This yields three uniform lemmas: + +1. the single-call products `P_{1}, P_{2}, P_{3}` vanish; +2. the `(I-N_1, I-N_3)` corner of the `xy` and `yx` coefficients vanishes; +3. `P_{12}` and `P_{23}` are not both nonzero. + +The patterns `xyx` and `yxy` then fail by Lemma 3. The patterns `xxy`, `yyx`, +`xyy` and `yxx`, which can survive the support test when `G` has a suitable +coincidence, fail by a rank-one column/row mismatch. Words of length at most +two fail by support alone. The proof uses no generation, perfectness, element +order or field characteristic. + +The noncommuting hypothesis is needed: for `y = x⁻¹` the target is `I`. + +## Evidence + +| Claim | Kind | Evidence | +|---|---|---| +| no word of length ≤ 3, every `G`, `F`, `r` | written proof | [PROOF.md](PROOF.md) | +| four calls suffice | construction | direct word `D_{E00}(x) D_{E00}(y) D_{E11}(y) D_{E11}(x)` | +| finite cross-check | exact finite certificate | `verify.py` | + +`verify.py` checks the expansion and corner identities on 200 seeded rational +triples. It collects the 82 distinct length-4 word-coincidence signatures of +noncommuting pairs in S3, S4, S5, Q8 and the free group. The direct word and +its four one-call deletions are checked on each. Their words of length 1..3 +reduce to 26 subset-class keys. Every key is excluded exhaustively over F2 at +widths 2 and 3 and over F3 at width 2. The finite check corroborates the proof +and does not replace it: it covers neither all groups nor all widths. + +## Reproduce + +From the repository root, with standard-library CPython 3.12: + +```sh +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B -W error research/conjugate-pair-every-group/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -O -B -W error research/conjugate-pair-every-group/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/research_package.py --package research/conjugate-pair-every-group +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/check_research_commit.py --package research/conjugate-pair-every-group --check-source-history +``` + +Any CPython 3.12 may replace that interpreter path. The expected marker is +`PASS_CONJUGATE_PAIR_EVERY_GROUP`; each run takes about five seconds locally. + +## Limits + +This is a theorem in the formal group-algebra model only. It prices no native +address operation, conversion, restoration or recursive caller, and it is not +a multiplication theorem. The selected κ is unchanged. The proof has had no +independent human or proof-kernel review. + +## Open next questions + +1. Which diagonal pair targets `diag([g],[h])` in an arbitrary group admit + cross-register sharing below the sum of their positive word lengths? The + corner-sandwich lemmas may give uniform floors in place of per-group + censuses such as the S3 and Q8 pair censuses. First step: try + `diag([xyx],[yxy])` at length five. Longer words have more corners and + coincidence patterns; no general lemma is supplied here. +2. Is there a priced native nonabelian address alphabet inside an admitted + BIT supplier? This theorem shows that the conjugate-pair target offers no + saving in any group, so such a proposal must find its gain elsewhere. + +The same questions are structured in [TASK.json](TASK.json). + +## Credit + +Wentao Li ([#4089](https://github.com/CrocSwap/integer-mult-bounds/pull/4089), +[#4093](https://github.com/CrocSwap/integer-mult-bounds/pull/4093)) supplied +the model, the any-register A5 and PSL(2,7) theorems and the open question. +Cinna Davis ([#2246](https://github.com/CrocSwap/integer-mult-bounds/pull/2246)) +supplied the original A5 target and its fixed-width result. Their results are +cited, not re-checked. Source pins are in [SOURCES.json](SOURCES.json). diff --git a/research/conjugate-pair-every-group/SOURCES.json b/research/conjugate-pair-every-group/SOURCES.json new file mode 100644 index 0000000000..43a163a151 --- /dev/null +++ b/research/conjugate-pair-every-group/SOURCES.json @@ -0,0 +1,36 @@ +{ + "schema_version": 1, + "base_commit": "19fdb086ea96af9a9f87936a2b888e10af4ed810", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "581f8d87008354eb5b869f7ed9de1317ad837ce8", + "sha256": "2a0220e866417774606e0f991e41b9c1d26b1f43b97857238cf478dbc7d330b5" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "3404fbdd5e7529a0674eef26114b5071e4586cec", + "sha256": "ead6cdc9d0af6d58e8a49744d8ec8c7c15e13d2ba93c276c434bcf9b51b93a81" + }, + { + "path": "research/a5-conjugate-any-registers/PROOF.md", + "usage": "provenance", + "git_blob": "a72b89bdd2428b78c6424d2d2299bdb1ac2981d3", + "sha256": "921a84d24148d27932aad24a9a5d74bd235de0c1b2f27c2b9bfc5d37fcf51dcf" + }, + { + "path": "research/psl27-conjugate-any-registers/README.md", + "usage": "provenance", + "git_blob": "a26e49a053f9a746cb5b452cbc77c3b8c1e446b0", + "sha256": "8d272a7b19d4c9df2e945713850ba90c45274e99ebc317c20228c31618e8c175" + }, + { + "path": "research/a5-conjugate-any-registers/README.md", + "usage": "provenance", + "git_blob": "92fa82d936248c7e3485e4ea3aecac88f42988f9", + "sha256": "26246a1b0448048f59d2a80e09addcf80950d728f2c768e56d32f145c59fd773" + } + ] +} diff --git a/research/conjugate-pair-every-group/TASK.json b/research/conjugate-pair-every-group/TASK.json new file mode 100644 index 0000000000..963d3138b7 --- /dev/null +++ b/research/conjugate-pair-every-group/TASK.json @@ -0,0 +1,70 @@ +{ + "schema_version": 1, + "task_id": "bit-new-register-model", + "priority_revision": 8, + "base_commit": "19fdb086ea96af9a9f87936a2b888e10af4ed810", + "original_card": { + "id": "bit-new-register-model", + "question": "Can an explicitly larger or nonabelian register model escape the scoped three-register obstruction?", + "starting_points": [ + "docs/research/research-family-status.md", + "research/bit-three-register-lower-bound/README.md", + "certificates/selected-result.json", + "research/bit-gl3-mixed-targets-length10/README.md", + "docs/research/community-efficient1000-review.md" + ], + "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. A scoped local result may be retained without a complete supplier. Expanding it into further construction rounds requires the family-level budget and obligation gate in research-family-status.md; an optimistic passing relaxation alone is not acceptance.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_selected_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Resolve the current selected review, separate complex/ordinary BIT/admitted BIT/outer budgets, and compare the card against live handoffs before starting. Historical ceilings require exact source/model equivalence.", + "scope": "Source-binding orientation only; not a scientific replay or all-size proof. Materialize selected inputs if this checkout is sparse." + }, + "first_experiment": "First compare the alphabet, role count and length with the fully replayed #1974 census and #2027 mixed-root tariff. Identify a changed premise and a legal native implementation; then price one smallest completed instance before searching larger words.", + "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.", + "Repeating the two-register GL3 census or a covered three-register length without changing a hypothesis; a formal group-algebra word without native conversion is a partial result." + ], + "overlap_terms": [ + "three-register", + "nonabelian", + "group algebra" + ] + }, + "scope_status": "changed", + "actual_scope": "Open next question 2 of PR #4089 (research/a5-conjugate-any-registers): do any-register four-call floors for diag([xy],[yx],[e],...,[e]) hold for other conjugate-pair alphabets? Answered for every group G, every pair x,y in G with xy != yx, every coefficient field and every width r >= 2, in the same formal rank-one-idempotent group-algebra model.", + "scope_change_reason": "The card asks about larger or nonabelian register models. PR #4089 and PR #4093 settle A5 and PSL(2,7) with group-specific support filters; a uniform statement removes the need for further per-group censuses in this model.", + "bottleneck_link": "Side result for the bit-new-register-model family: it closes the cross-register sharing question for this two-role conjugate-pair target in every nonabelian address group, so a native nonabelian BIT proposal cannot save calls on it. It does not price any native operation.", + "budget_minutes": 60, + "stop_rule": "Stop at a written proof plus finite corroboration; do not search larger words or other targets.", + "outcome": "completed", + "evidence": "PROOF.md (written all-group, all-field, all-width proof); verify.py (finite corroboration: 82 signatures, 26 keys, F2 widths 2-3 and F3 width 2, PASS_CONJUGATE_PAIR_EVERY_GROUP).", + "author": "Nick Petalas", + "ai_assistance": "Independent human and formal proof-kernel review are unclaimed.", + "open_questions": [ + { + "question": "Which diagonal pair targets diag([g],[h]) in an arbitrary group admit cross-register sharing below the sum of their positive word lengths?", + "why_it_matters": "The corner-sandwich method may give uniform floors for longer targets, replacing per-group censuses such as the S3 and Q8 pair censuses.", + "first_step": "Try targets diag([xyx],[yxy]) or diag([xy],[xy]) with the same corner lemmas, starting at length five.", + "blocked_by": "Longer words have more corners and more coincidence patterns; no general lemma is supplied here." + }, + { + "question": "Is there a priced native realization of a nonabelian label alphabet inside an admitted BIT supplier?", + "why_it_matters": "This theorem shows that the conjugate-pair target offers no saving in any group, so a native proposal must find its gain elsewhere.", + "first_step": "Name one runtime address operation and give its full entrance, exit and restoration invoice.", + "blocked_by": "No native nonabelian address contract exists in the selected supplier." + } + ] +} diff --git a/research/conjugate-pair-every-group/VERIFY.json b/research/conjugate-pair-every-group/VERIFY.json new file mode 100644 index 0000000000..1d62ce2cd0 --- /dev/null +++ b/research/conjugate-pair-every-group/VERIFY.json @@ -0,0 +1,32 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [], + "commands": [ + { + "argv": [ + "{python}", + "-B", + "-W", + "error", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Exact expansion and corner identities on 200 rational triples; direct four-call word and its four one-call deletions on 82 noncommuting length-4 signatures (S3, S4, S5, Q8, free group); exhaustive exclusion of every word of length 1..3 for all 26 subset-class keys over F2 at widths 2 and 3 and over F3 at width 2; inverse-pair control." + }, + { + "argv": [ + "{python}", + "-O", + "-B", + "-W", + "error", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Same checks under optimized execution; the verifier uses explicit exceptions, not assert." + } + ] +} diff --git a/research/conjugate-pair-every-group/verify.py b/research/conjugate-pair-every-group/verify.py new file mode 100644 index 0000000000..75ee7b2e86 --- /dev/null +++ b/research/conjugate-pair-every-group/verify.py @@ -0,0 +1,355 @@ +#!/usr/bin/env python3 +"""Finite corroboration for the every-group conjugate-pair four-call floor. + +The written proof is PROOF.md. This verifier checks, with exact arithmetic: + +1. the factor and product expansions used by the proof, on seeded random + rational and binary instances; +2. the corner-selection identities N1 P_U N3 = P_U or 0 used by Lemma 1; +3. the direct four-call word, for every signature and checked field/width; +4. that no word of length at most three realizes the target, for every + distinct length-three coincidence signature of a noncommuting pair in + S3, S4, S5, Q8 and the free group, over F2 at widths 2 and 3 and over F3 + at width 2; +5. failure controls: the four-call word with one call removed, and the + commuting pair y = x^-1, whose target is the identity. + +Standard library only. Prints PASS_CONJUGATE_PAIR_EVERY_GROUP on success. +""" + +import itertools +import random +import sys +from fractions import Fraction + +MARKER = "PASS_CONJUGATE_PAIR_EVERY_GROUP" +WORDS = tuple(w for k in range(5) for w in itertools.product("xy", repeat=k)) + + +def require(condition, message): + if not condition: + raise SystemExit("FAIL: " + message) + + +# ---------------------------------------------------------------- matrices + +def mat_mul(a, b, p): + n = len(a) + return tuple( + tuple(sum(a[i][k] * b[k][j] for k in range(n)) % p for j in range(n)) + for i in range(n) + ) + + +def mat_add(a, b, p): + return tuple(tuple((x + y) % p for x, y in zip(r, s)) for r, s in zip(a, b)) + + +def mat_sub(a, b, p): + return tuple(tuple((x - y) % p for x, y in zip(r, s)) for r, s in zip(a, b)) + + +def identity(n): + return tuple(tuple(int(i == j) for j in range(n)) for i in range(n)) + + +def zero(n): + return tuple(tuple(0 for _ in range(n)) for _ in range(n)) + + +def unit(n, i): + return tuple(tuple(int(a == i and b == i) for b in range(n)) for a in range(n)) + + +def rank_one_idempotents(r, p): + """All N = u v^T over F_p with v^T u = 1 (each N listed once).""" + vectors = [v for v in itertools.product(range(p), repeat=r) if any(v)] + found = set() + for u in vectors: + for v in vectors: + if sum(a * b for a, b in zip(u, v)) % p == 1: + found.add(tuple(tuple(a * b % p for b in v) for a in u)) + expected = (p ** r - 1) * p ** (r - 1) // (p - 1) + require(len(found) == expected, "idempotent count at r=%d p=%d" % (r, p)) + return sorted(found) + + +# ---------------------------------------------------------- group signatures + +def compose(a, b): + """Group product a*b for permutations: apply b first.""" + return tuple(a[i] for i in b) + + +def signature(x, y, e, mul): + """Partition of all positive words of length <= 4 by group value.""" + index = {} + labels = [] + for word in WORDS: + g = e + for c in word: + g = mul(g, x if c == "x" else y) + labels.append(index.setdefault(g, len(index))) + return tuple(labels) + + +def permutation_signatures(): + sigs = {} + for n in (3, 4, 5): + elements = list(itertools.permutations(range(n))) + e = tuple(range(n)) + for x in elements: + for y in elements: + if compose(x, y) != compose(y, x): + sigs.setdefault(signature(x, y, e, compose), "S%d" % n) + return sigs + + +def quaternion_signatures(): + # Q8 as pairs (sign, unit) with units 1,i,j,k. + table = { + ("1", u): (1, u) for u in "1ijk" + } + table.update({(u, "1"): (1, u) for u in "1ijk"}) + table.update({ + ("i", "i"): (-1, "1"), ("j", "j"): (-1, "1"), ("k", "k"): (-1, "1"), + ("i", "j"): (1, "k"), ("j", "i"): (-1, "k"), + ("j", "k"): (1, "i"), ("k", "j"): (-1, "i"), + ("k", "i"): (1, "j"), ("i", "k"): (-1, "j"), + }) + + def mul(a, b): + s, u = table[(a[1], b[1])] + return (a[0] * b[0] * s, u) + + elements = [(s, u) for s in (1, -1) for u in "1ijk"] + sigs = {} + for x in elements: + for y in elements: + if mul(x, y) != mul(y, x): + sigs.setdefault(signature(x, y, (1, "1"), mul), "Q8") + return sigs + + +def free_signature(): + return {signature("x", "y", "", lambda a, b: a + b): "free"} + + +def word_value(sig, word): + return sig[WORDS.index(word)] + + +# ------------------------------------------------------------ word products + +def corner_products(ns, p): + """P_U for every subset U (bitmask over call positions).""" + r = len(ns[0]) + comps = [mat_sub(identity(r), n, p) for n in ns] + out = {} + for mask in range(1 << len(ns)): + prod = identity(r) + for i, n in enumerate(ns): + prod = mat_mul(prod, n if mask >> i & 1 else comps[i], p) + out[mask] = prod + return out + + +def coefficients(sig, labels, ns, p): + """Group-algebra coefficients of a chronological product of paid factors.""" + r = len(ns[0]) + acc = {} + for mask, prod in corner_products(ns, p).items(): + word = tuple(labels[i] for i in range(len(labels)) if mask >> i & 1) + g = word_value(sig, word) + acc[g] = mat_add(acc.get(g, zero(r)), prod, p) + return acc + + +def target(sig, r): + rest = tuple(tuple(int(i == j and i >= 2) for j in range(r)) for i in range(r)) + out = {word_value(sig, ()): rest} + for word, role in ((("x", "y"), 0), (("y", "x"), 1)): + g = word_value(sig, word) + out[g] = mat_add(out.get(g, zero(r)), unit(r, role), 2 ** 31) + return out + + +def realizes(sig, labels, ns, p): + r = len(ns[0]) + got = coefficients(sig, labels, ns, p) + want = {g: tuple(tuple(v % p for v in row) for row in m) + for g, m in target(sig, r).items()} + for g in set(got) | set(want): + if got.get(g, zero(r)) != want.get(g, zero(r)): + return False + return True + + +def class_key(sig, labels): + """Canonical map from call subsets to coefficient classes. + + Realizability of the target depends only on this key: which subsets share + a group value, and which classes are e, xy and yx. + """ + special = {word_value(sig, ()): "e", word_value(sig, ("x", "y")): "xy", + word_value(sig, ("y", "x")): "yx"} + names = {} + key = [] + for mask in range(1 << len(labels)): + word = tuple(labels[i] for i in range(len(labels)) if mask >> i & 1) + g = word_value(sig, word) + key.append(special.get(g) or names.setdefault(g, len(names))) + return tuple(key) + + +def key_realizable(key, products, r, p): + want = {"e": tuple(tuple(int(i == j and i >= 2) for j in range(r)) + for i in range(r)), + "xy": unit(r, 0), "yx": unit(r, 1)} + if "xy" not in key or "yx" not in key: + return False + for cls in ("xy", "yx", "e") + tuple(sorted(c for c in set(key) + if isinstance(c, int))): + acc = zero(r) + for mask, c in enumerate(key): + if c == cls: + acc = mat_add(acc, products[mask], p) + if acc != want.get(cls, zero(r)): + return False + return True + + +def short_word_keys(sigs): + keys = set() + for sig in sigs: + for k in (1, 2, 3): + for labels in itertools.product("xy", repeat=k): + keys.add(class_key(sig, labels)) + return keys + + +def no_short_word(keys, idems, p): + """Exhaustive search over every word of length 1..3 for every key.""" + r = len(idems[0]) + by_len = {} + for key in keys: + by_len.setdefault(len(key), []).append(key) + for size, group in by_len.items(): + k = size.bit_length() - 1 + for ns in itertools.product(idems, repeat=k): + products = corner_products(ns, p) + for key in group: + if key_realizable(key, products, r, p): + return False + return True + + +# ----------------------------------------------------------------- checks + +def check_expansion_identities(): + """D_N(g) = [g]N + (I-N) and the corner selection identities.""" + rng = random.Random(20261028) + for _ in range(200): + r = rng.choice((2, 3, 4)) + ns = [] + for _ in range(3): + while True: + u = [Fraction(rng.randint(-3, 3)) for _ in range(r)] + v = [Fraction(rng.randint(-3, 3)) for _ in range(r)] + s = sum(a * b for a, b in zip(u, v)) + if s != 0: + break + ns.append(tuple(tuple(a * b / s for b in v) for a in u)) + eye = tuple(tuple(Fraction(int(i == j)) for j in range(r)) for i in range(r)) + + def mm(a, b): + return tuple(tuple(sum(a[i][k] * b[k][j] for k in range(r)) + for j in range(r)) for i in range(r)) + + def ms(a, b): + return tuple(tuple(x - y for x, y in zip(c, d)) for c, d in zip(a, b)) + + for n in ns: + require(mm(n, n) == n, "rational idempotent") + require(mm(n, ms(eye, n)) == mm(ms(eye, n), n) == ms(eye, eye), + "complementary idempotents annihilate") + comps = [ms(eye, n) for n in ns] + zero_r = ms(eye, eye) + for mask in range(8): + prod = eye + for i in range(3): + prod = mm(prod, ns[i] if mask >> i & 1 else comps[i]) + left = mm(ns[0], prod) + right = mm(prod, ns[2]) + require(left == (prod if mask & 1 else zero_r), + "left corner selection") + require(right == (prod if mask & 4 else zero_r), + "right corner selection") + bar_left = mm(comps[0], prod) + require(bar_left == (prod if not mask & 1 else zero_r), + "left complement selection") + # Sum over subsets of P_U equals I: the product of (N_i + (I - N_i)). + total = tuple(tuple(Fraction(0) for _ in range(r)) for _ in range(r)) + for mask in range(8): + prod = eye + for i in range(3): + prod = mm(prod, ns[i] if mask >> i & 1 else comps[i]) + total = tuple(tuple(a + b for a, b in zip(c, d)) + for c, d in zip(total, prod)) + require(total == eye, "subset expansion sums to identity") + return 200 + + +def check_direct_word(sig, r, p): + labels = ("x", "y", "y", "x") + ns = (unit(r, 0), unit(r, 0), unit(r, 1), unit(r, 1)) + require(realizes(sig, labels, ns, p), "direct four-call word") + for drop in range(4): + sub_l = labels[:drop] + labels[drop + 1:] + sub_n = ns[:drop] + ns[drop + 1:] + require(not realizes(sig, sub_l, sub_n, p), "mutated direct word rejected") + + +def check_commuting_control(): + """The noncommuting hypothesis is needed: y = x^-1 gives target I.""" + e = (0, 1, 2) + x = (1, 2, 0) + y = (2, 0, 1) + require(compose(x, y) == e == compose(y, x), "inverse control pair") + sig = signature(x, y, e, compose) + r = 2 + got = target(sig, r) + require(got == {word_value(sig, ()): identity(r)}, + "inverse pair target is the identity, met by the empty word") + return r + + +def main(): + checked = check_expansion_identities() + print("expansion and corner identities: %d random rational triples" % checked) + sigs = {} + sigs.update(permutation_signatures()) + sigs.update(quaternion_signatures()) + sigs.update(free_signature()) + print("distinct noncommuting length-4 signatures: %d" % len(sigs)) + keys = short_word_keys(sigs) + print("distinct subset-class keys for words of length 1..3: %d" % len(keys)) + for sig in sigs: + require(word_value(sig, ()) not in + (word_value(sig, ("x", "y")), word_value(sig, ("y", "x"))), + "the empty word cannot realize the target") + for (r, p) in ((2, 2), (3, 2), (2, 3)): + idems = rank_one_idempotents(r, p) + for sig in sigs: + check_direct_word(sig, r, p) + require(no_short_word(keys, idems, p), + "a word of length <= 3 realizes the target (r=%d p=%d)" % (r, p)) + print("F%d width %d: %d idempotents, no word of length <= 3 for any " + "key; direct word passes" % (p, r, len(idems))) + control = check_commuting_control() + print("control y = x^-1: target is I at width %d, met by zero calls" % control) + print(MARKER) + + +if __name__ == "__main__": + main()