diff --git a/research/p104-char3-rank36-window/NOTICE b/research/p104-char3-rank36-window/NOTICE new file mode 100644 index 0000000000..d2323347b9 --- /dev/null +++ b/research/p104-char3-rank36-window/NOTICE @@ -0,0 +1,6 @@ +Characteristic-3 rank-36 witness for the P104 port window. +Prepared by unpaidmoon with substantial Cursor Grok assistance. +The port list is the P104 set published in PR #6933. +The rank-38 degree-2 pattern without a constant term is the predecessor +finding in discussion comment 19492602. +New exposition and checks are Apache-2.0. diff --git a/research/p104-char3-rank36-window/PROOF.md b/research/p104-char3-rank36-window/PROOF.md new file mode 100644 index 0000000000..5a1ecf00b2 --- /dev/null +++ b/research/p104-char3-rank36-window/PROOF.md @@ -0,0 +1,200 @@ +# Characteristic 3 admits a rank-36 pattern on P104 + +No new κ. The selected record stays `781451/250000000`. This note does not +build a word, a decoder, or a paid profile, and it does not change the +selected frontier. + +The window below is the block-mask window of PR #6933. A physical decoder +for `k > 1` with exactly this mask is not derived, there or here. + +## 0. Definitions + +`P120` is the 120 vectors in `F_2^9` of weight congruent to 3 mod 4 (weights +3 and 7). Two distinct vectors are adjacent when their `F_2` dot product is +1 and orthogonal when it is 0. `P104` is the 104-vector subset in +`data/ports_p104.json`, byte-identical to the port list of #6933 at +`a967c521074c2c7450255ae237fda9c439ee1b35` (sha256 +`691c7b7d212112115b1bfc76db89f90d304ec448dc8c4a0c43d9a5954317146c`). Its +complement in `P120` is 16 vectors and exactly two cliques of size 8. Each +of those cliques, added to `P104`, is a 112-vector set `P112`. + +A **1-block pattern** on a vertex set `S` is a matrix, indexed by `S`, with +nonzero diagonal and with a zero in both off-diagonal positions of every +orthogonal pair. Entries on adjacent pairs are free, and the matrix need not +be symmetric. Write `w_1(S; F)` for the minimum rank of a 1-block pattern +over `F`, and `w(S; F)` for the infimum of `rank(B)/k` over k-block patterns +in the sense of #6933. Then `w(S; F) ≤ w_1(S; F)`. + +The predecessor note (fork PR 151, discussion comment 19492602) proves +`w(S; F) ≤ 36` for every nonempty `S ⊆ P120` and every field of +characteristic not 3, by the matrix `3I − A`, and proves `w(S; F_3) ≤ 38` by +a degree-at-most-2 factorisation with no constant term. Characteristic 2 is +already settled by #6933 and is not reopened. The lower bounds +`w(P104) ≥ 13`, `w(P112) ≥ 14` and `w(P120) ≥ 15` in odd characteristic are +#6933, Theorem 4. They are cited and not replayed. + +## 1. The adjacency square vanishes + +**Lemma 1.** Let `A` be the adjacency matrix of the odd graph on `P120`. +Over every field of characteristic 3, `A^2 = 0`. + +*Proof.* For an undirected simple graph, `(A^2)_ij` is the number of walks of +length 2 from `i` to `j`, including the degree on the diagonal. `verify.py` +enumerates all 120 vertices and all `C(120, 2) + 120` unordered pairs +`{i, j}` with `i ≤ j`, counts the common 1-bits of the two neighbor masks, +and checks that every count is divisible by 3. The domain is finite, every +pair is visited once, and the walk interpretation is the definition of `A^2`. +The same integer counts remain 0 in every field of characteristic 3. ∎ + +The predecessor proves that the graph is strongly regular with parameters +`(120, 63, 30, 36)`, which gives the integer identity +`A^2 = 27I − 6A + 36J`. All three coefficients are divisible by 3, so that +identity specialises to Lemma 1. The parameter census is not repeated here. +Lemma 1 does not depend on it. + +## 2. The class-constant ansatz cannot have rank 36 + +Call a matrix **class-constant** when its diagonal entries are equal, its +adjacent entries are equal, and its orthogonal entries are equal. Every such +matrix has the form + +``` +α I + β A + γ (J − I − A). +``` + +**Lemma 2.** Over every field of characteristic 3, every class-constant +1-block pattern on `P120` has rank 120. In particular, no class-constant +pattern has rank 36. + +*Proof.* An orthogonal pair has `A`-entry 0 and `(J − I − A)`-entry 1, so the +matrix entry there is `γ`. A pattern forces `γ = 0`. The diagonal entry is +then `α`. If `α = 0`, the diagonal vanishes and the matrix is not a pattern. +The reduction of `3I − A` is this illegal case: in characteristic 3 it equals +`−A`. If `α ≠ 0`, the matrix is `α(I + c A)` with `c = β α^{-1}`. Lemma 1 +gives + +``` +(I + c A)(I − c A) = I − c^2 A^2 = I. +``` + +So the matrix is invertible and has rank 120. ∎ + +This is a proof for one restricted ansatz: matrices constant on the three +relations of the odd graph. It is not a proof that an arbitrary pattern has +rank greater than 36. The legal class-constant patterns are exactly the +invertible ones. `verify.py` checks the three monic cases `I + β A` over +`F_3`, including the inverse identity, and checks that `3I − A` has zero +diagonal modulo 3. + +The same lemma is why the predecessor's rank-36 matrix does not reduce into +characteristic 3. Closing the gap needs a matrix that is not class-constant. + +## 3. The degree-at-most-2 witness + +Order the 46 monomials of degree at most 2 on `F_2^9` as the constant `1`, +the coordinates `x_0, …, x_8`, and the products `x_i x_j` for `0 ≤ i < j ≤ 8`. +Evaluate them at a vector as integers in `{0, 1}` and read the values in +`F_3`. This is a `120 × 46` matrix `Φ`. + +For each vertex `v`, let `C_v` be the matrix whose rows are the rows of `Φ` +indexed by `v` and by the vertices orthogonal to `v`. The system +`C_v y = e`, with right-hand side 1 on the `v` row and 0 on the orthogonal +rows, is consistent. Its reduced row echelon form has a unique set of pivot +columns. Take the unique solution `y_v` supported on those pivot columns +(free coordinates equal to 0). Define `M_uv = Φ_u · y_v`. + +**Theorem 1.** `M` is a 1-block pattern over `F_3` of rank 37. Its principal +submatrix on `P104` has rank 36. Extending scalars, the same matrix is a +1-block pattern of those same ranks over every field of characteristic 3. +Consequently, for every such field `F`, + +``` +w(P104; F) ≤ w_1(P104; F) ≤ 36, +w(P120; F) ≤ w_1(P120; F) ≤ 37. +``` + +Of the two `P112` extensions, the one that adds the clique + +``` +(7, 25, 42, 52, 76, 82, 97, 127) +``` + +has principal rank 36, and the one that adds + +``` +(67, 104, 137, 162, 266, 289, 448, 491) +``` + +has principal rank 37. So one 112-port extension meets the same ceiling 36, +and the other only meets 37. + +*Proof.* `verify.py` rebuilds `Φ` and every `y_v`, substitutes the solutions +back into the equations, and checks every diagonal entry and both +off-diagonal entries of every orthogonal pair. Rank is the number of pivots +in Gaussian elimination over `F_3`. A minor is zero over `F_3` if and only +if it is zero over an extension, and a nonzero value in `F_3` stays nonzero, +so the rank is unchanged by scalar extension. A principal submatrix of a +pattern is a pattern. The sha256 of the `104 × 104` principal submatrix, in +the port-file order, is + +``` +473541e0dcc7e2c22e879d37ebd3cd3e1f88c1de5c0306fd42fa38ff134c6e6a +``` + +with entries written as bytes in `{0, 1, 2}` row by row. ∎ + +The same solver with the constant monomial omitted reproduces the +predecessor's pattern: rank 38 on `P120`, and rank 37 on the `P104` principal +submatrix. The predecessor recorded only the upper bound 38 for every subset. +The constant monomial is what drops the `P104` principal rank from 37 to 36 +in this construction. `M` is not class-constant: it is asymmetric, and the +adjacent entries take more than one value. Lemma 2 does not apply to it. + +## 4. What the witness does not minimise + +`Φ` has rank 45. Its one-dimensional kernel is contained in the homogeneous +solution space of every vertex. The coefficient space of solutions with +diagonal normalised to 1 therefore has dimension 4 at each weight-3 vertex +and dimension 9 at each weight-7 vertex, while the space of legal columns +`Φ y` has dimension 3 and 8 respectively. `verify.py` checks these dimensions +for every vertex. + +Theorem 1 uses one point of that affine family, the point whose free +coordinates are 0. It is not an exhaustive search of the family, and a +different point might have smaller rank on `P120`. No such point is claimed +here. The pairs-only and linear-only feature maps are inconsistent; that +rules out those smaller maps and does not rule out another 36-dimensional +model. + +So three statements stay distinct: + +1. **Proof, restricted ansatz.** Every class-constant pattern has rank 120 + in characteristic 3 (Lemma 2). +2. **Proof, one witness.** The explicit matrix of Theorem 1 has rank 36 on + `P104` and rank 37 on `P120`. +3. **Not settled.** Whether every 1-block pattern on `P120` has rank at + least 37, and whether some other point of the degree-at-most-2 family + has rank 36 on `P120`. A search that did not find such a point would not + decide either question. This note does not report one. + +Accepting #6933, Theorem 4, without replaying it, the characteristic-3 +intervals are now + +| set | lower bound, cited | upper bound proved here | +|---|---|---| +| P104 | 13 | 36 | +| P112, clique `(7, 25, 42, 52, 76, 82, 97, 127)` | 14 | 36 | +| P112, the other deleted clique | 14 | 37 | +| P120 | 15 | 37 | + +The lower bounds are not claimed for arbitrary subsets. Characteristic 2 +stays inside #6933's interval `[53/6, 9]` on `P104` and the value 9 on +`P112` and `P120`. + +## 5. What this does not say + +A rank-36 pattern is not a multiplication algorithm, not a paid profile, and +not a change to the selected frontier. It does not show that 36 is the +minimum on `P104`: the cited lower bound is 13, and the star floor `53/6` +of #6933 is weaker. It does not show that `P120` admits rank 36. It does +not touch the `F_5` rank-13 factorisation. No human has reviewed this note. diff --git a/research/p104-char3-rank36-window/README.md b/research/p104-char3-rank36-window/README.md new file mode 100644 index 0000000000..07e30572ef --- /dev/null +++ b/research/p104-char3-rank36-window/README.md @@ -0,0 +1,94 @@ +# Characteristic-3 rank-36 pattern on the P104 window (no new κ) + +**No new κ.** The selected record stays `781451/250000000`. This package +exhibits one 1-block pattern of rank 36 on `P104` over every field of +characteristic 3. It does not build a word or a paid profile. + +The argument is in [PROOF.md](PROOF.md). The exact checks are in +[verify.py](verify.py). + +## Result + +`P120` is the odd graph on the 120 vectors in `F_2^9` of weight 3 or 7. +`P104` is the port list of PR #6933, vendored byte-for-byte. A 1-block +pattern has nonzero diagonal and zeros on both off-diagonal positions of +every orthogonal pair. + +1. **Class-constant ansatz, proved impossible at rank 36.** In + characteristic 3 the adjacency matrix satisfies `A^2 = 0`. Every matrix + that is constant on the diagonal, on edges, and on non-edges is then + either illegal (zero diagonal) or invertible of rank 120. The matrix + `3I − A` is the illegal case. This is not an unrestricted nonexistence + theorem. +2. **Witness, outside that ansatz.** The 46 monomials of degree at most 2, + including the constant, give a 1-block pattern over `F_3` of rank 37 on + `P120` and rank 36 on `P104`. Scalar extension preserves both ranks, so + `w(P104; F) ≤ 36` and `w(P120; F) ≤ 37` for every field `F` of + characteristic 3. One of the two `P112` extensions has rank 36 and the + other has rank 37. +3. **The witness is one point of a positive-dimensional family.** With the + diagonal normalised to 1, the coefficient spaces have dimensions 4 and 9, + and the legal columns have dimensions 3 and 8. Free coordinates were set + to 0. That choice was not minimised over the family. + +The same solver without the constant term reproduces the predecessor's rank +38 on `P120` and gives rank 37 on `P104`. The predecessor recorded only the +bound 38. The constant term is the step from 37 to 36 on `P104`. + +Accepting the lower bounds in #6933, Theorem 4, without replaying them, the +characteristic-3 window now satisfies `w(P104; F) ∈ [13, 36]`. The matching +upper bound 36 was previously known only off characteristic 3. No equality +is claimed. + +## Scope + +Original card: `complex-rank-shape-decoder`. Scope status: **changed**. The +card asks whether a decoder or coframe change improves the signed moment. +This package does not change a word or a moment. It answers the +characteristic-3 half of the question left open by the predecessor finding +on discussion comment 19492602: whether characteristic 3 admits a rank-36 +pattern on the P104 window. Base commit +`7c49fe32c55de02c2c873655c804b16e4c3fef0a`, priority revision 8. + +The `F_5` rank-13 factorisation is a different question and is not +investigated. Characteristic 2 is not reopened. + +## Reproduce + +From the repository root, CPython 3.12, standard library only: + +```sh +python3 -B research/p104-char3-rank36-window/verify.py +python3 -I -O -B research/p104-char3-rank36-window/verify.py +python3 -B scripts/research_package.py --package research/p104-char3-rank36-window +``` + +Expected final line: `PASS_CHAR3_RANK36 p104=36 p120=37 class_constant=120`, +then `PASS_REGISTERED_RESEARCH_PACKAGE` with outcome `partial`. + +The port file is an input copied from #6933 because that commit is not in +this repository's history. Its sha256 is pinned in `verify.py`. The +catalogue and the selected record are provenance pins at the base commit. + +## Open next questions + +1. Does `P120` admit a 1-block pattern of rank 36 in characteristic 3? The + witness here has rank 37, and one of the two `P112` extensions also stops + at 37. A first step is one explicit `120 × 36` factorisation over `F_3`, + or a lower bound of 37 with the hypotheses written down. Nothing in this + package shows that every pattern has rank at least 37. +2. Does any other point of this degree-at-most-2 family, with the recorded + nullities 4 and 9, have rank 36 on `P120`? The free-coordinate-zero point + has rank 37. The family was not searched. A partial search would not + decide the question. + +The rank-13 factorisation over `F_5` is open in the predecessor note and is +intentionally not a next step of this package. + +## Credit + +DreamingOfClouds, PR #6933, for the window, the port list, and Theorem 4. +The predecessor finding (discussion comment 19492602, fork PR 151) proved the +rank-36 pattern off characteristic 3 and the rank-38 degree-2 pattern in +characteristic 3. Prepared by unpaidmoon with substantial Cursor Grok +assistance. New work is Apache-2.0. diff --git a/research/p104-char3-rank36-window/SOURCES.json b/research/p104-char3-rank36-window/SOURCES.json new file mode 100644 index 0000000000..594089b9c7 --- /dev/null +++ b/research/p104-char3-rank36-window/SOURCES.json @@ -0,0 +1,18 @@ +{ + "schema_version": 1, + "base_commit": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "d59b5035e7b4cbaa9d688a1d32dd0d6eb79c466a", + "sha256": "9b8d0eea95b3bf0dfcb7938a732a6439b87a2685dec2a5ab9e525b3b34debbfa" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "3404fbdd5e7529a0674eef26114b5071e4586cec", + "sha256": "ead6cdc9d0af6d58e8a49744d8ec8c7c15e13d2ba93c276c434bcf9b51b93a81" + } + ] +} diff --git a/research/p104-char3-rank36-window/TASK.json b/research/p104-char3-rank36-window/TASK.json new file mode 100644 index 0000000000..1a6508fbde --- /dev/null +++ b/research/p104-char3-rank36-window/TASK.json @@ -0,0 +1,81 @@ +{ + "schema_version": 1, + "task_id": "complex-rank-shape-decoder", + "priority_revision": 8, + "base_commit": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "original_card": { + "id": "complex-rank-shape-decoder", + "question": "Can a legal decoder or coframe change improve the full signed moment, including changed helper targets?", + "starting_points": [ + "docs/research/current-priorities.md", + "docs/research/research-family-status.md", + "certificates/selected-result.json", + "docs/research/pr-intake-evidence/pr5599-completion/PROOF-REVIEW.md", + "docs/research/recursive-invoice-preflight.md" + ], + "methods": [ + "Construct and independently check one source-bound instance of the stated first experiment.", + "Seek an exact counterexample or target-specific complete-budget obstruction to that same proposed change." + ], + "acceptance_gate": "A source-bound arbitrary-input identity and legal producer/consumer boundary with the complete paid and productive target invoice, including restoration, ownership, native alignment and extra charges. Price under the actual current model; historical ceiling.py assumptions must be established before use. A favorable optimistic relaxation keeps a route open but is not a completed supplier. A scoped local result remains useful; expansion requires the family-level budget gate.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_selected_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read revision 8, the selected review and live exact-source handoffs. Then follow this card's bounded first_experiment.", + "scope": "Source-bound orientation only, not a supplier replay or theorem proof." + }, + "first_experiment": "Price one complete changed itinerary with both paid and productive histograms. Check #5693/#5698 for overlap and their exact hypotheses before another coframe search. Use the signed invoice preflight where its boundary contract agrees; an inconclusive concave comparison is not a power crossing. Stop if an optimistic complete budget fails at the chosen target or native delivery remains unspecified.", + "bottleneck_link": "Judge the actual current supplier contract and complete signed target/paid bill; frozen-profile ceilings require an applicability proof.", + "allowed_variations": [ + "One exact source head, helper/cut region or quantified proposition and changed hypothesis; check live handoffs first. Different seeds are not different scopes." + ], + "scope_change_triggers": [ + "Changing source head, helper/cut domain, operation alphabet or caller boundary without recording the new scope.", + "Treating an archived proposal or local numerical pass as complete supplier admission." + ], + "overlap_terms": [ + "coframe", + "signed moment", + "5693", + "5698" + ], + "existing_checks": [ + { + "scope": "Selected PR5599: complete helper-subspace construction and independent caller replay; five framework assumptions remain.", + "evidence": "docs/research/pr-intake-evidence/pr5599-completion/PROOF-REVIEW.md", + "remaining": "The next experiment must identify uncovered source-specific work. Successor archive intake does not transfer this admission.", + "status": "reviewed", + "source_commit": "09dd0965711ca7eeb169057a420abab1c9052137", + "selected_record_sha256": "2a0220e866417774606e0f991e41b9c1d26b1f43b97857238cf478dbc7d330b5" + } + ] + }, + "scope_status": "changed", + "actual_scope": "Decide whether characteristic 3 admits a rank-36 1-block pattern on the P104 port window of PR 6933. No word, moment, or kappa.", + "scope_change_reason": "The card asks whether a decoder or coframe change improves the signed moment. This package does not change a word or a moment. It answers the characteristic-3 question left open by the predecessor odd-character window: 3I-A is illegal in characteristic 3, and the recorded degree-2 pattern has rank 38. The result is a rank upper bound for that window, not a supplier admission.", + "bottleneck_link": "A k-block decoder mask on these ports is the fractional Haemers window of the odd graph. Characteristic 3 was the only odd characteristic whose recorded pattern sat strictly above the off-character ceiling 36. A rank-36 pattern there removes that gap for P104. This is a scoped rank witness, not a signed-moment improvement.", + "budget_minutes": 60, + "stop_rule": "Stop after one explicit characteristic-3 pattern on P104 whose rank is checked exactly, together with the class-constant obstruction. Do not search the F_5 rank-13 factorisation or exhaust the degree-2 affine family.", + "outcome": "partial", + "evidence": "PROOF.md Lemma 2 and Theorem 1. verify.py prints PASS_CHAR3_RANK36 p104=36 p120=37 class_constant=120. The lower bound 13 is cited from PR 6933 Theorem 4 and is not replayed. P120 is improved only to 37.", + "author": "unpaidmoon", + "ai_assistance": "Substantial Cursor Grok assistance.", + "open_questions": [ + { + "question": "Does P120 admit a 1-block pattern of rank 36 over a field of characteristic 3?", + "why_it_matters": "The witness in this package has rank 37 on P120 and on one P112 extension, and rank 36 on P104 and the other P112 extension. The off-characteristic-3 ceiling is 36 for every one of these sets.", + "first_step": "Exhibit one 120 by 36 factorisation over F_3 with nonzero diagonal and zeros on orthogonal pairs, or prove rank at least 37 under explicit hypotheses.", + "blocked_by": "The degree-at-most-2 point constructed here has rank 37. The class-constant ansatz has rank 120. Neither fact forbids a different column space of dimension 36." + }, + { + "question": "Does any other point of this degree-at-most-2 family have rank 36 on P120?", + "why_it_matters": "This is the restricted ansatz that produced the P104 witness. It is a different question from unrestricted existence. A positive answer would also settle the P120 upper bound; a negative answer would not.", + "first_step": "Use the recorded nullities, 4 at weight 3 and 9 at weight 7, and ask whether one affine choice puts every column in a 36-dimensional space.", + "blocked_by": "Only the free-coordinate-zero point was evaluated. It has rank 37. The family was not searched, and an incomplete search would not be a proof." + } + ] +} diff --git a/research/p104-char3-rank36-window/VERIFY.json b/research/p104-char3-rank36-window/VERIFY.json new file mode 100644 index 0000000000..f476aa5474 --- /dev/null +++ b/research/p104-char3-rank36-window/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": 180, + "checks": "Exhaustive check that A^2 vanishes over F_3; class-constant patterns I+beta A have rank 120; the degree-at-most-2 witness with a constant term has rank 37 on P120 and rank 36 on P104; the two P112 extensions have ranks 36 and 37; nullities are 4 and 9; the no-constant predecessor pattern has ranks 38 and 37; controls reject a planted orthogonal entry, a zero diagonal, the all-ones matrix, the characteristic-3 reduction of 3I-A, and linear-only features." + } + ] +} diff --git a/research/p104-char3-rank36-window/data/ports_p104.json b/research/p104-char3-rank36-window/data/ports_p104.json new file mode 100644 index 0000000000..8037fd1087 --- /dev/null +++ b/research/p104-char3-rank36-window/data/ports_p104.json @@ -0,0 +1,109 @@ +{ +"description": "The 104 ports of P104 as vectors of F_2^9 (bit i of the integer is coordinate i), in a fixed order; two distinct ports are adjacent in the odd graph iff popcount(a & b) is odd.", +"ports": [ +11, +19, +35, +131, +259, +13, +21, +37, +69, +133, +261, +41, +73, +265, +49, +81, +145, +273, +161, +193, +321, +385, +14, +22, +38, +70, +134, +262, +26, +74, +138, +50, +146, +274, +98, +290, +194, +322, +386, +28, +44, +140, +268, +84, +148, +276, +100, +164, +292, +196, +324, +388, +56, +88, +152, +280, +168, +296, +200, +328, +392, +112, +176, +304, +208, +336, +400, +224, +352, +416, +508, +506, +502, +494, +478, +446, +382, +254, +505, +501, +493, +477, +445, +381, +253, +499, +475, +443, +379, +251, +487, +471, +439, +375, +247, +463, +431, +367, +239, +415, +351, +223, +319, +191 +] +} \ No newline at end of file diff --git a/research/p104-char3-rank36-window/verify.py b/research/p104-char3-rank36-window/verify.py new file mode 100644 index 0000000000..9192693abc --- /dev/null +++ b/research/p104-char3-rank36-window/verify.py @@ -0,0 +1,482 @@ +#!/usr/bin/env python3 +"""Characteristic-3 rank-36 witness for the P104 port window. + +No kappa claim. Standard library only. + +The witness is one explicit 1-block pattern over F_3. It is not a census of +patterns. The class-constant ansatz is a separate, exhaustive algebraic check: +every matrix constant on the three relations has rank 120 in characteristic 3. +""" + +import hashlib +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +PORTS_SHA256 = "691c7b7d212112115b1bfc76db89f90d304ec448dc8c4a0c43d9a5954317146c" +# sha256 of the 104x104 pattern in ports_p104.json order, entries in 0,1,2. +P104_MATRIX_SHA256 = "473541e0dcc7e2c22e879d37ebd3cd3e1f88c1de5c0306fd42fa38ff134c6e6a" +CLIQUE_RANK = { + (7, 25, 42, 52, 76, 82, 97, 127): 36, + (67, 104, 137, 162, 266, 289, 448, 491): 37, +} + + +def require(ok, message): + if not ok: + raise SystemExit("FAIL: " + message) + + +def weight(v): + return bin(v).count("1") + + +def odd_dot(a, b): + return (bin(a & b).count("1") & 1) == 1 + + +def p120(): + return [v for v in range(1 << 9) if weight(v) % 4 == 3] + + +def features(v, constant): + bits = [(v >> i) & 1 for i in range(9)] + coords = [1] if constant else [] + coords.extend(bits) + for i in range(9): + for j in range(i + 1, 9): + coords.append(bits[i] * bits[j]) + return coords + + +def rref_solve(phi, equations): + """Unique solution supported on the pivot columns, or (None, None) if inconsistent. + + Free coordinates of the reduced row echelon form are set to 0. Pivot columns + are exactly those of the unique RREF, so the particular solution does not + depend on the order of the equations. + """ + width = len(phi[0]) + matrix = [phi[i][:] + [rhs % 3] for i, rhs in equations] + pivot_of = [None] * width + rank = 0 + for col in range(width): + pivot = None + for row in range(rank, len(matrix)): + if matrix[row][col] % 3: + pivot = row + break + if pivot is None: + continue + matrix[rank], matrix[pivot] = matrix[pivot], matrix[rank] + inverse = pow(matrix[rank][col], -1, 3) + for k in range(col, width + 1): + matrix[rank][k] = matrix[rank][k] * inverse % 3 + for row in range(len(matrix)): + if row == rank or matrix[row][col] % 3 == 0: + continue + factor = matrix[row][col] % 3 + for k in range(col, width + 1): + matrix[row][k] = (matrix[row][k] - factor * matrix[rank][k]) % 3 + pivot_of[col] = rank + rank += 1 + for row in range(rank, len(matrix)): + if matrix[row][width] % 3: + return None, None + solution = [0] * width + for col, row in enumerate(pivot_of): + if row is not None: + solution[col] = matrix[row][width] % 3 + free = [col for col, row in enumerate(pivot_of) if row is None] + return solution, free + + +def null_basis(phi, equations): + """Basis of the homogeneous solution space, one vector per free column.""" + width = len(phi[0]) + matrix = [phi[i][:] + [0] for i, _rhs in equations] + # Reuse the inhomogeneous solver's elimination by calling rref on rhs 0 + # through the same pivot rule. Build it directly so the basis matches. + pivot_of = [None] * width + rank = 0 + for col in range(width): + pivot = None + for row in range(rank, len(matrix)): + if matrix[row][col] % 3: + pivot = row + break + if pivot is None: + continue + matrix[rank], matrix[pivot] = matrix[pivot], matrix[rank] + inverse = pow(matrix[rank][col], -1, 3) + for k in range(col, width): + matrix[rank][k] = matrix[rank][k] * inverse % 3 + for row in range(len(matrix)): + if row == rank or matrix[row][col] % 3 == 0: + continue + factor = matrix[row][col] % 3 + for k in range(col, width): + matrix[row][k] = (matrix[row][k] - factor * matrix[rank][k]) % 3 + pivot_of[col] = rank + rank += 1 + basis = [] + for free in [col for col, row in enumerate(pivot_of) if row is None]: + vector = [0] * width + vector[free] = 1 + for col, row in enumerate(pivot_of): + if row is not None: + vector[col] = (-matrix[row][free]) % 3 + basis.append(vector) + return basis + + +def rank_mod(rows): + matrix = [row[:] for row in rows] + if not matrix: + return 0 + n = len(matrix) + m = len(matrix[0]) + rank = 0 + for col in range(m): + pivot = None + for row in range(rank, n): + if matrix[row][col] % 3: + pivot = row + break + if pivot is None: + continue + matrix[rank], matrix[pivot] = matrix[pivot], matrix[rank] + inverse = pow(matrix[rank][col], -1, 3) + for k in range(col, m): + matrix[rank][k] = matrix[rank][k] * inverse % 3 + for row in range(n): + if row == rank or matrix[row][col] % 3 == 0: + continue + factor = matrix[row][col] % 3 + for k in range(col, m): + matrix[row][k] = (matrix[row][k] - factor * matrix[rank][k]) % 3 + rank += 1 + return rank + + +def rank_prime(rows, prime): + matrix = [row[:] for row in rows] + n = len(matrix) + m = len(matrix[0]) + rank = 0 + for col in range(m): + pivot = None + for row in range(rank, n): + if matrix[row][col] % prime: + pivot = row + break + if pivot is None: + continue + matrix[rank], matrix[pivot] = matrix[pivot], matrix[rank] + inverse = pow(matrix[rank][col], -1, prime) + for k in range(col, m): + matrix[rank][k] = matrix[rank][k] * inverse % prime + for row in range(n): + if row == rank or matrix[row][col] % prime == 0: + continue + factor = matrix[row][col] % prime + for k in range(col, m): + matrix[row][k] = (matrix[row][k] - factor * matrix[rank][k]) % prime + rank += 1 + return rank + + +def load_ports(): + raw = (ROOT / "data" / "ports_p104.json").read_bytes() + require(hashlib.sha256(raw).hexdigest() == PORTS_SHA256, "P104 port bytes changed") + ports = json.loads(raw)["ports"] + require(len(ports) == len(set(ports)) == 104, "P104 is not 104 distinct ports") + return ports + + +def orthogonal_lists(vertices): + lists = [[] for _ in vertices] + for i, u in enumerate(vertices): + for j in range(i + 1, len(vertices)): + if not odd_dot(u, vertices[j]): + lists[i].append(j) + lists[j].append(i) + return lists + + +def factorisation(vertices, constant): + phi = [[c % 3 for c in features(v, constant)] for v in vertices] + orth = orthogonal_lists(vertices) + columns = [] + nullities = [] + for j in range(len(vertices)): + equations = [(i, 0) for i in orth[j]] + [(j, 1)] + solution, free = rref_solve(phi, equations) + require(solution is not None, "degree-2 system inconsistent at vertex %d" % j) + for i, rhs in equations: + got = sum(phi[i][t] * solution[t] for t in range(len(solution))) % 3 + require(got == rhs % 3, "solution misses an equation") + columns.append(solution) + nullities.append(len(free)) + width = len(phi[0]) + matrix = [] + for u in range(len(vertices)): + matrix.append( + [sum(phi[u][t] * columns[v][t] for t in range(width)) % 3 for v in range(len(vertices))] + ) + return phi, orth, columns, nullities, matrix + + +def valid_pattern(matrix, vertices): + n = len(vertices) + for i, u in enumerate(vertices): + if matrix[i][i] % 3 == 0: + return False + for j in range(i + 1, n): + if odd_dot(u, vertices[j]): + continue + if matrix[i][j] % 3 or matrix[j][i] % 3: + return False + return True + + +def principal(matrix, index): + return [[matrix[i][j] for j in index] for i in index] + + +def odd_cliques(vertices, size): + found = [] + + def rec(start, chosen): + if len(chosen) == size: + found.append(tuple(sorted(vertices[i] for i in chosen))) + return + for i in range(start, len(vertices)): + v = vertices[i] + if all(odd_dot(v, vertices[j]) for j in chosen): + chosen.append(i) + rec(i + 1, chosen) + chosen.pop() + + rec(0, []) + return found + + +def adjacency_square_vanishes(vertices): + """(A^2)_ij is the number of length-2 walks. Every such count is 0 mod 3.""" + neighbor = [] + for i, u in enumerate(vertices): + mask = 0 + for j, v in enumerate(vertices): + if i != j and odd_dot(u, v): + mask |= 1 << j + neighbor.append(mask) + n = len(vertices) + for i in range(n): + for j in range(i, n): + if (neighbor[i] & neighbor[j]).bit_count() % 3: + return False + return True + + +def class_constant_patterns(vertices): + """I + beta A for beta in F_3. Each is a legal pattern. Return their ranks.""" + n = len(vertices) + ranks = [] + for beta in (0, 1, 2): + rows = [[0] * n for _ in range(n)] + for i, u in enumerate(vertices): + rows[i][i] = 1 + for j in range(i + 1, n): + if odd_dot(u, vertices[j]): + rows[i][j] = rows[j][i] = beta + require(valid_pattern(rows, vertices), "I+%dA is not a pattern" % beta) + product = [[0] * n for _ in range(n)] + # (I+beta A)(I-beta A) = I when A^2 = 0. -beta == 3-beta == -beta mod 3. + minus = (-beta) % 3 + other = [[0] * n for _ in range(n)] + for i, u in enumerate(vertices): + other[i][i] = 1 + for j in range(i + 1, n): + if odd_dot(u, vertices[j]): + other[i][j] = other[j][i] = minus + for i in range(n): + for j in range(n): + product[i][j] = sum(rows[i][k] * other[k][j] for k in range(n)) % 3 + require(all(product[i][i] == 1 and all(product[i][j] == 0 for j in range(n) if j != i) for i in range(n)), + "(I+%dA)(I-%dA) is not I" % (beta, beta)) + ranks.append(rank_mod(rows)) + return ranks + + +def three_i_minus_a_mod5(vertices): + n = len(vertices) + rows = [[0] * n for _ in range(n)] + for i, u in enumerate(vertices): + rows[i][i] = 3 % 5 + for j in range(i + 1, n): + if odd_dot(u, vertices[j]): + rows[i][j] = rows[j][i] = (-1) % 5 + return rank_prime(rows, 5) + + +def matrix_sha256(rows): + raw = bytes(entry % 3 for row in rows for entry in row) + return hashlib.sha256(raw).hexdigest() + + +def main(): + vertices = p120() + require(len(vertices) == 120, "P120 count") + require(sum(weight(v) == 3 for v in vertices) == 84, "weight-3 count") + require(sum(weight(v) == 7 for v in vertices) == 36, "weight-7 count") + require(adjacency_square_vanishes(vertices), "A^2 does not vanish over F_3") + print("PASS_A_SQUARE_ZERO") + + ranks = class_constant_patterns(vertices) + require(ranks == [120, 120, 120], "class-constant patterns are not full rank: %s" % ranks) + print("PASS_CLASS_CONSTANT_RANK120") + + require(three_i_minus_a_mod5(vertices) == 36, "3I-A mod 5 is not rank 36") + reduced = [] + n = len(vertices) + for i, u in enumerate(vertices): + row = [0] * n + row[i] = 0 # 3 ≡ 0, so the characteristic-3 reduction of 3I-A is -A + for j, v in enumerate(vertices): + if i != j and odd_dot(u, v): + row[j] = (-1) % 3 + reduced.append(row) + require(all(reduced[i][i] == 0 for i in range(n)), "3I-A should have zero diagonal in char 3") + require(not valid_pattern(reduced, vertices), "3I-A must be illegal in char 3") + print("PASS_OFFCHAR_CONTROL rank36_mod5=36 char3_diagonal=0") + + ports = load_ports() + require(set(ports) <= set(vertices), "P104 not inside P120") + require(sum(weight(v) == 3 for v in ports) == 70, "P104 weight 3") + require(sum(weight(v) == 7 for v in ports) == 34, "P104 weight 7") + degrees = {sum(odd_dot(u, v) for v in ports if v != u) for u in ports} + require(degrees == {55}, "P104 is not 55-regular: %s" % sorted(degrees)) + + phi, orth, columns, nullities, matrix = factorisation(vertices, constant=True) + require(len(phi[0]) == 46, "feature width") + require(rank_mod(phi) == 45, "quadratic evaluation rank") + require(valid_pattern(matrix, vertices), "constant quadratic factorisation is not a pattern") + full_rank = rank_mod(matrix) + require(full_rank == 37, "P120 witness rank %d is not 37" % full_rank) + asymmetric = sum( + matrix[i][j] != matrix[j][i] for i in range(len(vertices)) for j in range(i + 1, len(vertices)) + ) + edge_values = { + matrix[i][j] + for i in range(len(vertices)) + for j in range(len(vertices)) + if i != j and odd_dot(vertices[i], vertices[j]) + } + require(asymmetric > 0 and len(edge_values) > 1, + "witness collapsed into a class-constant matrix") + by_weight = {} + for v, nullity in zip(vertices, nullities): + by_weight.setdefault(weight(v), set()).add(nullity) + require(by_weight == {3: {4}, 7: {9}}, "nullities %s" % by_weight) + + # The one-dimensional syzygy of Φ lies in every homogeneous column space, + # so coefficient nullity is one larger than the dimension of legal columns. + kernel = null_basis(phi, [(i, 0) for i in range(len(vertices))]) + require(len(kernel) == 1, "evaluation corank") + syzygy = kernel[0] + image_dims = {3: set(), 7: set()} + for j, v in enumerate(vertices): + equations = [(i, 0) for i in orth[j]] + [(j, 0)] + basis = null_basis(phi, equations) + require(_in_span(syzygy, basis), "syzygy missed at vertex %d" % j) + images = [] + width = len(phi[0]) + for vector in basis: + images.append([sum(phi[u][t] * vector[t] for t in range(width)) % 3 for u in range(len(vertices))]) + image_dims[weight(v)].add(rank_mod(images)) + require(image_dims == {3: {3}, 7: {8}}, "legal-column dimensions %s" % image_dims) + print("PASS_FAMILY_DIMENSIONS coeff_nullity=4,9 column_dim=3,8") + + index = {v: i for i, v in enumerate(vertices)} + p104 = principal(matrix, [index[v] for v in ports]) + require(valid_pattern(p104, ports), "P104 principal submatrix is not a pattern") + p104_rank = rank_mod(p104) + require(p104_rank == 36, "P104 witness rank %d is not 36" % p104_rank) + digest = matrix_sha256(p104) + require(digest == P104_MATRIX_SHA256, "P104 matrix sha256 %s" % digest) + + deleted = [v for v in vertices if v not in set(ports)] + require(len(deleted) == 16, "deleted set") + cliques = odd_cliques(deleted, 8) + require(len(cliques) == 2, "expected two deleted 8-cliques") + require(set(cliques) == set(CLIQUE_RANK), "deleted cliques changed: %s" % (cliques,)) + seen = {} + for clique in cliques: + block = list(ports) + list(clique) + rows = principal(matrix, [index[v] for v in block]) + require(len(block) == 112 and valid_pattern(rows, block), "P112 pattern") + seen[clique] = rank_mod(rows) + require(seen == CLIQUE_RANK, "P112 ranks %s" % seen) + print("PASS_CHAR3_WITNESS p120=37 p104=36 p112=%s" % sorted(seen.values())) + + # Predecessor feature map: no constant term. Same solver, free variables 0. + _phi0, _orth0, _cols0, _null0, matrix0 = factorisation(vertices, constant=False) + require(valid_pattern(matrix0, vertices), "no-constant factorisation is not a pattern") + require(rank_mod(matrix0) == 38, "no-constant P120 rank is not 38") + require(rank_mod(principal(matrix0, [index[v] for v in ports])) == 37, "no-constant P104 rank is not 37") + print("PASS_NO_CONSTANT_COMPARISON p120=38 p104=37") + + # Controls that reject illegal masks and an inconsistent smaller feature map. + planted = [row[:] for row in matrix] + pair = next((i, j) for i in range(120) for j in range(i + 1, 120) if not odd_dot(vertices[i], vertices[j])) + planted[pair[0]][pair[1]] = (planted[pair[0]][pair[1]] + 1) % 3 + require(not valid_pattern(planted, vertices), "control: planted orthogonal entry was accepted") + killed = [row[:] for row in matrix] + killed[0][0] = 0 + require(not valid_pattern(killed, vertices), "control: zero diagonal was accepted") + ones = [[1] * 120 for _ in range(120)] + require(not valid_pattern(ones, vertices), "control: all-ones was accepted") + linear = [[(v >> i) & 1 for i in range(9)] for v in vertices] + linear_fail = 0 + for j in range(0, 120, 17): + equations = [(i, 0) for i in orth[j]] + [(j, 1)] + solution, _free = rref_solve(linear, equations) + if solution is None: + linear_fail += 1 + require(linear_fail >= 1, "control: linear features solved every sampled column") + print("PASS_CONTROLS linear_failures=%d" % linear_fail) + print("PASS_CHAR3_RANK36 p104=36 p120=37 class_constant=120") + + +def _in_span(vector, basis): + if not basis: + return all(entry == 0 for entry in vector) + width = len(vector) + matrix = [[basis[c][r] for c in range(len(basis))] + [vector[r] % 3] for r in range(width)] + cols = len(basis) + rank = 0 + for col in range(cols): + pivot = None + for row in range(rank, width): + if matrix[row][col] % 3: + pivot = row + break + if pivot is None: + continue + matrix[rank], matrix[pivot] = matrix[pivot], matrix[rank] + inverse = pow(matrix[rank][col], -1, 3) + for k in range(col, cols + 1): + matrix[rank][k] = matrix[rank][k] * inverse % 3 + for row in range(width): + if row == rank or matrix[row][col] % 3 == 0: + continue + factor = matrix[row][col] % 3 + for k in range(col, cols + 1): + matrix[row][k] = (matrix[row][k] - factor * matrix[rank][k]) % 3 + rank += 1 + return all(matrix[row][cols] % 3 == 0 for row in range(rank, width)) + + +if __name__ == "__main__": + main()