diff --git a/research/connector-chart-rank-distribution/PROOF.md b/research/connector-chart-rank-distribution/PROOF.md new file mode 100644 index 0000000000..07f10950fa --- /dev/null +++ b/research/connector-chart-rank-distribution/PROOF.md @@ -0,0 +1,163 @@ +# The finite-field chart-repair rank enumerator + +This contribution was produced by Nick Petalas. Apache-2.0. + +## Statement + +Let F be a finite field of order q. Let B0,B1:V -> W be linear maps on the +same finite-dimensional source, with dim W=n. Write + +```text +a = rank B0, b = rank B1, c = dim(row B0 intersect row B1). +``` + +For 0<=r<=n, let N_r count the charts R in GL(W) for which +rank(B1-R B0)=r. The row spaces are subspaces of V*. The source dimension +can be arbitrary, subject to a+b-c<=dim V. The answer depends only on +(q,n,a,b,c), not on the matrices' remaining entries or dim V. + +Use the following conventions: + +```text +G_q(d,k) = Gaussian binomial [d choose k]_q, or 0 if k<0 or k>d; +J_q(d,k) = product_(i=0..k-1) (q^d-q^i), or 0 if k<0 or k>d; +J_q(d,0) = 1; +gamma = J_q(n,n)/J_q(n,a). +``` + +For 0<=t<=n define + +```text +F_t = sum_(h=0..c, 0<=j<=n-b) + G_q(c,h) G_q(n-b,j) q^((c-h)j+t(c-h)) J_q(t,a-c+h), + where j=t-b+c-h. +``` + +Define D_0=F_0 and successively + +```text +D_t = F_t - sum_(r=0..t-1) G_q(n-r,t-r) D_r. +``` + +Then the complete chart counts are N_r=gamma D_r. In particular, if +s=min(a,b) and u=max(a,b), the exact fraction attaining the minimum repair +rank u-c is + +```text +N_(u-c)/|GL_n(F)| = q^(c(u-c)) J_q(u-c,s-c) / J_q(n,s). (1) +``` + +The minimum-rank value itself is ywz65's #2680 theorem, which is cited, +not a new claim. The new result is the complete distribution and its +minimum-rank density. The proof below also explains each counting factor. +Empty dimensions and zero maps obey the same formulas. + +## Normalize the source coordinates + +Choose a basis of the intersection of the two row spaces, extend it +separately to bases of both row spaces, and then extend their union to V*. +Let the corresponding source coordinates be shared coordinates of dimension +c, B0-only coordinates of dimension a-c, B1-only coordinates of dimension +b-c, and unused coordinates. A basis change in W makes B1's nonzero columns +on its coordinates e1,...,eb. + +As R varies, C=R B0 ranges over exactly the maps whose row space equals +row B0. Equivalently, its a potentially nonzero columns form an injective +map from F^a to W. There are J_q(n,a) such maps. Each occurs for exactly +gamma charts: after fixing the images of a independent vectors, extend their +images to an ordered basis in product_(i=a..n-1)(q^n-q^i) ways. Thus it +suffices to count C, and multiply the resulting counts by gamma. + +Let E=span(e_(c+1),...,e_b), of dimension v=b-c, and let +B=span(e1,...,eb). The residual B1-C contains E in its image. Its remaining +columns are e_i-C_i for the shared coordinates and -C_i for the B0-only +coordinates. + +## Count residual images contained in a t-space + +Fix a t-dimensional T<=W. It can contain the residual image only if E<=T. +Put h=dim(T intersect B)-v and j=t-v-h. For such T, the number of choices is + +```text +G_q(c,h) G_q(n-b,j) q^((c-h)j). (2) +``` + +To see this, pass to W/E and its distinguished c-dimensional subspace B/E. +Choose the h-dimensional intersection, choose the j-dimensional image in +W/B, and choose its lift modulo the intersection. These lifts are the +linear maps from a fixed j-space to a (c-h)-space, giving q^((c-h)j). +This standard subspace-intersection count uses no independence assumption +about random charts. + +The condition im(B1-C)<=T prescribes C modulo T: shared coordinates map to +e_i mod T and B0-only coordinates map to zero. This prescribed quotient map +has rank c-h and kernel dimension a-c+h. An injective lift C must map that +kernel injectively into T, giving J_q(t,a-c+h) choices. On a fixed +complement of the kernel, each of the c-h basis vectors has q^t possible +lifts, independently. Their images are independent modulo T, so these +choices introduce no further injectivity condition. There are therefore + +```text +q^(t(c-h)) J_q(t,a-c+h) (3) +``` + +injective lifts. Multiplying (2) and (3) and summing h gives F_t. Thus F_t +counts pairs (C,T) with C injective, dim T=t and im(B1-C)<=T. + +## Recover the exact ranks + +If im(B1-C) has dimension r, its t-dimensional superspaces are in bijection +with the (t-r)-subspaces of W/im(B1-C). Consequently + +```text +F_t = sum_(r=0..t) D_r G_q(n-r,t-r), (4) +``` + +where D_r counts injective C with residual rank r. The diagonal coefficient +in this triangular system is one, so the displayed recurrence recovers +all D_r uniquely. The chart multiplicity gives N_r=gamma D_r. This proves +the full distribution for every finite field, including extension fields. + +## Extract the minimum density + +First assume a<=b. The residual contains E of dimension b-c. At t=b-c, +j=-h in the formula for F_t, so only h=0 is possible. Hence + +```text +D_(b-c) = F_(b-c) = q^(c(b-c)) J_q(b-c,a-c). +``` + +No lower residual rank can occur because E is contained in every residual +image. Dividing by J_q(n,a) proves (1) when a<=b. For the other order, the +bijection R -> R^-1 preserves the residual rank after swapping B0 and B1: + +```text +rank(B1-R B0) = rank(B0-R^-1 B1). +``` + +Apply the first case to the swapped maps. This also proves the symmetry of +the complete chart counts in a and b. There is no assertion that the +numbers of injective C, before multiplying by gamma, are symmetric. + +## Worked exact example + +Over F2 take dim W=3, dim V=3 and + +```text +B0 = [[1,0,0], [0,1,0], [0,0,0]], +B1 = [[1,0,0], [0,0,1], [0,0,0]]. +``` + +Here a=b=2,c=1. The containment counts are (0,2,30,42). Triangular +inversion gives D=(0,2,24,16), and gamma=4. Thus among all 168 invertible +charts the residual-rank histogram is + +```text +rank 0 1 2 3 +charts 0 8 96 64. +``` + +Exactly 1/21 of the charts have the minimum rank one. Equal map ranks by +themselves do not determine this distribution: with c=2 the same n,a,b +instead give (4,60,104,0). These are counts of charts, not distinct residual +maps, scalar circuit words, or physically legal native adapters. diff --git a/research/connector-chart-rank-distribution/README.md b/research/connector-chart-rank-distribution/README.md new file mode 100644 index 0000000000..0d9d815f81 --- /dev/null +++ b/research/connector-chart-rank-distribution/README.md @@ -0,0 +1,126 @@ +# Count every finite-field connector chart repair rank + +This contribution was produced by Nick Petalas. Apache-2.0. + +Claim type: scoped algebraic proof with finite corroboration. For fixed maps +B0,B1:V -> F_q^n, this package gives the complete histogram of +rank(B1-R B0) over R in GL_n(F_q). It depends only on the two ranks a,b, +their row-space intersection dimension c, n and q. A Gaussian-binomial +containment count followed by triangular inversion gives every coefficient. +[PROOF.md](PROOF.md) proves the formula over every finite field. + +If s=min(a,b), u=max(a,b), and +J_q(d,k)=product_(i=0..k-1)(q^d-q^i), the exact fraction of charts attaining +the minimum rank u-c is + +```text +q^(c(u-c)) J_q(u-c,s-c) / J_q(n,s). +``` + +The minimum rank is the cited result of ywz65's +[PR #2680](https://github.com/CrocSwap/integer-mult-bounds/pull/2680). +The new contribution counts the entire distribution and the density of its +minimizers. No predecessor executable or certificate is imported or replayed. + +For q=2,n=3,a=b=2,c=1, the 168 charts have repair-rank histogram +`(0,8,96,64)` at ranks zero through three. Thus exactly 1/21 attain rank one. +With c=2 instead, the histogram is `(4,60,104,0)`. This distinguishes chart +multiplicity from the minimum-rank value and from distinct residual maps. + +## Evidence and reproduction + +The verifier computes the counting formula using integer arithmetic and +compares it with direct matrix subtraction, multiplication and elimination. +Its complete finite domains are: + +- 110 canonical parameter cases over F2,F3,F4,F5, with every codomain + dimension through three for F2 and through two for the other fields. + Every feasible a,b,c occurs, and every invertible chart is enumerated. + These cases make 15,090 individual chart comparisons. +- All 4,096 pairs of binary two-by-three maps and all 6,561 pairs of ternary + two-by-two maps. The combined 10,657 arbitrary pairs make 339,504 chart + comparisons. The formula must give every histogram entry, rather than + only its first nonzero entry. These domains include some canonical cases. +- Six invalid-parameter controls and four mathematical controls cover + omitted inversion, omitted chart multiplicity, F4 arithmetic and the + exact minimum-density fixture. F4 is F2[t]/(t^2+t+1), not Z/4. + +From the repository root, using CPython 3.12 and only the standard library: + +```sh +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -B research/connector-chart-rank-distribution/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -O -B research/connector-chart-rank-distribution/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/research_package.py --package research/connector-chart-rank-distribution +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/check_research_commit.py --package research/connector-chart-rank-distribution --check-source-history +``` + +The direct marker is `PASS_CONNECTOR_CHART_RANK_DISTRIBUTION`. +Registered commands have separate 120-second limits. Another CPython 3.12 +path can replace the local path. Both modes use explicit exceptions, and +both are read-only. Each stdout receipt binds all six package files with +SHA256. No receipt is handwritten or stored in the package. Provenance +pins authenticate historical source bytes, not predecessor mathematics. + +## Scope and code constraints + +The universal claim is the written counting proof. Finite execution +corroborates its declared domains; independent human and formal proof-kernel +review are unclaimed. The computational formula accepts prime powers +2<=q<=256 and 0<=n<=12. The written theorem has no such upper bounds. + +The chart distribution is over the full general linear group. A restricted +native alphabet, chart synthesis cost, scalar work, physical producer, +restoration, storage, precision and a complete supplier invoice are outside +scope. These costs remain unknown. No particular selected caller is claimed +to need this statistic, and no downstream construction campaign follows. +No new kappa, selected-frontier change or complete multiplication theorem +is claimed. Selected scientific cold replay, Lean and Docker were not run. + +All functions are below 60 physical lines, use direct calls and have no +recursion, generated code or external processes. Formula loops have at most +13 iterations per dimension. Field-order validation tries at most 255 +divisors and eight divisions per selected divisor. Oracle matrices have at +most six rows/columns, enumerate at most 625 candidate charts at a time, +and retain at most 81 maps in the arbitrary-pair scan. The largest pair +scan has 6,561 iterations, each with at most 48 charts. Invalid field orders, +rank parameters and dimension overflow raise explicit errors. Warnings are +errors in both registered commands. No external static analyzer is required +or claimed. + +Power of Ten rule 3 deviation: CPython and its standard library allocate +integers, tuples and elimination rows dynamically. The enforced formula +capacity and fixed oracle domains above bound live memory. Each comparison +releases its temporary matrices; only bounded collections and counters +persist. Both modes exercise the finite scans and capacity rejection. A +fixed-allocation port would be needed before native or long-lived use. + +## Open next questions + +1. For a named physical caller with a legal restricted chart alphabet, how + much of this minimum-rank density survives? Begin by specifying that + alphabet and its complete chart, injection and restoration prices. The + unrestricted distribution is a reference count, not a physical tariff. +2. Can one sample a minimum-rank chart uniformly without enumerating GL_n? + The injective-lift proof suggests a constructive sampler. An exact + uniformity proof and the actual caller's selection cost are still needed. + This package does not reserve or implement that extension. + +## Credit and assignment + +Credit ywz65 #2680 for the paid residual-rank interface and minimum theorem, +woklerx for the equal-kernel dirty-chart contract, and Ross Richardson #943 +for the dirty-query and complete-call context. Gaussian coefficients, +subspace-intersection counting and triangular inversion are classical. +This is a new application and formula in that interface, with no claim of +literature-wide priority. All predecessor files and credit lines are unchanged. + +The `connector-alphabet-change` card is explicitly changed to an algebraic +side result about chart multiplicity. It adds neither a connector operation +nor a favorable completed budget. The user's original-work restriction +supersedes the card's predecessor-replay example. Current selected-binding +orientation passed; it is metadata evidence only. Live claims, open PRs, +merged-PR searches and main README searches were used for overlap. The +cached helper covered 416 open PRs and 5,307 Discussion records, but sparse +local coverage omitted 7,622 notes. Targeted searches of all main READMEs +supplemented that cache; unpublished work and arbitrary diffs remain outside +coverage. Lack of a matching record does not establish novelty. diff --git a/research/connector-chart-rank-distribution/SOURCES.json b/research/connector-chart-rank-distribution/SOURCES.json new file mode 100644 index 0000000000..550304c620 --- /dev/null +++ b/research/connector-chart-rank-distribution/SOURCES.json @@ -0,0 +1,36 @@ +{ + "schema_version": 1, + "base_commit": "de5ec2e7a6074068452f45b1a191b5c72832df4a", + "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/connector-chart-rank-repair/README.md", + "usage": "provenance", + "git_blob": "298bf702a48b6ff2bf3d1e10035aa304ecb25546", + "sha256": "222d197d7ca6cebabc23af9c05db6dec813b7003f7b4bab83aac94dfcd26a745" + }, + { + "path": "research/dirty-connector-chart-transport/README.md", + "usage": "provenance", + "git_blob": "2b161ebfccfc3867d3b6b74cc05c761ba1becfd2", + "sha256": "c3d8b2fcc3485e267e25efc260b37ed7a2e8a0bc7d20294e9c79f0792a253d67" + }, + { + "path": "research/universal-connector-boundary/README.md", + "usage": "provenance", + "git_blob": "d277f7c5830b1f2bc42e1ff41ab86e7d7564929f", + "sha256": "23415f7829ab8d80a783142f10f7d31abbce84579362769984680af3df954476" + } + ] +} diff --git a/research/connector-chart-rank-distribution/TASK.json b/research/connector-chart-rank-distribution/TASK.json new file mode 100644 index 0000000000..b1ae348ec7 --- /dev/null +++ b/research/connector-chart-rank-distribution/TASK.json @@ -0,0 +1,68 @@ +{ + "schema_version": 1, + "task_id": "connector-alphabet-change", + "priority_revision": 8, + "base_commit": "de5ec2e7a6074068452f45b1a191b5c72832df4a", + "original_card": { + "id": "connector-alphabet-change", + "question": "Does one explicit extension of the connector alphabet offer a favorable completed budget?", + "starting_points": [ + "docs/research/research-family-status.md", + "research/universal-connector-boundary/README.md", + "certificates/selected-result.json" + ], + "methods": [ + "Construct and charge a legal extra operation on a minimal instance.", + "Prove a target-specific bound after adding one specified operation family." + ], + "acceptance_gate": "State which fixed-alphabet premise changes and charge its implementation; do not declare it free. 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", + "research/universal-connector-boundary/verify.py" + ], + "expected": "PASS_UNIVERSAL_CONNECTOR_BOUNDARY", + "inspect": "Reproduce the 945-pairing control, then read Exact interface to list the allowed calls.", + "scope": "Positive control / source-bound orientation only; this is not a new construction or full cold replay." + }, + "first_experiment": "Add exactly one legally priced operation and test a tiny dirty-input instance before enumerating larger cases.", + "bottleneck_link": "A new legal connector operation could change recursive interface cost; a larger census in the same alphabet is a separate side result.", + "allowed_variations": [ + "Choose one additional operation and a small source count for its first counterexample." + ], + "scope_change_triggers": [ + "Keeping the alphabet and only increasing the source count; record this as a changed assignment.", + "Extending a source-count census without naming a supplier/interface decision it could change; audit #2973 pruning concerns before relying on the affected predecessor exclusions." + ], + "overlap_terms": [ + "universal connector", + "source-toggle", + "connector alphabet" + ] + }, + "scope_status": "changed", + "actual_scope": "Complete finite-field distribution of rank(B1-R B0) over all invertible codomain charts, with exact minimum-rank density.", + "scope_change_reason": "Original successor counting theorem beyond ywz65 #2680; this is a side result, not an extension of the connector alphabet or a physical supplier.", + "bottleneck_link": "Counts the availability of low-rank paid chart repairs. A selected consumer and complete native costs remain unknown; no implementation campaign is started.", + "budget_minutes": 60, + "stop_rule": "Ship the first proved distribution after bounded matrix corroboration; do not extend to sampling or physical synthesis.", + "outcome": "completed", + "evidence": "PROOF.md proves the all-finite-field formula. verify.py compares 110 canonical cases and 10657 arbitrary map pairs against direct complete chart enumeration.", + "author": "Nick Petalas", + "ai_assistance": "Independent human and formal proof-kernel review are unclaimed.", + "open_questions": [ + { + "question": "Determine the minimum repair-rank distribution in one named caller's restricted legal chart alphabet.", + "why_it_matters": "Full GL_n density does not price or guarantee native availability.", + "first_step": "Specify one physical caller, chart alphabet and complete prices.", + "blocked_by": "No concrete physical consumer is supplied." + }, + { + "question": "Sample a minimum-rank chart exactly uniformly without enumerating GL_n.", + "why_it_matters": "A constructive sampler could make the counting proof usable for chart selection.", + "first_step": "Turn the injective-lift factorization into a sampler and prove its output law.", + "blocked_by": "Uniformity and physical selection costs are unproved." + } + ] +} diff --git a/research/connector-chart-rank-distribution/VERIFY.json b/research/connector-chart-rank-distribution/VERIFY.json new file mode 100644 index 0000000000..8dcc27d0dc --- /dev/null +++ b/research/connector-chart-rank-distribution/VERIFY.json @@ -0,0 +1,34 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [], + "commands": [ + { + "argv": [ + "{python}", + "-I", + "-W", + "error", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Full chart-rank histograms, finite-field canonical and arbitrary-pair oracles, invalid-input and mathematical controls." + }, + { + "argv": [ + "{python}", + "-I", + "-W", + "error", + "-O", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Full chart-rank histograms, finite-field canonical and arbitrary-pair oracles, invalid-input and mathematical controls." + } + ] +} diff --git a/research/connector-chart-rank-distribution/verify.py b/research/connector-chart-rank-distribution/verify.py new file mode 100644 index 0000000000..9d5eff4531 --- /dev/null +++ b/research/connector-chart-rank-distribution/verify.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 +"""Exact chart-rank enumerator and bounded independent matrix oracles.""" +from collections import Counter +from fractions import Fraction +from hashlib import sha256 +from itertools import product +from math import prod +from pathlib import Path +import json +import sys + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def prime_power(q): + require(type(q) is int and 2 <= q <= 256, "field order capacity") + for p in range(2, q + 1): + if q % p == 0: + remaining = q + for _ in range(8): + if remaining % p == 0: + remaining //= p + return remaining == 1 + return False + + +def gaussian(q, n, k): + if k < 0 or k > n: + return 0 + numerator = prod(q ** (n - i) - 1 for i in range(k)) + denominator = prod(q ** (k - i) - 1 for i in range(k)) + require(numerator % denominator == 0, "nonintegral Gaussian coefficient") + return numerator // denominator + + +def injections(q, n, k): + return prod(q ** n - q ** i for i in range(k)) if 0 <= k <= n else 0 + + +def validate(q, n, a, b, c): + require(prime_power(q), "order is not a prime power") + require(all(type(x) is int for x in (n, a, b, c)), "dimensions must be integers") + require(0 <= n <= 12, "codomain dimension capacity") + require(0 <= a <= n and 0 <= b <= n, "map rank range") + require(0 <= c <= min(a, b), "intersection dimension range") + + +def containment_moments(q, n, a, b, c): + moments = [] + for t in range(n + 1): + total = 0 + for h in range(c + 1): + j = t - b + c - h + if 0 <= j <= n - b: + spaces = gaussian(q, c, h) * gaussian(q, n - b, j) + spaces *= q ** ((c - h) * j) + lifts = q ** (t * (c - h)) * injections(q, t, a - c + h) + total += spaces * lifts + moments.append(total) + return tuple(moments) + + +def rank_distribution(q, n, a, b, c): + """Return counts of GL_n charts at each residual rank, including zero.""" + validate(q, n, a, b, c) + moments = containment_moments(q, n, a, b, c) + counts = [] + for t in range(n + 1): + lower = sum(counts[r] * gaussian(q, n - r, t - r) for r in range(t)) + counts.append(moments[t] - lower) + multiplicity = injections(q, n, n) // injections(q, n, a) + result = tuple(multiplicity * value for value in counts) + require(all(value >= 0 for value in result), "negative chart count") + require(sum(result) == injections(q, n, n), "chart total") + return result + + +def minimum_density(q, n, a, b, c): + validate(q, n, a, b, c) + s, r = min(a, b), max(a, b) + numerator = q ** (c * (r - c)) * injections(q, r - c, s - c) + return Fraction(numerator, injections(q, n, s)) + + +def add(a, b, q): + return a ^ b if q == 4 else (a + b) % q + + +def multiply(a, b, q): + if q != 4: + return a * b % q + a0, a1, b0, b1 = a & 1, a >> 1, b & 1, b >> 1 + return (a0 * b0 ^ a1 * b1) | ((a0 * b1 ^ a1 * b0 ^ a1 * b1) << 1) + + +def negative(a, q): + return a if q == 4 else -a % q + + +def matrix_rank(matrix, q): + require(q in (2, 3, 4, 5), "oracle field capacity") + require(len(matrix) <= 6, "oracle row capacity") + width = len(matrix[0]) if matrix else 0 + require(width <= 6 and all(len(row) == width for row in matrix), "oracle shape") + require(all(type(x) is int and 0 <= x < q for row in matrix for x in row), "field entry") + rows = [list(row) for row in matrix] + rank = 0 + for column in range(width): + pivot = next((i for i in range(rank, len(rows)) if rows[i][column]), None) + if pivot is None: + continue + rows[rank], rows[pivot] = rows[pivot], rows[rank] + value = rows[rank][column] + inverse = multiply(value, value, q) if q == 4 else pow(value, q - 2, q) + rows[rank] = [multiply(x, inverse, q) for x in rows[rank]] + for i in range(rank + 1, len(rows)): + coefficient = negative(rows[i][column], q) + rows[i] = [add(x, multiply(coefficient, y, q), q) + for x, y in zip(rows[i], rows[rank])] + rank += 1 + return rank + + +def matrices(q, rows, columns): + require(rows <= 3 and columns <= 3 and q ** (rows * columns) <= 6561, + "matrix enumeration capacity") + for entries in product(range(q), repeat=rows * columns): + yield tuple(tuple(entries[i * columns:(i + 1) * columns]) for i in range(rows)) + + +def general_linear(q, n): + return tuple(matrix for matrix in matrices(q, n, n) if matrix_rank(matrix, q) == n) + + +def matmul(left, right, q): + width = len(right[0]) if right else 0 + output = [] + for row in left: + target = [] + for j in range(width): + value = 0 + for k in range(len(right)): + value = add(value, multiply(row[k], right[k][j], q), q) + target.append(value) + output.append(tuple(target)) + return tuple(output) + + +def subtract(left, right, q): + return tuple(tuple(add(x, negative(y, q), q) for x, y in zip(a, b)) + for a, b in zip(left, right)) + + +def canonical_pair(n, a, b, c): + width = a + b - c + first = tuple(tuple(int(j == i) for j in range(width)) if i < a + else (0,) * width for i in range(n)) + second = tuple(tuple(int((i < c and j == i) or + (c <= i < b and j == a + i - c)) + for j in range(width)) for i in range(n)) + return first, second + + +def check_oracle(q, n, first, second, charts): + a, b = matrix_rank(first, q), matrix_rank(second, q) + c = a + b - matrix_rank(first + second, q) + actual = Counter(matrix_rank(subtract(second, matmul(r, first, q), q), q) + for r in charts) + expected = rank_distribution(q, n, a, b, c) + require(tuple(actual[t] for t in range(n + 1)) == expected, "matrix oracle mismatch") + density = minimum_density(q, n, a, b, c) + require(Fraction(actual[max(a, b) - c], len(charts)) == density, "minimum density") + require(expected == rank_distribution(q, n, b, a, c), "chart inversion symmetry") + return len(charts) + + +def canonical_oracles(): + cases = comparisons = 0 + for q, maximum in ((2, 3), (3, 2), (4, 2), (5, 2)): + for n in range(maximum + 1): + charts = general_linear(q, n) + require(len(charts) == injections(q, n, n), "GL enumeration") + for a in range(n + 1): + for b in range(n + 1): + for c in range(min(a, b) + 1): + first, second = canonical_pair(n, a, b, c) + comparisons += check_oracle(q, n, first, second, charts) + cases += 1 + return cases, comparisons + + +def arbitrary_pair_oracles(): + pairs = comparisons = 0 + for q, n, width in ((2, 2, 3), (3, 2, 2)): + charts = general_linear(q, n) + maps = tuple(matrices(q, n, width)) + for first in maps: + transformed = tuple(matmul(r, first, q) for r in charts) + for second in maps: + a, b = matrix_rank(first, q), matrix_rank(second, q) + c = a + b - matrix_rank(first + second, q) + actual = Counter(matrix_rank(subtract(second, x, q), q) for x in transformed) + expected = rank_distribution(q, n, a, b, c) + require(tuple(actual[t] for t in range(n + 1)) == expected, + "arbitrary-pair distribution") + pairs += 1 + comparisons += len(charts) + return pairs, comparisons + + +def controls(): + rejected = 0 + bad = ((6, 3, 2, 2, 1), (2, 13, 2, 2, 1), (2, 3, 4, 2, 1), + (2, 3, 2, 2, 3), (2, 3, 2.0, 2, 1), (1, 3, 2, 2, 1)) + for arguments in bad: + try: + rank_distribution(*arguments) + except ValueError: + rejected += 1 + else: + raise ValueError("invalid input accepted") + require(rank_distribution(2, 3, 2, 2, 1) == (0, 8, 96, 64), "worked example") + moments = containment_moments(2, 3, 2, 2, 1) + require(moments == (0, 2, 30, 42), "containment fixture") + require(tuple(4 * x for x in moments) != (0, 8, 96, 64), "inversion omission control") + require(sum((0, 2, 24, 16)) != 168, "stabilizer omission control") + require(multiply(2, 2, 4) == 3 and add(2, 2, 4) == 0, "F4 is not Z/4") + require(minimum_density(2, 3, 2, 2, 1) == Fraction(1, 21), "density example") + return rejected, 4 + + +def main(): + canonical, canonical_charts = canonical_oracles() + arbitrary, arbitrary_charts = arbitrary_pair_oracles() + rejected, mathematical_controls = controls() + package = Path(__file__).resolve().parent + names = ("README.md", "PROOF.md", "TASK.json", "SOURCES.json", "VERIFY.json", "verify.py") + hashes = {name: sha256((package / name).read_bytes()).hexdigest() for name in names} + receipt = {"canonical_cases": canonical, "canonical_chart_comparisons": canonical_charts, + "arbitrary_map_pairs": arbitrary, "arbitrary_chart_comparisons": arbitrary_charts, + "invalid_inputs_rejected": rejected, "mathematical_controls": mathematical_controls, + "example": [0, 8, 96, 64], "minimum_fraction": "1/21", + "python": sys.version.split()[0], "sha256": hashes} + print(json.dumps(receipt, sort_keys=True)) + print("PASS_CONNECTOR_CHART_RANK_DISTRIBUTION") + + +if __name__ == "__main__": + main()