From e8861a715b3d22fbf398393a98604caaa73c4f8d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 20 Oct 2026 02:45:47 +0000 Subject: [PATCH] Record that one P104 encoder fiber equals axis-0 U. The bank-0 column-0 slice of the frozen PR #3979 encoder is multiplication by U, not a transpose or inverse. This does not replay the PR #3996 checker or change kappa. Co-authored-by: unpaidmoon --- research/p104-axis0-encoder-fiber/PROOF.md | 56 +++++ research/p104-axis0-encoder-fiber/README.md | 64 ++++++ .../p104-axis0-encoder-fiber/SOURCES.json | 24 ++ research/p104-axis0-encoder-fiber/TASK.json | 94 ++++++++ research/p104-axis0-encoder-fiber/VERIFY.json | 29 +++ .../frozen/word_builder.py | 201 +++++++++++++++++ .../p104-axis0-encoder-fiber/test_verify.py | 46 ++++ research/p104-axis0-encoder-fiber/verify.py | 212 ++++++++++++++++++ 8 files changed, 726 insertions(+) create mode 100644 research/p104-axis0-encoder-fiber/PROOF.md create mode 100644 research/p104-axis0-encoder-fiber/README.md create mode 100644 research/p104-axis0-encoder-fiber/SOURCES.json create mode 100644 research/p104-axis0-encoder-fiber/TASK.json create mode 100644 research/p104-axis0-encoder-fiber/VERIFY.json create mode 100644 research/p104-axis0-encoder-fiber/frozen/word_builder.py create mode 100644 research/p104-axis0-encoder-fiber/test_verify.py create mode 100644 research/p104-axis0-encoder-fiber/verify.py diff --git a/research/p104-axis0-encoder-fiber/PROOF.md b/research/p104-axis0-encoder-fiber/PROOF.md new file mode 100644 index 0000000000..52deddc364 --- /dev/null +++ b/research/p104-axis0-encoder-fiber/PROOF.md @@ -0,0 +1,56 @@ +# One encoder fiber is axis 0 of U + +## Statement + +Let `B` be the `8×96` integer matrix rebuilt from the canonical P104 fixture +`research/p104-native-channel/inputs/P104-FIXTURE.json` (SHA256 +`516c06f6ec3cb84be588c546108de897650288576dd5fbf5fe44b9c5546ad8a4`), with the +pivot order `(0,1,3,6,22,31,93,103)` and the same root removal as PR #3979. +Its ASCII JSON digest is +`88e9a726e8c8aec055bfd7cd024883b5c8ecbda0cd6471e591a08c43a108a535`, and it has +384 entries in `{-1,0,1}`. + +Let `U` be the `104×104` matrix + +```text +U = [[I_8, B/2], [0, I_96]] +``` + +over `Q`. Axis 0 varies the row index `i` at a fixed column `j`. On one bank, +that is left multiplication by `U` on each column, the factor `U ⊗ I` in the +row-major layout `index = (bank*104 + i)*104 + j`. + +Let `W` be the encoder word `code_word(B)` emitted by the frozen builder at +`frozen/word_builder.py`, SHA256 +`27bae82fe247fe49b8fc3b5efbd429e2c8c0ee8f56cc4ace748cbb681a5abacc`. Those are +the bytes PR #3996 vendors from PR #3979. This note does not call PR #3996's +checker. + +## Program + +The axis-0 program on bank `0`, column `0`, is: + +1. Halve rows `8..103`. +2. For each nonzero `B[r][c]`, add that unit into row `r` from row `8+c`. +3. Double rows `8..103`. + +After step 1 the tail is `x_tail/2`. Step 2 adds `B x_tail/2` into the pivot +block. Step 3 restores the tail. The net map is `pivot ↦ pivot + (B/2) tail` +and `tail ↦ tail`, which is multiplication by `U`. + +## Word bytes + +`W` contains this 576-event program exactly once, as the contiguous slice +starting at event `41600`. The slice's own indices all lie on bank `0` and +column `0`. Interpreting those events on the 104 row coordinates reproduces +`U` exactly, and the same map is not `U^{-1}`, `U^t`, or `U^{-t}`. + +The offset is the end of the encoder's first sweep. It is found by searching +the emitted events, not by skipping a hardcoded prefix and trusting it. + +## What this does not say + +The encoder's full map is `L = U_r U_c^{-t}`, not this single factor. The +other 415 encoder fibers, both decoders, and both Gram words are not +replayed. No physical consumer, identity-side shear, native tariff, or new κ +is claimed. Selected κ stays `0.001672660197076918`. diff --git a/research/p104-axis0-encoder-fiber/README.md b/research/p104-axis0-encoder-fiber/README.md new file mode 100644 index 0000000000..01fbc0a892 --- /dev/null +++ b/research/p104-axis0-encoder-fiber/README.md @@ -0,0 +1,64 @@ +# One P104 encoder fiber on axis 0 of U + +**Partial audit. No new κ.** Selected κ stays `0.001672660197076918`. + +## Scope and evidence + +Original card: `p104-side-correction`, scope **changed**. The card asks for a +chronological correction program. This package does not write one. + +[Discussion #1166 comment 19035716](https://github.com/CrocSwap/integer-mult-bounds/discussions/1166#discussioncomment-19035716) +asks for an inspection of the literal-index bridge or for one physical +consumer. PR #4125 did the bridge and left the events unread. Its open +question is to compare one frozen encoder fiber from the PR #3996 word bytes +with axis 0 of `U`, without calling that checker. + +That comparison holds for bank `0`, column `0`: + +- `U = [[I_8, B/2], [0, I_96]]`, with `B` rebuilt from the canonical fixture. +- The frozen builder `frozen/word_builder.py` is the PR #3996 vendored copy of + the PR #3979 builder, SHA256 + `27bae82fe247fe49b8fc3b5efbd429e2c8c0ee8f56cc4ace748cbb681a5abacc`. +- Its encoder has 203008 events. The 576-event axis-0 program occurs once, at + offset 41600. Interpreting that slice gives `U`, not `U^{-1}`, `U^t`, or + `U^{-t}`. + +The argument is in [PROOF.md](PROOF.md). Pins are in [SOURCES.json](SOURCES.json). +The checker in PR #3996 is not imported. The other fibers and both Gram words +are not replayed. Algebraic agreement is not a native-call price. + +## Reproduce + +From the repository root, Python 3.12: + +```sh +python3.12 -B scripts/research_package.py --package research/p104-axis0-encoder-fiber +``` + +Expected markers: `PASS_P104_AXIS0_ENCODER_FIBER` and +`PASS_P104_AXIS0_ENCODER_FIBER_TESTS`. + +## Open next questions + +1. Do the other 103 bank-0 axis-0 fibers differ from column 0 only by the + column index? That would cover the `U_r` sweep on one bank. First step: + localize column 1 and compare it with column 0 after substituting the + column. Nothing blocks that check; it was left out to keep this package to + one column. +2. Does one repeated consumer of `(N-P) ⊗ M` pay less than rebuilding the + uncoded Gram pair? PR #4125 already shows rational rank 10816 on each + omitted side. First step: price one consumer of the exhibited inverse of + `N-P` on a single bank. Blocked here because no consumer or complete + allowance is named. + +## Credit + +The fixture and port order are the retained P104 native channel. The encoder +schedule and builder bytes are Chris R / Clear1nsight, PR #3979, head +`a8a1d744811cd7d1f9c43ec7ccbae85ef9695b61`, as vendored by ToikY, PR #3996, +head `b8dd4e04bf8490aca121abc7ba0e503651db6c97`. The index convention and the +one-fiber question are that PR and PR #4125. The slice search and the +interpreted comparison are new. + +Prepared by unpaidmoon with Cursor Grok 4.7 assistance. No independent human +review. Apache-2.0. diff --git a/research/p104-axis0-encoder-fiber/SOURCES.json b/research/p104-axis0-encoder-fiber/SOURCES.json new file mode 100644 index 0000000000..6441450d9e --- /dev/null +++ b/research/p104-axis0-encoder-fiber/SOURCES.json @@ -0,0 +1,24 @@ +{ + "schema_version": 1, + "base_commit": "bb4bccbf42844d2801487450727c2f63e10d1d0f", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "b1fea0c94436b236cc2b7d41a7be032811b94c81", + "sha256": "bb2eaa58647b353f88d0aec2eafb9d30df1be53589231b23e12ceef3e4bad129" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "67f085acd86acd7d4e03922d9cf4b26bca66fed5", + "sha256": "47b42433f5a85809a3aadd29c2c339da2c6ed728e4f7762df6b88bccb7874cf0" + }, + { + "path": "research/p104-native-channel/inputs/P104-FIXTURE.json", + "usage": "input", + "git_blob": "2e16f99b295bb386fd13bd8fbd57b42ef54143a9", + "sha256": "516c06f6ec3cb84be588c546108de897650288576dd5fbf5fe44b9c5546ad8a4" + } + ] +} diff --git a/research/p104-axis0-encoder-fiber/TASK.json b/research/p104-axis0-encoder-fiber/TASK.json new file mode 100644 index 0000000000..b460d613bf --- /dev/null +++ b/research/p104-axis0-encoder-fiber/TASK.json @@ -0,0 +1,94 @@ +{ + "schema_version": 1, + "task_id": "p104-side-correction", + "priority_revision": 6, + "base_commit": "bb4bccbf42844d2801487450727c2f63e10d1d0f", + "original_card": { + "id": "p104-side-correction", + "question": "Can the proposed P104 joint endpoint flags be realized by a chronological correction program with coefficients, dirty restoration and an affordable complete bill?", + "starting_points": [ + "docs/research/research-family-status.md", + "research/p104-native-channel/README.md", + "research/p104-native-channel/PROOF.md", + "docs/research/community-efficient1000-review.md", + "research/p104-joint-unit-flags/README.md" + ], + "methods": [ + "Construct one side-correction word at an explicit chronological cut with the needed frames still available.", + "Derive a lower bound on the side correction and hosting costs that decides whether this channel can beat the selected budget." + ], + "acceptance_gate": "An exact arbitrary-input identity, source/target frame availability and restoration at the chosen cut, plus the complete channel+correction+idle/hosting bill or an explicit favorable bound. The native channel alone is not a supplier. A scoped local result may be retained without a complete supplier. Expanding it into further construction rounds requires the family-level budget and obligation gate in research-family-status.md; an optimistic passing relaxation alone is not acceptance.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read the revision-6 family record and #2981 static joint flags, alongside the reviewed #1991 channel. #2981 is an author-checked source archive, not an independently validated executable correction or a refutation of program-level lifetime floors.", + "scope": "Source-bound orientation only. Read the named package and review before relying on its local evidence; this command is not its replay or supplier admission." + }, + "first_experiment": "After checking live handoffs, pin one named collection from #2981 and attach acquisition/delivery times, source dependencies and coefficient requirements. Test legal access and arbitrary dirty restoration; price any completion against the full channel/endpoint/hosting allowance. Stop with the exact missing implication or a scoped counterexample rather than expanding the static cover census.", + "bottleneck_link": "Completing an already realized changed channel tests a concrete construction opportunity, instead of refining the incumbent packing. A positive local result still needs global and all-size admission.", + "allowed_variations": [ + "One correction factorization, one chronological cut, or one explicit hosting obstruction.", + "A changed correction schedule with an updated full bill and native frame contract." + ], + "scope_change_triggers": [ + "Recompiling the already certified low-rank channel without closing a new obligation.", + "Treating a pending ancestor, local histogram or unpriced side correction as an admitted global supplier.", + "Repeating a correction or physical conversion already supplied by a pending follow-up without adding independent coverage or a different unresolved obligation.", + "Repeating the 208-flag static matching or calling a static nested cover a chronological correction program. Independent audit of that certificate is distinct and remains useful." + ], + "overlap_terms": [ + "P104", + "I-G/2", + "side correction", + "native channel", + "1972", + "1991", + "2586", + "endpoint transport", + "physical dual", + "relay composition", + "2981", + "joint unit flags", + "acquisition delivery", + "static nesting" + ], + "existing_checks": [ + { + "scope": "PR #2981 reports static joint endpoint flags and a matching of 208 departure and arrival flags; archival intake is not independent verification.", + "evidence": "research/p104-joint-unit-flags/README.md", + "remaining": "Independent flag check and a chronological coefficient program with dirty restoration and a complete cost.", + "status": "author-checked", + "source_commit": "3d24b92d8ba057b57cb2d480170ec407520e6882", + "selected_record_sha256": "bb2eaa58647b353f88d0aec2eafb9d30df1be53589231b23e12ceef3e4bad129" + } + ] + }, + "scope_status": "changed", + "actual_scope": "On the frozen PR #3979 encoder word vendored by PR #3996, the bank-0 column-0 fiber is exactly axis-0 multiplication by U = [[I, B/2], [0, I]], and it is not U inverse or either transpose.", + "scope_change_reason": "The card asks for a chronological side-correction program and a complete bill. Discussion #1166 comment 19035716 leaves a fiber comparison after the index-bridge audit in PR #4125. This package answers that comparison for one column. It does not build a correction word or price a consumer.", + "bottleneck_link": "Axis 0 of U is the row factor inside the encoder L = U_r U_c^{-t}. Confirming one fiber from the emitted events separates that factor from the algebraic bridge in PR #4125. A single fiber does not change the selected moment.", + "budget_minutes": 60, + "stop_rule": "Stop after one bank-0 column. Do not replay the other 415 encoder fibers, the decoder, or either Gram word, and do not start a physical consumer.", + "outcome": "partial", + "evidence": "PASS_P104_AXIS0_ENCODER_FIBER: the 576-event program occurs once at offset 41600 inside the 203008-event encoder, and its interpreted map equals U.", + "author": "unpaidmoon", + "ai_assistance": "Cursor Grok 4.7 drafted the verifier, the proof note, and the package text. No independent human review is claimed.", + "open_questions": [ + { + "question": "Do the other 103 bank-0 axis-0 fibers differ from column 0 only by the column index?", + "why_it_matters": "Uniform columns would extend this identity from one fiber to the whole U_r sweep on bank 0, still without a physical bill.", + "first_step": "Localize column 1's events and compare them with column 0 after substituting the column index.", + "blocked_by": "Nothing mathematical. It was left out so this package would stay the one-column comparison." + }, + { + "question": "Does one repeated consumer of (N-P) tensor M pay less than rebuilding the uncoded Gram pair?", + "why_it_matters": "PR #4125 shows each omitted identity side has rational rank 10816. Rank is not a native price, and this fiber does not implement that side.", + "first_step": "Price one consumer of the exhibited inverse of N-P on a single bank before any sweep search.", + "blocked_by": "No named consumer or complete allowance is in this package." + } + ] +} diff --git a/research/p104-axis0-encoder-fiber/VERIFY.json b/research/p104-axis0-encoder-fiber/VERIFY.json new file mode 100644 index 0000000000..e7bb81cdef --- /dev/null +++ b/research/p104-axis0-encoder-fiber/VERIFY.json @@ -0,0 +1,29 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/p104-native-channel/inputs/P104-FIXTURE.json" + ], + "commands": [ + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "One bank-0 column-0 encoder fiber matches U and misses the three other signed transposes." + }, + { + "argv": [ + "{python}", + "-B", + "{package}/test_verify.py" + ], + "timeout_seconds": 120, + "checks": "The matched slice is the searched program, column 1 is not that slice, and dropping the doubles leaves a half-scale tail." + } + ] +} diff --git a/research/p104-axis0-encoder-fiber/frozen/word_builder.py b/research/p104-axis0-encoder-fiber/frozen/word_builder.py new file mode 100644 index 0000000000..7b81946424 --- /dev/null +++ b/research/p104-axis0-encoder-fiber/frozen/word_builder.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +"""Exact dyadic tensor-code protocol and coefficient-ring audit; standard library, Apache-2.0.""" +import argparse +import hashlib +import itertools +import json +from pathlib import Path + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +PIVOTS = (0, 1, 3, 6, 22, 31, 93, 103) + + +def require(ok, message): + if not ok: + raise ValueError(message) + + +def read(path): + def pairs(items): + ans = {} + for key, value in items: + require(key not in ans, 'duplicate JSON key') + ans[key] = value + return ans + return json.loads(path.read_text(), object_pairs_hook=pairs) + + +def authenticate(): + for row in read(HERE / 'SOURCES.json')['files']: + if row['usage'] != 'input': + continue + path = ROOT / row['path'] + require(not path.is_symlink(), 'source symlink') + data = path.read_bytes() + require(hashlib.sha256(data).hexdigest() == row['sha256'], 'input hash: ' + row['path']) + require(hashlib.sha1(b'blob ' + str(len(data)).encode() + b'\0' + data).hexdigest() == row['git_blob'], 'input blob') + + +def source_matrix(): + roots = [] + for a, b in itertools.combinations(range(8), 2): + for sign in (-1, 1): + row = [0] * 8 + row[a], row[b] = 2, 2 * sign + roots.append(tuple(row)) + roots.extend((1,) + tail for tail in itertools.product((-1, 1), repeat=7) if tail.count(-1) % 2 == 0) + fixture = read(ROOT / 'research/p104-native-channel/inputs/P104-FIXTURE.json')['section4_explicit_P104'] + removed = {tuple(row) for row in fixture['F0'] + fixture['C']} + ports = sorted(set(roots) - removed) + require(len(ports) == 104, 'P104 port count') + order = list(PIVOTS) + [i for i in range(104) if i not in PIVOTS] + ports = [ports[i] for i in order] + gram = [[sum(x*y for x,y in zip(a,b)) for b in ports] for a in ports] + require(all(gram[i][j] == 8*(i == j) for i in range(8) for j in range(8)), 'pivot Gram') + b2 = [[gram[i][j] // 4 for j in range(8,104)] for i in range(8)] + require(all(v in (-1,0,1) for row in b2 for v in row), 'signed half coefficients') + require(all(sum(b2[i][k]*b2[j][k] for k in range(96)) == 48*(i == j) for i in range(8) for j in range(8)), 'BBt=12I') + require(all(sum(b2[k][i]*b2[k][j] for k in range(8)) == gram[i+8][j+8]//2 for i in range(96) for j in range(96)), 'nonpivot Gram') + return b2 + + + +def index(bank,i,j,n): return (bank*n+i)*n+j + + +def triangular(b,bank,axis,fixed,transpose=False,inverse=False): + p=len(b);n=p+len(b[0]) + def ix(k): return index(bank,k,fixed,n) if axis==0 else index(bank,fixed,k,n) + donors=range(p) if transpose else range(p,n) + for d in donors: yield ('half',ix(d)) + for j,row in enumerate(b): + for k,v in enumerate(row,p): + if v: + dest,src=(k,j) if transpose else (j,k) + yield ('add',ix(dest),ix(src),-v if inverse else v) + for d in donors: yield ('double',ix(d)) + + +def code_word(b,inverse=False): + n=len(b)+len(b[0]) + steps=[(0,1,True,True),(0,0,False,False),(1,1,False,False),(1,0,True,True)] + if inverse: steps=[(bank,axis,t,not inv) for bank,axis,t,inv in reversed(steps)] + for bank,axis,t,inv in steps: + for fixed in range(n):yield from triangular(b,bank,axis,fixed,t,inv) + + +def coded_pair(b): + p=len(b);n=p+len(b[0]) + # lower: Y += P_r M_c X. upper: X -= M_r P_c Y. + for source,axis in ((0,1),(1,0)): + target=1-source;sign=1 if source==0 else -1 + for fixed in range(p): + yield from triangular(b,source,axis,fixed,True) + yield from triangular(b,source,axis,fixed) + for k in range(n): + i,j=(fixed,k) if axis==1 else (k,fixed) + yield ('add',index(target,i,j,n),index(source,i,j,n),sign) + yield from triangular(b,source,axis,fixed,inverse=True) + yield from triangular(b,source,axis,fixed,True,True) + + +def reference_pair(b): + p=len(b);n=p+len(b[0]) + for source,axis in ((0,0),(1,1)): + target=1-source;sign=1 if source==0 else -1 + for fixed in range(n): + def ix(bank,k):return index(bank,k,fixed,n) if axis==0 else index(bank,fixed,k,n) + yield from triangular(b,source,axis,fixed) + for j in range(p):yield ('add',ix(target,j),ix(source,j),sign) + for j in range(p):yield ('half',ix(source,j)) + for j,row in enumerate(b): + for k,v in enumerate(row,p): + if v:yield ('add',ix(target,k),ix(source,j),sign*v) + for j in range(p):yield ('double',ix(source,j)) + yield from triangular(b,source,axis,fixed,inverse=True) + + +def evaluate(word,values): + x=list(values) + for op in word: + if op[0]=='add':x[op[1]]+=op[3]*x[op[2]] + elif op[0]=='half': + require(x[op[1]]%2==0,'exact dyadic integer test scale') + x[op[1]]//=2 + elif op[0]=='double':x[op[1]]*=2 + else:raise ValueError('unknown operation') + return x + + +def invoice(word): + from collections import Counter + c=Counter(op[0] for op in word) + return {key:c[key] for key in ('add','half','double')} + + +def mod_rank(a,p=13): + a=[[x%p for x in row] for row in a];r=0 + for j in range(len(a[0])): + pivot=next((i for i in range(r,len(a)) if a[i][j]),None) + if pivot is None:continue + a[r],a[pivot]=a[pivot],a[r];scale=pow(a[r][j],-1,p);a[r]=[(x*scale)%p for x in a[r]] + for i in range(len(a)): + if i!=r: + c=a[i][j];a[i]=[(v-c*w)%p for v,w in zip(a[i],a[r])] + r+=1 + if r==len(a):break + return r + + +def result(): + authenticate();b=source_matrix();n=104;p=8 + enc=list(code_word(b));dec=list(code_word(b,True));cp=list(coded_pair(b));rp=list(reference_pair(b)) + ei=invoice(enc+dec);ci=invoice(cp);ri=invoice(rp) + require(ei=={'add':319488,'half':43264,'double':43264},'boundary invoice') + require(ci=={'add':26240,'half':3328,'double':3328},'coded pair invoice') + require(ri=={'add':241280,'half':41600,'double':41600},'reference pair invoice') + # Dense arbitrary integer fixture, including untouched dirty-helper sentinels. + data=[((i*37+i//11)%31-15)*(1<<24) for i in range(2*n*n)]+[123,-77] + require(evaluate(dec,evaluate(enc,data))==data,'full payload inverse') + reference=evaluate(rp,evaluate(rp,data)) + coded=evaluate(dec,evaluate(cp,evaluate(cp,evaluate(enc,data)))) + require(coded==reference,'actual P104 two-pair scalar endpoint') + require(coded[-2:]==data[-2:],'arbitrary dirty helper preservation') + # A nonzero kernel payload is retained in syndrome coordinates. + syndrome=[0]*(2*n*n) + syndrome[index(0,8,0,n)]=2 + for i in range(p):syndrome[index(0,i,0,n)]=-b[i][0] + require(any(syndrome),'nonzero syndrome') + require(evaluate(dec,evaluate(enc,[v*(1<<16) for v in syndrome]))==[v*(1<<16) for v in syndrome],'kernel payload retained') + # Reconstruct A mod13 from V=[I B], not by division by its eigenvalue. + v=[[int(i==j) for j in range(p)]+[(x*7)%13 for x in b[i]] for i in range(p)] + a=[[sum(v[k][i]*v[k][j] for k in range(p))%13 for j in range(n)] for i in range(n)] + rank=mod_rank(a) + require(rank==8 and all(sum(a[i][k]*a[k][j] for k in range(n))%13==0 for i in range(n) for j in range(n)),'nonzero square-zero mod13 Gram') + require(mod_rank(b)==8,'B mod13 rank') + v5=[[int(i==j) for j in range(p)]+[(x*3)%5 for x in b[i]] for i in range(p)] + side5=[[(int(i==j)-sum(v5[k][i]*v5[k][j] for k in range(p)))%5 for j in range(n)] for i in range(n)] + require(mod_rank(side5,5)==104,'full-rank identity side correction') + # 13*(1/13)=1 cannot hold for dyadic coefficients; 13 reduces to zero. + require(13%13==0 and pow(2,-1,13)==7 and 5*5%13==12,'ring homomorphism') + return {'schema':'p104-tensor-code/1','data_degrees':2*n*n,'source_rank':8,'mod13_gram_rank':rank,'mod13_tensor_product_rank':rank*rank,'full_identity_side_rank':n*n, + 'code':'L=U_r U_c^-t; (Xhat,Yhat)=(L X,L^-t Y)', + 'transformed_lower':'P_r M_c','transformed_upper':'M_r P_c', + 'boundary_invoice':ei,'coded_pair_invoice':ci,'reference_pair_invoice':ri, + 'one_pair_add_difference':ei['add']+ci['add']-ri['add'], + 'two_pair_add_saving':2*ri['add']-ei['add']-2*ci['add'], + 'two_pair_half_saving':2*ri['half']-ei['half']-2*ci['half'], + 'first_add_break_even_integer':2,'first_half_break_even_integer':2, + 'arithmetic_scope':'exact common-chart Gaussian dyadic word; formal scalar counts, not physical/native upper bill', + 'remaining':'physical chart recipes, actual repeated consumer, identity-side correction, helpers/owners, full native moment and precision'} + + +def main(): + parser=argparse.ArgumentParser();parser.add_argument('--write-result',action='store_true');parser.add_argument('--result',type=Path,default=HERE/'RESULT.json');args=parser.parse_args() + r=result() + if args.write_result:args.result.write_text(json.dumps(r,indent=2,sort_keys=True)+'\n') + else:require(json.dumps(read(args.result),sort_keys=True)==json.dumps(r,sort_keys=True),'typed result mismatch') + print('PASS_P104_TENSOR_CODE payload=21632 mod13_rank=64 two_pair_add_saving=110592 no_new_kappa') + +if __name__=='__main__':main() diff --git a/research/p104-axis0-encoder-fiber/test_verify.py b/research/p104-axis0-encoder-fiber/test_verify.py new file mode 100644 index 0000000000..0fdd2f1233 --- /dev/null +++ b/research/p104-axis0-encoder-fiber/test_verify.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Failure controls for the one-fiber axis-0 comparison.""" +from __future__ import annotations + +import importlib.util +import json +from pathlib import Path + +HERE = Path(__file__).resolve().parent + + +def load(): + spec = importlib.util.spec_from_file_location("axis0_fiber", HERE / "verify.py") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def main(): + module = load() + report = module.receipt() + if report["map"] != "U" or report["match_count"] != 1 or report["checker_called"]: + raise SystemExit("FAIL: receipt") + b2 = module.rebuild_b2() + needle = module.axis0_u_program(b2, 0, 0) + word = module.load_encoder(b2) + start = report["match_offset"] + if word[start : start + len(needle)] != needle: + raise SystemExit("FAIL: slice drifted") + # A column-shifted copy is a different fiber and is not this slice. + shifted = module.axis0_u_program(b2, 0, 1) + if module.find_slice(word[start : start + len(needle)], shifted): + raise SystemExit("FAIL: column 1 program collided with column 0") + if module.find_slice(word, shifted) == [start]: + raise SystemExit("FAIL: column 1 occupied the column 0 offset") + # Dropping the restoring doubles leaves a half-scale tail. + truncated = needle[:-96] + realized = module.interpret_axis0(truncated, 0, 0) + tail = realized[8] + if tail.get(8) != module.Fraction(1, 2): + raise SystemExit("FAIL: truncated tail scale") + print("PASS_P104_AXIS0_ENCODER_FIBER_TESTS " + json.dumps({"groups": 3, "new_kappa": False})) + + +if __name__ == "__main__": + main() diff --git a/research/p104-axis0-encoder-fiber/verify.py b/research/p104-axis0-encoder-fiber/verify.py new file mode 100644 index 0000000000..3781ab0ff2 --- /dev/null +++ b/research/p104-axis0-encoder-fiber/verify.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +"""One frozen encoder fiber equals axis-0 multiplication by U. + +The fiber is a contiguous slice of the encoder word emitted by the frozen +PR #3979 builder bytes that PR #3996 vendors. This file does not import or +call the PR #3996 checker. +""" +from __future__ import annotations + +import hashlib +import importlib.util +import itertools +import json +from fractions import Fraction +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +HERE = Path(__file__).resolve().parent +FIXTURE = ROOT / "research/p104-native-channel/inputs/P104-FIXTURE.json" +BUILDER = HERE / "frozen/word_builder.py" +FIXTURE_SHA256 = "516c06f6ec3cb84be588c546108de897650288576dd5fbf5fe44b9c5546ad8a4" +BUILDER_SHA256 = "27bae82fe247fe49b8fc3b5efbd429e2c8c0ee8f56cc4ace748cbb681a5abacc" +B2_SHA256 = "88e9a726e8c8aec055bfd7cd024883b5c8ecbda0cd6471e591a08c43a108a535" +N = 104 +PIVOTS = (0, 1, 3, 6, 22, 31, 93, 103) +BANK = 0 +COLUMN = 0 + + +def require(condition, message): + if not condition: + raise SystemExit("FAIL: " + message) + + +def load_json(path): + def pairs(items): + found = {} + for key, value in items: + require(key not in found, "duplicate JSON key in " + str(path)) + found[key] = value + return found + + return json.loads(path.read_text(encoding="utf-8"), object_pairs_hook=pairs) + + +def sha256(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def rebuild_b2(): + """Integer numerator of B, independent of the word builder.""" + roots = [] + for left, right in itertools.combinations(range(8), 2): + for sign in (-1, 1): + row = [0] * 8 + row[left], row[right] = 2, 2 * sign + roots.append(tuple(row)) + roots.extend( + (1,) + tail + for tail in itertools.product((-1, 1), repeat=7) + if tail.count(-1) % 2 == 0 + ) + fixture = load_json(FIXTURE)["section4_explicit_P104"] + removed = {tuple(row) for row in fixture["F0"] + fixture["C"]} + ports = sorted(set(roots) - removed) + require(len(ports) == N, "P104 port count") + order = list(PIVOTS) + [index for index in range(N) if index not in PIVOTS] + ports = [ports[index] for index in order] + gram = [[sum(x * y for x, y in zip(left, right)) for right in ports] for left in ports] + b2 = [[gram[row][column] // 4 for column in range(8, N)] for row in range(8)] + require(all(entry in (-1, 0, 1) for row in b2 for entry in row), "B numerators") + digest = hashlib.sha256( + json.dumps(b2, separators=(",", ":")).encode("ascii") + ).hexdigest() + require(digest == B2_SHA256, "B2 digest") + require(sum(entry != 0 for row in b2 for entry in row) == 384, "B support") + return b2 + + +def axis0_u_program(b2, bank, column): + """Half, add B, double: the axis-0 program for U = [[I, B/2], [0, I]].""" + pivot_count = len(b2) + width = pivot_count + len(b2[0]) + + def at(row): + return (bank * width + row) * width + column + + program = [("half", at(row)) for row in range(pivot_count, width)] + for pivot, row in enumerate(b2): + for offset, value in enumerate(row): + if value: + program.append(("add", at(pivot), at(pivot_count + offset), value)) + program.extend(("double", at(row)) for row in range(pivot_count, width)) + return program + + +def load_encoder(b2): + require(sha256(BUILDER) == BUILDER_SHA256, "frozen builder bytes") + spec = importlib.util.spec_from_file_location("frozen_word_builder", BUILDER) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + require(callable(getattr(module, "code_word", None)), "builder exports code_word") + # code_word emits events. Do not call result(), evaluate(), or any checker. + return list(module.code_word(b2)) + + +def find_slice(word, needle): + width = len(needle) + hits = [] + first = needle[0] + limit = len(word) - width + 1 + for start in range(limit): + if word[start] != first: + continue + if word[start : start + width] == needle: + hits.append(start) + return hits + + +def decode(index): + owner, offset = divmod(index, N * N) + row, column = divmod(offset, N) + return owner, row, column + + +def interpret_axis0(program, bank, column): + rows = [{row: Fraction(1)} for row in range(N)] + for operation in program: + kind = operation[0] + require(kind in ("add", "half", "double"), "operation alphabet") + owner, row, fixed = decode(operation[1]) + require((owner, fixed) == (bank, column), "fiber leaves the column") + if kind == "add": + require(len(operation) == 4 and operation[3] in (-1, 1), "unit add") + source_owner, source_row, source_column = decode(operation[2]) + require((source_owner, source_column) == (bank, column), "add source leaves the column") + updated = dict(rows[row]) + for coordinate, value in rows[source_row].items(): + total = updated.get(coordinate, Fraction(0)) + operation[3] * value + if total: + updated[coordinate] = total + else: + updated.pop(coordinate, None) + rows[row] = updated + else: + factor = Fraction(1, 2) if kind == "half" else Fraction(2) + rows[row] = {coordinate: factor * value for coordinate, value in rows[row].items()} + return rows + + +def matrix_u(b2, inverse=False): + rows = [{row: Fraction(1)} for row in range(N)] + sign = -1 if inverse else 1 + for pivot, row in enumerate(b2): + for offset, value in enumerate(row): + if value: + rows[pivot][8 + offset] = Fraction(sign * value, 2) + return rows + + +def matrix_u_transpose(b2, inverse=False): + rows = [{row: Fraction(1)} for row in range(N)] + sign = -1 if inverse else 1 + for pivot, row in enumerate(b2): + for offset, value in enumerate(row): + if value: + rows[8 + offset][pivot] = Fraction(sign * value, 2) + return rows + + +def receipt(): + require(sha256(FIXTURE) == FIXTURE_SHA256, "fixture bytes") + b2 = rebuild_b2() + needle = axis0_u_program(b2, BANK, COLUMN) + word = load_encoder(b2) + hits = find_slice(word, needle) + require(hits == [41600], "encoder contains the bank-0 column-0 axis-0 U fiber once, after the first sweep") + realized = interpret_axis0(word[hits[0] : hits[0] + len(needle)], BANK, COLUMN) + require(realized == matrix_u(b2), "fiber map is U") + require(realized != matrix_u(b2, inverse=True), "fiber is not U inverse") + require(realized != matrix_u_transpose(b2), "fiber is not U transpose") + require(realized != matrix_u_transpose(b2, inverse=True), "fiber is not U inverse transpose") + broken = list(needle) + for index, operation in enumerate(broken): + if operation[0] == "add": + broken[index] = (operation[0], operation[1], operation[2], -operation[3]) + break + require(interpret_axis0(broken, BANK, COLUMN) != matrix_u(b2), "sign flip must miss U") + fiber_digest = hashlib.sha256( + json.dumps(needle, separators=(",", ":")).encode("ascii") + ).hexdigest() + return { + "bank": BANK, + "column": COLUMN, + "fiber_digest_sha256": fiber_digest, + "fiber_events": len(needle), + "match_offset": hits[0], + "match_count": len(hits), + "encoder_events": len(word), + "map": "U", + "axis": 0, + "checker_called": False, + "new_kappa": False, + } + + +def main(): + print("PASS_P104_AXIS0_ENCODER_FIBER " + json.dumps(receipt(), sort_keys=True)) + + +if __name__ == "__main__": + main()