diff --git a/research/cubic-reader-rational-repair/PROOF.md b/research/cubic-reader-rational-repair/PROOF.md new file mode 100644 index 0000000000..7209cd0473 --- /dev/null +++ b/research/cubic-reader-rational-repair/PROOF.md @@ -0,0 +1,195 @@ +# Exact rational cube-query repair + +This scoped proof is produced by Nick Petalas. Apache-2.0. + +## Contract and theorem + +Work over Q. The distinct streams y,a,b have arbitrary incoming values. For an +integer r>=2 retain exactly r original children, each performing + +``` +y += a^3 +a += b +``` + +The eager program follows every child by `a -= b`. Its endpoint is +`(y+r*a^3,a,b)`, in entry coordinates. The deferred program retains all the +children and appends a repair. It must have the same endpoint for every input. +There is no intermediate observation and no feedback from y into a or b. + +A repair may apply invertible rational linear changes to the source pair and +add signed, rationally weighted cubes of source linear forms to y. Each such +cube accumulation is one query, including its coefficient. Source changes and +coefficient preparation are additional work. The attaining programs use only +`a += c*b`, preserve b throughout, and explicitly restore a. The lower bound +allows the larger class of all rational source linear forms, so it applies to +these programs too. Extra nonlinear operations, access to original child +interiors, output recoding and output-dependent source changes are excluded. + +**Theorem.** The exact minimum number of appended cube queries is + +``` +2, if q_r = (2r^2-2r-1)/12 is a rational square; +3, otherwise. +``` + +Over R the minimum is always two. In particular r=3 needs three rational +queries, while r=14 needs two. This is a query lower bound and an attaining +restoring program in a declared alphabet, not an arithmetic-circuit lower +bound or a complete supplier cost. + +## Derive the chronological defect + +Child i, indexed from zero, observes `a+i*b` in entry coordinates. Thus the +unrepaired deferred output differs from the eager output by + +``` +f(a,b) = 3S1*a^2*b + 3S2*a*b^2 + S3*b^3, +S1 = r(r-1)/2, +S2 = r(r-1)(2r-1)/6, +S3 = S1^2. +``` + +These expressions follow by expanding each of the r cubes and summing i, +i^2 and i^3 for 0<=i0. + +Every appended source transformation is independent of y and linear in entry +a,b. Consequently any q-query repair represents -f as a sum of q signed +weighted cubes of rational linear forms. Multiple queries in the same +direction can be combined for a lower-bound argument. Any additional linear +output terms cannot change these homogeneous cubic coefficients. + +## Necessity of the rational-square criterion + +One cube cannot represent f. Its zero a^3 coefficient would force its a +coefficient to vanish, contradicting the nonzero a^2*b coefficient. + +Suppose two cubes represent f. Neither linear form can have zero a +coefficient, since the remaining cube would then have a nonzero a^3 +coefficient. Normalize both a coefficients to one, absorbing their cubes +into their rational weights. Cancellation of a^3 makes the weights opposite. +The two directions must be distinct. We therefore have + +``` +f = lambda*((a+t*b)^3 - (a+s*b)^3), t != s. +``` + +Coefficient comparison gives + +``` +lambda*(t-s) = S1, +t+s = S2/S1, +t^2+t*s+s^2 = S3/S1. +``` + +Put `u=(t+s)/2` and `h=(t-s)/2`. The equations become + +``` +u = S2/(2S1), +h^2 = S3/S1 - 3u^2 = (2r^2-2r-1)/12 = q_r. +``` + +If t,s are rational, h is rational. Conversely, if q_r is a rational square, +take its positive rational square root h, set t=u+h, s=u-h, and +`lambda=S1/(2h)`. These choices satisfy all four cubic coefficients. Since +q_r>0 for r>=2, h is nonzero. This proves both directions and the two-query +minimum whenever the square criterion holds. Over R, the positive root always +exists, proving the real statement too. + +## An explicit three-query repair and source restoration + +For any nonzero rational h, direct expansion gives + +``` +f = S1/(2h)*((a+(u+h)*b)^3 - (a+(u-h)*b)^3) + + (S3-3S1*u^2-S1*h^2)*b^3. +``` + +If the square criterion fails, choose h=1. The last coefficient is nonzero, +since otherwise q_r=1 would be a square. This gives exactly three queries. +Starting from the actual drifting source `a+r*b`, append + +``` +a += (u+h-r)*b +y -= S1/(2h)*a^3 +a -= 2h*b +y += S1/(2h)*a^3 +a -= (u-h)*b +y -= (S3-3S1*u^2-S1*h^2)*b^3 +``` + +Omit the final cube only when its coefficient is zero, and omit exactly zero +shifts. The first two cube inputs are the required entry-coordinate forms. +The fifth event returns a to its entry value; b never changes. Subtracting f +gives the eager y endpoint for arbitrary incoming y,a,b. Every event is +invertible because its target is absent from its source expression. Reversing +event order and negating coefficients is a literal inverse. No clean state, +copy, hidden source snapshot or discarded dirty value is used. + +For r=3, u=5/6 and q_r=11/12. The six repair events have shift coefficients +`-7/6,-2,1/6` and cube coefficients `-3/2,3/2,1/4`, the last reading b. +For r=14, u=9/2 and h=11/2. The five repair events are + +``` +a -= 4*b +y -= (91/11)*a^3 +a -= 11*b +y += (91/11)*a^3 +a += b +``` + +Both examples restore the actual source, rather than assuming an entry copy. + +## An integer decision criterion + +The square condition is equivalently the existence of an integer k with + +``` +(2r-1)^2 - 6k^2 = 3. +``` + +Indeed `q_r=((2r-1)^2-3)/24`. If its reduced rational square root is A/B, +then B^2 divides 24, so B divides 2. Hence k=2A/B is an integer. The converse +uses the root k/2. This is a decision criterion, not a classification of all +solutions of the Pell-type equation. The bounded checker enumerates arities; +the all-r result is the coefficient proof above. + +## Complete logical event bill and boundaries + +Let `Q_c(N)` price a complete `y += c*a^3` child on N coordinates, including +its coefficient, source access, private restoration and return. Let `L_c(N)` +price a complete `a += c*b`. A b-cube uses the corresponding complete query +price with b as source. Set the prices of omitted zero operations to zero. +Then the eager program costs exactly + +``` +r*Q_1(N) + r*L_1(N) + r*L_-1(N). +``` + +The deferred program costs exactly `r*Q_1(N)+r*L_1(N)` plus every displayed +repair event at its own price. In particular r=14 adds `Q_-91/11 + Q_91/11` +and `L_-4 + L_-11 + L_1`. Its original fourteen cube children all remain. +It saves eleven source-shift events and adds two cube-query events, with +nonunit rational coefficients. Query counts alone do not establish a saving. +Coefficient generation, routing, precision, storage and controller preparation +are additional obligations. No numerical backend price is substituted here. + +The fixed original calls are essential. If they can be opened, the target +`y += r*a^3` can be computed directly and no deferral comparison is needed. +The all-r statement is exact rational arithmetic. Approximate queries, finite +fields, nonlinear source maps and intermediate observations are outside it. +No selected assumption, physical supplier or multiplication theorem is proved. + +## Credit + +Sricharan Vagvala / theon199's [PR #1532](https://github.com/CrocSwap/integer-mult-bounds/pull/1532) +provides the quadratic fixed-reader/paid-repair interface and its sharp +square-query floor. Adam Gall / PR1205 and Hanson Sun / PR1246 retain the +underlying linear deferral and paid repair lineage. Their computations are +cited, not replayed as a deliverable here. + +Binary-form power decomposition is classical. Carlini, Catalisano and Geramita's +[monomial Waring-rank paper](https://arxiv.org/abs/1110.0745) is relevant +background; this proof does not claim a new general Waring-rank theorem. +The contribution is the exact arithmetic-sensitive cubic-reader criterion, +its rational restoring schedules and the stated interface cost consequence. diff --git a/research/cubic-reader-rational-repair/README.md b/research/cubic-reader-rational-repair/README.md new file mode 100644 index 0000000000..3522d487b6 --- /dev/null +++ b/research/cubic-reader-rational-repair/README.md @@ -0,0 +1,126 @@ +# Exact rational query cost for cubic-reader repair + +This contribution is produced by Nick Petalas. Apache-2.0. +Independent human and formal proof-kernel review are unclaimed. + +**Scoped proof with exact finite corroboration. No new kappa.** For every +integer r>=2, retain r children `y += a^3; a += b` and defer their source +restorations. The minimum appended signed cube-query count over rational +source linear forms is exactly two if + +``` +(2r^2-2r-1)/12 is a rational square, +``` + +and exactly three otherwise. Over the reals it is always two. Thus rational +source frames impose a cost invisible in the real relaxation. [PROOF.md](PROOF.md) +derives the defect, proves necessity by coefficient comparison, constructs +attaining schedules and includes every source restoration. + +The first discriminator is r=3, whose criterion value is 11/12. Its rational +repair needs three queries. At r=14 the value is 121/4, and the optimal repair +from the actual final source `a_entry+14*b` is + +``` +a -= 4*b +y -= (91/11)*a^3 +a -= 11*b +y += (91/11)*a^3 +a += b +``` + +Every source and output starts arbitrary; b stays unchanged. Original child +calls remain intact. No entry snapshot or clean scratch is assumed. The +fourteen-child program saves eleven source-shift events and adds two cube +queries. Its complete backend tariff still includes the displayed nonunit +coefficients, private restoration, source access and physical implementation. +This is not a claim that the resulting program is cheaper. + +## Reproduce + +From the repository root, using CPython 3.12 and its standard library: + +```sh +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -B research/cubic-reader-rational-repair/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -O -B research/cubic-reader-rational-repair/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/research_package.py --package research/cubic-reader-rational-repair +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/check_research_commit.py --package research/cubic-reader-rational-repair --check-source-history +``` + +Replace the absolute interpreter path with a local CPython 3.12 executable on +another machine. The direct success marker is +`PASS_CUBIC_READER_RATIONAL_REPAIR`, in a generated JSON receipt bound to the +SHA256 hashes of all six package files. No receipt is hand-written and the +verifier writes nothing. Both registered commands have a 120-second limit. + +[verify.py](verify.py) checks eager, repaired and inverse maps by full cubic +polynomial convolution, rather than relying on coordinate-basis inputs. It +also executes dirty integer and rational triples, scans the square criterion +through r=10,000, and compares both directions of the two-cube coefficient +equations on a fixed rational slope set. The scan lists the exact two-query +arities in its bounded domain. The all-r lower bound rests on the written +proof, not extrapolation from that scan. Mutation controls omit restoration, +omit or reverse the last cube correction, and reverse chronology; separate +controls check the arithmetic boundary and the failure of basis-only tests. + +## Provenance and limits + +This changes the `joint-query-controller` card to a self-contained nonlinear +interface side result. Its connection is the cost of preserving original +recursive calls while repairing their shared source at a later boundary. +No current supplier with these indivisible cubic readers is identified. +The positive-control command `scripts/research_selected_baseline.py` passed +with `PASS_RESEARCH_BASELINE_BINDINGS_ONLY`. That is orientation, not a +scientific replay. At canonical base +`a5bff3bf133e482541c09eba4e773884bdb2b1b7`, priority revision 8, the selected +record resolves to PR6030, kappa .003125804. Older priority prose still names +PR5599; this package follows the selected record and changes neither. + +Credit Sricharan Vagvala / theon199's [PR #1532](https://github.com/CrocSwap/integer-mult-bounds/pull/1532) +for the quadratic fixed-reader/paid-repair interface and its square-query +floor, Adam Gall / PR1205 for linear observation, and Hanson Sun / PR1246 for +paid linear repair. Their computations are cited premises, not rechecked +deliverables. Classical binary-form power decompositions retain their credit, +including Carlini, Catalisano and Geramita's +[Waring-rank work](https://arxiv.org/abs/1110.0745). No general Waring-rank +theorem or literature-priority claim is made. The new result is the exact +arithmetic-sensitive cubic interface criterion and its restoring schedules. + +[SOURCES.json](SOURCES.json) pins the predecessor README, task card and selected +record as historical provenance. There are no external scientific runtime +inputs and no predecessor program is imported. Live PRs, current handoffs, +local reservations, recent account work and merged README/PR searches were +checked. The overlap cache's sparse local-note inventory is incomplete, so +absence of a match is not proof of novelty. The +[advance claim](https://github.com/CrocSwap/integer-mult-bounds/discussions/1166#discussioncomment-19272267) +states the same delivered mathematical scope. + +The theorem excludes output feedback, altered child interiors, intermediate +observations, nonlinear source maps, approximate queries and finite fields. +Source-frame and coefficient work is paid separately from query count. No +physical native realization, precision or stock bound, all-size compiler, +complete caller invoice, selected assumption discharge, Lean build, Docker +replay or complete multiplication theorem is supplied. + +The verifier has no recursion, subprocess, dynamic evaluation or input CLI. +Its arities are bounded by 10,000, full polynomial programs by r=64, and +numeric programs by r=32. States contain at most five cubic monomials; all +event lists have finite capacities derived from these bounds. Every function +is below sixty lines and checks use explicit exceptions under optimized Python. +Python managed allocation is a Power of Ten rule 3 deviation, bounded by the +fixed fixture sizes. The two callback targets used only for rejection controls +are a rule 9 deviation. Warning-strict normal and optimized replay provide the +available diagnostics; no external static analyzer or proof kernel is claimed. + +## Open next questions + +1. Which admissible dyadic coefficients permit the same two-query minimum? + Rational square roots alone do not ensure that query weights and source + shifts are dyadic. Start with the two normalized slopes and weight forced + by the proof. The missing step is a prime-denominator classification. +2. Does an actual recursive supplier expose indivisible cubic readers for + which the complete r=14 tariff beats eager restoration? Start by pinning + its child return map and pricing every displayed query and source shift. + No such admitted backend or physical coefficient implementation is supplied. + +Structured relevance, first steps and blockers are in [TASK.json](TASK.json). diff --git a/research/cubic-reader-rational-repair/SOURCES.json b/research/cubic-reader-rational-repair/SOURCES.json new file mode 100644 index 0000000000..65c5c3e373 --- /dev/null +++ b/research/cubic-reader-rational-repair/SOURCES.json @@ -0,0 +1,24 @@ +{ + "schema_version": 1, + "base_commit": "a5bff3bf133e482541c09eba4e773884bdb2b1b7", + "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" + }, + { + "path": "research/quadratic-reader-restoration/README.md", + "usage": "provenance", + "git_blob": "71c6d22f174f1984cd5aa52b984efa1e08aba289", + "sha256": "eaf5278c40eeab8235014926fda17f3fe163c808ab642704802ee26dddc8ce68" + } + ] +} diff --git a/research/cubic-reader-rational-repair/TASK.json b/research/cubic-reader-rational-repair/TASK.json new file mode 100644 index 0000000000..a5b5db83e6 --- /dev/null +++ b/research/cubic-reader-rational-repair/TASK.json @@ -0,0 +1,99 @@ +{ + "schema_version": 1, + "task_id": "joint-query-controller", + "priority_revision": 8, + "base_commit": "a5bff3bf133e482541c09eba4e773884bdb2b1b7", + "original_card": { + "id": "joint-query-controller", + "question": "Can a changed query demand or caller remove real work while satisfying native chronology and restoration?", + "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" + ], + "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": "Choose an exact caller and a new demand/interface hypothesis. Read the scoped #5617/#5631/#5649/#5747 and #5720/#5745 objections before rebuilding an excluded schedule. Compare the complete matched source/consumer protocols including all retained helper outputs. For an active-mode injection, first check #5745: its canonical delivery claim repays the eight removed centre jobs. Audit that exact claim or change its channel/feedback hypothesis; do not repeat the same free-injection search. Stop if the full favorable budget fails or the required restored output is unobservable.", + "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": [ + "query demand", + "active mode", + "5720", + "5745", + "5747", + "caller" + ], + "existing_checks": [ + { + "scope": "PR #4166: author-checked installed producer/service/return/bridge connection; native-component comparison loses.", + "evidence": "research/qq16-caller-install/README.md", + "remaining": "Complete matched physical protocol bill, or changed source-compatible demand/circuit; no affordable supplier yet.", + "status": "author-checked", + "source_commit": "0b082d22a0e9a442d264ab0633e35ef26c790630", + "selected_record_sha256": "bb2eaa58647b353f88d0aec2eafb9d30df1be53589231b23e12ceef3e4bad129" + }, + { + "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": "Exact rational versus real appended cube-query minimum for fixed cubic-reader batches, including explicit dirty-source restoration.", + "scope_change_reason": "The donated assignment forbids audit deliverables. This is a new cubic nonlinear-interface side result building on another contributor, rather than a selected caller replay or an audit of the quadratic predecessor.", + "bottleneck_link": "It identifies a rational-frame repair cost missed by a real relaxation. No supported supplier with these indivisible cubic readers is identified, so no selected budget improvement is inferred.", + "budget_minutes": 60, + "stop_rule": "Stop after the square criterion and restoring schedules pass bounded exact checks; defer dyadic coefficients and actual backend adoption.", + "outcome": "completed", + "evidence": "PROOF.md and verify.py: coefficient lower bound, explicit rational repair, polynomial endpoints/inverses, arbitrary dirty fixtures, bounded square scan and mutation controls.", + "author": "Nick Petalas", + "ai_assistance": "Independent human and formal proof-kernel review are unclaimed.", + "open_questions": [ + { + "question": "Which dyadic source and query coefficients attain the two-query count?", + "why_it_matters": "Rational existence need not give an admissible dyadic implementation.", + "first_step": "Apply prime-denominator tests to the uniquely forced normalized slopes and weights.", + "blocked_by": "No dyadic coefficient classification is proved." + }, + { + "question": "Can an actual indivisible cubic-reader supplier profit from the r=14 repair?", + "why_it_matters": "The added cube calls may exceed the saved source restorations.", + "first_step": "Pin one child return map and price all displayed source shifts and signed cube accumulations.", + "blocked_by": "No such admitted backend or physical coefficient implementation is supplied." + } + ], + "coordination": { + "claim": "https://github.com/CrocSwap/integer-mult-bounds/discussions/1166#discussioncomment-19272267", + "source": "PR #1532", + "source_author": "theon199", + "main_checked": "a5bff3bf133e482541c09eba4e773884bdb2b1b7", + "selected_pr": 6030, + "selected_kappa": ".003125804", + "coverage": "Live open PRs, latest 30 handoff comments, active discussions, account contributions since October 22, reservations, full main README searches, targeted merged PR searches; sparse overlap-note inventory incomplete." + } +} diff --git a/research/cubic-reader-rational-repair/VERIFY.json b/research/cubic-reader-rational-repair/VERIFY.json new file mode 100644 index 0000000000..27c1098010 --- /dev/null +++ b/research/cubic-reader-rational-repair/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 polynomial endpoint and inverse, dirty cases, rational square criterion, coefficient-pair scan and failure controls." + }, + { + "argv": [ + "{python}", + "-I", + "-W", + "error", + "-O", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Same exact checks with optimization enabled; no assertions are required." + } + ] +} diff --git a/research/cubic-reader-rational-repair/verify.py b/research/cubic-reader-rational-repair/verify.py new file mode 100644 index 0000000000..650ca747fe --- /dev/null +++ b/research/cubic-reader-rational-repair/verify.py @@ -0,0 +1,251 @@ +"""Exact bounded evidence for the cubic-reader repair theorem; stdlib only.""" + +from fractions import Fraction as F +from hashlib import sha256 +from itertools import combinations, product +import json +from math import comb, isqrt +from pathlib import Path +import platform + + +MAX_R = 10_000 +PACKAGE_FILES = ("README.md", "PROOF.md", "TASK.json", "SOURCES.json", + "VERIFY.json", "verify.py") + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def validate_r(r): + require(type(r) is int and 2 <= r <= MAX_R, "r outside bounded domain") + + +def moments(r): + validate_r(r) + s1 = F(r * (r - 1), 2) + s2 = F(r * (r - 1) * (2 * r - 1), 6) + return s1, s2, s1 * s1 + + +def rational_root(value): + require(isinstance(value, F) and value >= 0, "invalid square-root input") + a, b = isqrt(value.numerator), isqrt(value.denominator) + if a * a == value.numerator and b * b == value.denominator: + return F(a, b) + return None + + +def repair(r): + """Events (kind, source, coefficient); a += cb or y += c source^3.""" + s1, s2, s3 = moments(r) + u = s2 / (2 * s1) + root = rational_root(s3 / s1 - 3 * u * u) + h = F(1) if root is None else root + require(h > 0, "distinct query slopes required") + weight = s1 / (2 * h) + events = [("shift", "b", u + h - r), ("cube", "a", -weight), + ("shift", "b", -2 * h), ("cube", "a", weight), + ("shift", "b", -u + h)] + residual = s3 - 3 * s1 * u * u - s1 * h * h + if residual: + events.append(("cube", "b", -residual)) + return tuple(event for event in events if event[2]) + + +def batch(r, eager): + validate_r(r) + events = [] + for _ in range(r): + events.extend((("cube", "a", F(1)), ("shift", "b", F(1)))) + if eager: + events.append(("shift", "b", F(-1))) + if not eager: + events.extend(repair(r)) + return tuple(events) + + +def inverse(events): + return tuple((kind, source, -c) for kind, source, c in reversed(events)) + + +def execute(events, state): + y, a, b = state + for kind, source, coefficient in events: + require(kind in ("shift", "cube"), "unknown event") + require(source in ("a", "b"), "invalid source") + if kind == "shift": + require(source == "b", "shift must preserve b") + a += coefficient * b + else: + value = a if source == "a" else b + y += coefficient * value ** 3 + return y, a, b + + +def add(left, right): + result = dict(left) + for exponent, coefficient in right.items(): + result[exponent] = result.get(exponent, F(0)) + coefficient + if not result[exponent]: + del result[exponent] + require(len(result) <= 5, "polynomial state exceeds cubic capacity") + return result + + +def scale(poly, coefficient): + return {e: c * coefficient for e, c in poly.items() if c * coefficient} + + +def multiply(left, right): + result = {} + for x, cx in left.items(): + for z, cz in right.items(): + exponent = tuple(x[i] + z[i] for i in range(3)) + require(sum(exponent) <= 3, "degree exceeds cubic contract") + result[exponent] = result.get(exponent, F(0)) + cx * cz + return {e: c for e, c in result.items() if c} + + +def polynomial_endpoint(events): + """Generic convolution, without the closed-form defect/moment formulas.""" + y, a, b = ({(1, 0, 0): F(1)}, {(0, 1, 0): F(1)}, + {(0, 0, 1): F(1)}) + for kind, source, coefficient in events: + if kind == "shift": + a = add(a, scale(b, coefficient)) + else: + value = a if source == "a" else b + cube = multiply(multiply(value, value), value) + y = add(y, scale(cube, coefficient)) + return y, a, b + + +def check_polynomials(): + for r in range(2, 65): + eager, deferred = batch(r, True), batch(r, False) + expected = ({(1, 0, 0): F(1), (0, 3, 0): F(r)}, + {(0, 1, 0): F(1)}, {(0, 0, 1): F(1)}) + require(polynomial_endpoint(eager) == expected, "eager endpoint") + require(polynomial_endpoint(deferred) == expected, "repair endpoint") + identity = polynomial_endpoint(()) + require(polynomial_endpoint(deferred + inverse(deferred)) == identity, + "polynomial inverse endpoint") + raw = tuple(event for _ in range(r) for event in + (("cube", "a", F(1)), ("shift", "b", F(1)))) + raw_output = polynomial_endpoint(raw)[0] + s1, s2, s3 = moments(r) + defect = add(raw_output, scale(expected[0], F(-1))) + require(defect == {(0, 2, 1): 3 * s1, (0, 1, 2): 3 * s2, + (0, 0, 3): s3}, "chronological defect") + return 63 + + +def check_dirty_inputs(): + count = 0 + states = tuple(product((F(-1), F(0), F(1)), repeat=3)) + states += ((F(5, 7), F(-2, 3), F(7, 11)), + (F(-4, 5), F(13, 8), F(-3, 2))) + for r in range(2, 33): + for eager in (True, False): + events = batch(r, eager) + for state in states: + y, a, b = state + result = execute(events, state) + require(result == (y + r * a ** 3, a, b), "dirty endpoint") + require(execute(inverse(events), result) == state, "dirty inverse") + count += 1 + return count + + +def check_square_criterion(): + two_query = [] + for r in range(2, MAX_R + 1): + q = F(2 * r * r - 2 * r - 1, 12) + root = rational_root(q) + k = isqrt(((2 * r - 1) ** 2 - 3) // 6) + pell = (2 * r - 1) ** 2 - 6 * k * k == 3 + require((root is not None) == pell, "integer square criterion") + if root is not None: + two_query.append(r) + require(2 * root == k, "Pell witness") + require(two_query == [2, 14, 134, 1322], "bounded two-query arities") + return two_query + + +def check_two_cube_coefficients(): + """Exhaust a bounded rational slope set, directly comparing all coefficients.""" + slopes = sorted({F(a, b) for a in range(-4, 5) for b in range(1, 4)}) + tested = 0 + for r in range(2, 25): + s1, s2, s3 = moments(r) + target = (F(0), 3 * s1, 3 * s2, s3) + for t, s in combinations(slopes, 2): + weight = s1 / (t - s) + coefficients = tuple(weight * comb(3, j) * (t ** j - s ** j) + for j in range(4)) + u, h = (t + s) / 2, (t - s) / 2 + predicted = (2 * s1 * u == s2 and + s1 * (3 * u * u + h * h) == s3) + require((coefficients == target) == predicted, "two-cube necessity") + tested += 1 + return len(slopes), tested + + +def rejected(call): + try: + call() + except ValueError: + return True + return False + + +def check_controls(): + r, state = 3, (F(2), F(1), F(1)) + correct = batch(r, False) + expected = execute(batch(r, True), state) + require(execute(correct[:-1], state) != expected, "missing b-cube control") + wrong = correct[:-1] + (("cube", "b", -correct[-1][2]),) + require(execute(wrong, state) != expected, "b-cube sign control") + no_restore = tuple(e for i, e in enumerate(correct) if i != len(correct) - 2) + require(execute(no_restore, state) != expected, "unrestored source control") + require(execute(tuple(reversed(correct)), state) != expected, + "chronology control") + require(rational_root(F(11, 12)) is None, "r=3 nonsquare boundary") + require(rational_root(F(121, 4)) == F(11, 2), "r=14 square boundary") + require([3 * a * a * b for a, b in ((0, 0), (1, 0), (0, 1))] + == [0, 0, 0] and 3 * 1 * 1 * 1 == 3, "basis-only blind spot") + invalid = (0, 1, -2, MAX_R + 1, True, "3") + require(all(rejected(lambda value=value: repair(value)) for value in invalid), + "invalid arity rejection") + require(rejected(lambda: rational_root(F(-1))), "negative square rejection") + return {"semantic": 7, "invalid_arities": len(invalid), "invalid_roots": 1} + + +def main(): + polynomial_arities = check_polynomials() + dirty_cases = check_dirty_inputs() + two_query = check_square_criterion() + slopes, coefficient_cases = check_two_cube_coefficients() + controls = check_controls() + pilots = {} + for r in (3, 14): + events = repair(r) + pilots[str(r)] = {"repair": [[k, s, str(c)] for k, s, c in events], + "cube_queries": sum(k == "cube" for k, _, _ in events), + "source_shifts": sum(k == "shift" for k, _, _ in events)} + root = Path(__file__).resolve().parent + receipt = {"status": "PASS_CUBIC_READER_RATIONAL_REPAIR", "python": platform.python_version(), + "polynomial_arities": polynomial_arities, "dirty_cases": dirty_cases, + "square_criterion_arities": MAX_R - 1, "two_query_arities": two_query, + "rational_slopes": slopes, "coefficient_cases": coefficient_cases, + "controls": controls, "pilots": pilots, + "sha256": {name: sha256((root / name).read_bytes()).hexdigest() + for name in PACKAGE_FILES}} + print(json.dumps(receipt, sort_keys=True, indent=2)) + + +if __name__ == "__main__": + main()