From 3a54499c0967ff4cf17214449b20fb080087e5a3 Mon Sep 17 00:00:00 2001 From: Ryanson Jonathan Date: Wed, 21 Oct 2026 18:37:01 +0700 Subject: [PATCH] Check #4334's sharp right-vector threshold over six extension fields Co-Authored-By: Claude Opus 5.5 --- .../right-vector-extension-fields/README.md | 81 +++++++ .../SOURCES.json | 18 ++ .../right-vector-extension-fields/TASK.json | 58 +++++ .../right-vector-extension-fields/VERIFY.json | 18 ++ .../right-vector-extension-fields/verify.py | 207 ++++++++++++++++++ 5 files changed, 382 insertions(+) create mode 100644 research/right-vector-extension-fields/README.md create mode 100644 research/right-vector-extension-fields/SOURCES.json create mode 100644 research/right-vector-extension-fields/TASK.json create mode 100644 research/right-vector-extension-fields/VERIFY.json create mode 100644 research/right-vector-extension-fields/verify.py diff --git a/research/right-vector-extension-fields/README.md b/research/right-vector-extension-fields/README.md new file mode 100644 index 0000000000..02d7d29bc4 --- /dev/null +++ b/research/right-vector-extension-fields/README.md @@ -0,0 +1,81 @@ +# #4334's sharp right-vector threshold over extension fields + +**Claim type: an independent finite check over six non-prime fields. No new +κ.** It adds the extension-field software coverage that #4334 explicitly does +not claim. + +## Object + +[PR #4334](https://github.com/CrocSwap/integer-mult-bounds/pull/4334) (ToikY) +works in the right-vector model: + +- paid factors `I + u·yᵀ`, with `u ∈ R²` and `y ∈ K²`; +- `R = K^k`, where `u` may vary by component but `y` and the free `GL_2(K)` + maps are common to all components. + +It proves a sharp component threshold for every finite field `K = F_q`. For +`k ≤ q`, every invertible target has `cost = δ ≤ 2`. For `k ≥ q+1`, there is a +target with `cost = 3` and `δ = 2`. + +The sharp example comes from a quadratic extension `L = K[X]/(h)`: the +components are multiplication by one representative of each of the `q+1` +`K`-lines of `L`. #4334 writes the proof for every finite field, but its +software witnesses cover only prime fields. Its README says it does not +"claim an extension-field software census". + +## Results + +For `F_4`, `F_8`, `F_9`, `F_16`, `F_25` and `F_27`, built from irreducible +polynomials found by search, this package builds #4334's target with `q+1` +components and checks: + +| Check | Result, every field | +| --- | --- | +| Each input line `t` is sent onto every line of `P¹(K)` exactly once | holds | +| No common pivot: every `(φ, t)` pair is killed by some component, over all `(q+1)²` pairs | holds, so `cost > 2` by #4334's criterion | +| #4334's Section 3 word `[[1,0],[r,1]]·[[1,b],[0,D]]·[[e,0],[f,1]]` reproduces each component | holds, so `cost ≤ 3` | +| `δ = min_T dim((MT − I)K²)` over every free `T ∈ GL_2(K)` | `δ = 2` | +| `k = q` side: 300 random invertible targets with `q` components have a common pivot | holds | + +**F4 without the criterion.** An exhaustive search over every free `S`, every +pair of right-vector lines and every left vector finds **no word with two +paid factors** for the five-component target. It does not use #4334's pivot +criterion. + +**Control.** The same search finds a two-factor word once one component is +dropped, which is the `k = q` case. + +## Method and independence + +- Field arithmetic is built here: `F_(p^k)` as `F_p[x]/(f)`, with `f` found + by search and field tables checked. +- The irreducible quadratic `h` over `K` is also found by search. +- Nothing is imported from #4334. Its prime-field oracle and BFS are not used. + +## Not covered + +- The written proof for every finite field, which this corroborates on six + fields and does not replace. +- Singular targets and general commutative algebras. +- Any native caller or invoice. + +## Reproduce + +```sh +python3.12 -B research/right-vector-extension-fields/verify.py +``` + +It prints `PASS_RIGHT_VECTOR_EXTENSION_FIELDS` in about 90 seconds, using only +the standard library. Most of the time goes to the `δ` check over `GL_2(F_27)`, +which has 511,056 elements. + +## Open next questions + +None from this check. + +## Credit + +The theorem, the construction and the three-factor word are ToikY's (#4334), +answering Nick Petalas's #4276 and building on Wentao Li's #4099 and #2513. +Prepared by Ryanson Jonathan with substantial Claude Code (Claude Opus 5.5) +assistance. Apache-2.0. diff --git a/research/right-vector-extension-fields/SOURCES.json b/research/right-vector-extension-fields/SOURCES.json new file mode 100644 index 0000000000..fcfba8aa31 --- /dev/null +++ b/research/right-vector-extension-fields/SOURCES.json @@ -0,0 +1,18 @@ +{ + "schema_version": 1, + "base_commit": "12fa8c5c844be21bfefb38a19503fbd867a11244", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "b1fea0c94436b236cc2b7d41a7be032811b94c81", + "sha256": "bb2eaa58647b353f88d0aec2eafb9d30df1be53589231b23e12ceef3e4bad129" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "64bfc5af6709ed9811171e0a2108f05e1219cb65", + "sha256": "352a6184713b8843d96fd2c2071eb7aeaa655906b7c51d45ad444912666c8a96" + } + ] +} diff --git a/research/right-vector-extension-fields/TASK.json b/research/right-vector-extension-fields/TASK.json new file mode 100644 index 0000000000..869a59e45b --- /dev/null +++ b/research/right-vector-extension-fields/TASK.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "task_id": "bit-new-register-model", + "priority_revision": 7, + "base_commit": "12fa8c5c844be21bfefb38a19503fbd867a11244", + "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_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": "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": "refined", + "actual_scope": "Independently check #4334's quadratic-extension sharpness construction over six non-prime fields, which its software does not cover, and over F4 confirm cost > 2 by exhaustive search without its criterion.", + "scope_change_reason": "#4334 proves the all-finite-field threshold in writing but states that its software covers only prime fields; extension-field coverage is the explicit gap.", + "bottleneck_link": "The right-vector model's threshold decides when commutative products can avoid a third paid factor in the new register model.", + "budget_minutes": 25, + "stop_rule": "Stop once every listed field passes or one fails.", + "outcome": "completed", + "evidence": "verify.py: over F4, F8, F9, F16, F25, F27 the q+1 Singer components map every line onto P^1 once; no common pivot over all (q+1)^2 pairs; #4334's three-factor word reproduces every component; delta = 2 over every free T; k = q random targets have a common pivot; over F4 an exhaustive two-factor search finds no word, and finds one when a component is dropped.", + "author": "Ryanson Jonathan, with Claude Code (Claude Opus 5.5) assistance", + "ai_assistance": "Substantial Claude Code (Claude Opus 5.5) assistance in reading, verifier implementation and writing; no independent human or proof-kernel review.", + "open_questions": [], + "no_open_questions_reason": "Every field passes; the all-field statement rests on #4334's written proof." +} diff --git a/research/right-vector-extension-fields/VERIFY.json b/research/right-vector-extension-fields/VERIFY.json new file mode 100644 index 0000000000..bbd139d63e --- /dev/null +++ b/research/right-vector-extension-fields/VERIFY.json @@ -0,0 +1,18 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [], + "commands": [ + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 300, + "checks": "GF(p^k) construction and field tables; irreducible quadratic by search; Singer components invertible and line-transitive; no common pivot; three-factor word per component; delta = 2 over GL_2(K); k = q random common-pivot corroboration; F4 exhaustive two-factor search with a dropped-component control." + } + ] +} diff --git a/research/right-vector-extension-fields/verify.py b/research/right-vector-extension-fields/verify.py new file mode 100644 index 0000000000..71248e8a66 --- /dev/null +++ b/research/right-vector-extension-fields/verify.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python3 +"""#4334's sharp right-vector threshold, checked over extension fields F_4, F_8, F_9, F_16, F_25, F_27. + +Model (#4334): paid factors I + u y^T with u in R^2, R = K^k, and y in K^2 common to all components; +GL_2(K) free and common. For each q this builds #4334's quadratic-extension target (multiplication by +one representative of each K-line of L = K[X]/(h), h irreducible) and checks: no common pivot phi, t; +#4334's explicit three-factor word reproduces every component; delta = 2 over all free T. Over F_4 it +also shows by exhaustive search that no word with two paid factors exists, without the criterion. +Standard library only; no code from #4334. +Ryanson Jonathan with Claude Code (Claude Opus 5.5) assistance. Apache-2.0. +""" +from itertools import product +import json +import random +import sys + +FIELDS = [(2, 2), (2, 3), (3, 2), (2, 4), (5, 2), (3, 3)] + + +def need(condition, message): + if not condition: + raise AssertionError(message) + + +class GF: + """F_(p^k) as F_p[x]/(f), elements encoded as integers in base p""" + + def __init__(self, p, k): + self.p, self.k, self.q = p, k, p ** k + for tail in product(range(p), repeat=k): + f = list(tail) + [1] + self.f = f + table = [[self._mul(a, b) for b in range(self.q)] for a in range(self.q)] + if all(any(table[a][b] == 1 for b in range(1, self.q)) for a in range(1, self.q)): + self.M = table + break + self.A = [[self._enc([(x + y) % p for x, y in zip(self._dec(a), self._dec(b))]) for b in range(self.q)] for a in range(self.q)] + self.neg = [next(b for b in range(self.q) if self.A[a][b] == 0) for a in range(self.q)] + self.inv = [None] + [next(b for b in range(1, self.q) if self.M[a][b] == 1) for a in range(1, self.q)] + + def _dec(self, a): + return [(a // self.p ** i) % self.p for i in range(self.k)] + + def _enc(self, v): + return sum(c * self.p ** i for i, c in enumerate(v)) + + def _mul(self, a, b): + x, y, k, p = self._dec(a), self._dec(b), self.k, self.p + r = [0] * (2 * k - 1) + for i in range(k): + for j in range(k): + r[i + j] = (r[i + j] + x[i] * y[j]) % p + for d in range(2 * k - 2, k - 1, -1): + c = r[d] + if c: + for i in range(k + 1): + r[d - k + i] = (r[d - k + i] - c * self.f[i]) % p + return self._enc(r[:k]) + + def add(self, a, b): + return self.A[a][b] + + def mul(self, a, b): + return self.M[a][b] + + def sub(self, a, b): + return self.A[a][self.neg[b]] + + +def mm(K, x, y): + return tuple(tuple(K.add(K.mul(x[i][0], y[0][j]), K.mul(x[i][1], y[1][j])) for j in range(2)) for i in range(2)) + + +def mv(K, x, v): + return tuple(K.add(K.mul(x[i][0], v[0]), K.mul(x[i][1], v[1])) for i in range(2)) + + +def det(K, x): + return K.sub(K.mul(x[0][0], x[1][1]), K.mul(x[0][1], x[1][0])) + + +def singer_target(K): + """components A_l: multiplication by (1, x) and (0, 1) in L = K[X]/(X^2 + bX + c), basis (1, X)""" + q = K.q + b, c = next((b, c) for b in range(q) for c in range(q) + if all(K.add(K.add(K.mul(x, x), K.mul(b, x)), c) for x in range(q))) + # X * X = -bX - c; multiplication by u0 + u1 X sends 1 -> (u0, u1), X -> (-c u1, u0 - b u1) + comps = [] + for u0, u1 in [(1, x) for x in range(q)] + [(0, 1)]: + comps.append(((u0, K.neg[K.mul(c, u1)]), (u1, K.sub(u0, K.mul(b, u1))))) + return comps + + +def points(K): + return [(1, x) for x in range(K.q)] + [(0, 1)] + + +def line(K, v): + """normalized representative of the K-line through a nonzero vector""" + s = K.inv[v[0]] if v[0] else K.inv[v[1]] + return (K.mul(s, v[0]), K.mul(s, v[1])) + + +def three_factor_word(K, M): + """#4334 Section 3, componentwise: M = [[1,0],[r,1]] [[1,b],[0,D]] [[e,0],[f,1]]""" + (a, b), (c, d) = M + r = 0 if d else 1 + D = K.sub(d, K.mul(r, b)) + f = K.mul(K.inv[D], K.sub(c, K.mul(r, a))) + e = K.sub(a, K.mul(b, f)) + return mm(K, mm(K, ((1, 0), (r, 1)), ((1, b), (0, D))), ((e, 0), (f, 1))) + + +def rank_stack(K, rows): + rows, rank = [list(r) for r in rows], 0 + for col in range(2): + piv = next((i for i in range(rank, len(rows)) if rows[i][col]), None) + if piv is None: + continue + rows[rank], rows[piv] = rows[piv], rows[rank] + iv = K.inv[rows[rank][col]] + for i in range(len(rows)): + if i != rank and rows[i][col]: + fct = K.mul(rows[i][col], iv) + rows[i] = [K.sub(x, K.mul(fct, y)) for x, y in zip(rows[i], rows[rank])] + rank += 1 + return rank + + +def gl2(K): + rng = range(K.q) + return [((a, b), (c, d)) for a, b, c, d in product(rng, rng, rng, rng) if det(K, ((a, b), (c, d)))] + + +def two_factor_exists(K, comps): + """exhaustive: M_i S^-1 = (I + u1_i y1^T)(I + u2_i y2^T) for one S, y1, y2 and some u1_i, u2_i""" + I = ((1, 0), (0, 1)) + vecs = list(product(range(K.q), repeat=2)) + ys = points(K) + for S in gl2(K): + dS = K.inv[det(K, S)] + Sinv = ((K.mul(S[1][1], dS), K.neg[K.mul(S[0][1], dS)]), (K.neg[K.mul(S[1][0], dS)], K.mul(S[0][0], dS))) + targets = [mm(K, Mi, Sinv) for Mi in comps] + for y1 in ys: + for y2 in ys: + def ok(X): + for u2 in vecs: + F2 = ((K.add(1, K.mul(u2[0], y2[0])), K.mul(u2[0], y2[1])), (K.mul(u2[1], y2[0]), K.add(1, K.mul(u2[1], y2[1])))) + # need X F2^-1 - I = u1 y1^T, a rank <= 1 matrix with row space in span(y1) + dF = det(K, F2) + if not dF: + continue + iv = K.inv[dF] + F2i = ((K.mul(F2[1][1], iv), K.neg[K.mul(F2[0][1], iv)]), (K.neg[K.mul(F2[1][0], iv)], K.mul(F2[0][0], iv))) + Z = mm(K, X, F2i) + Z = ((K.sub(Z[0][0], 1), Z[0][1]), (Z[1][0], K.sub(Z[1][1], 1))) + if all(K.sub(K.mul(Z[i][0], y1[1]), K.mul(Z[i][1], y1[0])) == 0 for i in range(2)): + return True + return False + if all(ok(X) for X in targets): + return True + return False + + +def main(): + out = {} + rng = random.Random(4334) + for p, k in FIELDS: + K = GF(p, k) + q = K.q + comps = singer_target(K) + need(len(comps) == q + 1 and all(det(K, A) for A in comps), f"q={q}: q+1 invertible components") + P = points(K) + # each input line is sent onto every line exactly once + for t in P: + need(sorted(line(K, mv(K, A, t)) for A in comps) == sorted(P), f"q={q}: images of t={t} cover P^1") + # hence no common pivot: every (phi, t) is killed by some component + for phi in P: + for t in P: + need(any(K.add(K.mul(phi[0], v[0]), K.mul(phi[1], v[1])) == 0 for v in (mv(K, A, t) for A in comps)), + f"q={q}: common pivot at phi={phi}, t={t}") + # #4334's three-factor word, every component + need(all(three_factor_word(K, A) == A for A in comps), f"q={q}: three-factor word") + # delta = 2: min over free T of dim((M T - I) K^2) on the stacked components + G = gl2(K) + need(min(rank_stack(K, [row for A in comps for row in ((lambda X: ((K.sub(X[0][0], 1), X[0][1]), (X[1][0], K.sub(X[1][1], 1))))(mm(K, A, T)))]) + for T in G) == 2, f"q={q}: delta = 2") + # the other side of the threshold: k = q random invertible components always share a pivot + for _ in range(300): + sample = [rng.choice(G) for _ in range(q)] + need(any(all(K.add(K.mul(phi[0], v[0]), K.mul(phi[1], v[1])) for v in (mv(K, A, t) for A in sample)) + for phi in P for t in P), f"q={q}: k = q sample has a common pivot") + out[str(q)] = {"components": q + 1, "gl2": len(G)} + # direct exhaustive confirmation over F_4, without the pivot criterion: cost > 2 + K4 = GF(2, 2) + need(not two_factor_exists(K4, singer_target(K4)), "F_4: no two-paid-factor word exists") + need(two_factor_exists(K4, singer_target(K4)[:4]), "control: dropping one component makes two factors suffice") + print(json.dumps({ + "status": "PASS_RIGHT_VECTOR_EXTENSION_FIELDS", + "fields": out, + "f4_two_factor_exhaustive": "no word", + "new_kappa_claimed": False, + }, indent=1)) + + +if __name__ == "__main__": + sys.exit(main())