Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions research/bank-gauge-boundary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# What entrance gauges and completed banks can absorb (no new κ)

A scoping note for the paired-cube words of #168 v4, #200 and #207–#213. **No κ is claimed, and no certificate changes.**

#208 prices "bank-absorption rungs" (for example, absorbing the bit word's rank-22 family for +2.52%) and leaves open which families a bank may absorb. This note says where the published mechanism stops. The absorbable families are already absorbed on the current words. The priced rungs need a lemma outside this mechanism.

## 1. What the published bank removes

By `notes/paired-cube-sharing.tex`, a role entering with gauge T_σ has the exact operator U = F_A T_σ⁻¹. Its forward correction F_A U⁻¹ = F_A T_σ F_A⁻¹ has Fourier rank dim σ, and its three stage blocks tensor into **one** child of width 3·dim σ: the exterior. #186 and #207 replace exactly this correction with the S_P bank endpoint, and say so: "Exactly the 2200 rank60 gauge exteriors are removed. Every internal chain increment, source and target connector, centre copy, original data endpoint … remains."

`notes/paired-cube-bit.tex` gives the converse. A role corrected at the zero frame has no exterior, and pays its first transition as an ordinary internal child.

So, under this mechanism, **the bankable children are exactly the gauge exteriors.** On #207's word the surviving genuine entrance gauges number 2,200, and all of them are banked. The 1,760 rank-21 recipient gauges are internal splices (#186).

## 2. When a register may carry an entrance gauge

The correction F_A T_σ F_A⁻¹ fixes the frame because the role's scalar contract **restores its own entrance value**. Its raw entrance z is read as T_σ ẑ, and it exits as F_A ẑ, a function of ẑ alone. Two other register classes fail this test.

- **Targets** accumulate. A target entering at gauge τ would end as T·T_τ⁻¹·y_old + T·f(x).
- One end correction cannot apply T_τ to the old part while leaving the new part alone.
- A start correction applied jointly on all three stage blocks breaks the gates. In stage j, a target is added to registers whose inactive blocks were not transformed the same way, so the inactive offsets no longer cancel.
- **Sources** are restored, but their values are *consumed*. Read as T_τ x̂, the injections would deliver x̂ ≠ x.

An entrance gauge, and with it a bank, therefore needs content that is **both don't-care and restored**, i.e. auxiliary dirt. This is a property of the gauge/bank mechanism, not an impossibility proof for other constructions.

## 3. Consequences for #208's rungs

#208's own allocation classifies the rank-22 family (and every later rung's) as "internal / target / center / compensating / terminal-substitution dirt". Its verdict is "not buildable with the construction as published". Sections 1–2 give the reason. None of those children is an entrance-gauge exterior, and the target, source and internal ones fail the gauge test of section 2. A rung needs a mechanism other than gauge reinterpretation.

## 4. Two measured near-misses

These are float discovery scores on our #173 bit word (p = 12, R = 22,120). They show the boundary is binding in practice, not only in principle.

- **Re-selecting auxiliary gauges once exteriors are free (banks).**
- There are 3,552 ungauged, non-source auxiliary roles outside phase one that have targets. Their feasible σ lies in the first-operation frame ∩ each target's first event frame. No role has an empty adjoint.
- Ignoring target cost, the upper bound is +4.17%.
- A gauge read at σ inserts an event into each of the role's 4–9 targets, splitting their first increments. The best nested selection loses 1.46%.
- A greedy pass that accepts a role only when the exact float saving rises accepts **zero** roles.
- **Target entrance gauges** (section 2) would price at +3.9%, or +4.5% merged with the final rank-two complement child. They are invalid for the reason given in section 2.

The pricing scripts are short and read the #173 package (`research/paired-cube-bit-rl-module`). They are in `regauge.py` here and need numpy.

## Scope

All interfaces of the cited words remain as stated by their authors. Sections 1 and 2 restate and apply the published sharing and bank arguments; they do not prove optimality of any construction. Credit goes to an664 (#128 completed-core sharing), icekylinx (paired cubes, general Clifford frames), the #186/#207 bank authors (Dugongue and others), chafreaky (#200 word), and maxime-fleury (#208 pricing).

Prepared by Joel Pulikkan (GamingPuzzled) with Anthropic Claude assistance; Apache-2.0.
140 changes: 140 additions & 0 deletions research/bank-gauge-boundary/regauge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/env python3
"""Float discovery pricing for README section 4 (auxiliary re-gauging under banks; target entrance gauges).

Copyright 2026 Joel Pulikkan (GamingPuzzled). Apache-2.0. Prepared with Anthropic Claude assistance.
Reads the PR173 package research/paired-cube-bit-rl-module (set PR173 to its path). Discovery only; no certificate.
"""
import os
import sys,math
from collections import Counter,defaultdict
sys.path.insert(0,os.environ.get('PR173','research/paired-cube-bit-rl-module'))
from word import Candidate
c=Candidate([]);C=c.C;C.decoder();C.geometry();M=c.module;h=c.h;w,g=c.w,c.g
rf=w['root_frame']
# target events in time order: gauge reads (by readtime), side roots, deliveries
ev=defaultdict(list)
for b in sorted(c.order,key=lambda b:c.readtime[b]):
for t in c.gauge[b]['targets']: ev[t].append(c.gauge[b]['frame'])
dl=defaultdict(list)
for e in C.k['entries']: dl[e['deliver_after_root']].append(e)
for j,r in enumerate(g['roots']):
if r['kind']=='center': continue
for t in r['targets']: ev[t].append(rf[j])
for e in dl.get(j,[]):
for t in e['receivers']: ev[t].append(e['deliver_frame'])
adj=c.adjoint()
first_op={}
for i,(a,b,x) in enumerate(c.ops):
for s in (a,b): first_op.setdefault(s,i)
src=set(c.source.values());p1=set()
for i in c.phase1: p1.update(c.ops[i][:2])
cand=[s for s in range(c.R) if s not in c.gauge and s not in src and s not in p1 and s in first_op and adj[s]]
cache={}
def inter(fs):
k=tuple(sorted(set(fs)))
if k not in cache:
A=[r for f in k for r in C.A[f]];B,_=M.kernel(A,h);cache[k]=len(B)
return cache[k]
dims=Counter();firstd=Counter();gain_rank=0
for s in cand:
F=c.opframe[first_op[s]]
fs=[F]+[ev[t][0] for t in adj[s] if ev[t]]
f=inter(fs);dims[f]+=1;firstd[C.dimf[F]]+=1
print('ungauged non-source roles with targets',len(cand),'of R',c.R,'| existing gauges',len(c.gauge))
print('first-op dims',sorted(firstd.items()))
print('feasible sigma dims (read before all target events)',sorted(dims.items()))
print('targets per role',Counter(min(len(adj[s]),9) for s in cand).most_common(6))
empty=[s for s in range(c.R) if s not in c.gauge and s not in src and s in first_op and not adj[s]]
print('ungauged roles with EMPTY adjoint',len(empty),'in phase1',sum(s in p1 for s in empty),'root roles',sum(s in c.rootroles for s in empty))
print('their first-op dims',sorted(Counter(C.dimf[c.opframe[first_op[s]]] for s in empty).items()))
print('sources',len(src),'gauges',len(c.gauge),'phase1 roles',len(p1),'roots',len(c.rootroles))
import math
row=c.row();H={int(k):n for k,n in row['child_histogram'].items()};W=row['W_per_vertex'];m=72
def sav(H,W):
g=lambda a:math.fsum(n*r*math.exp(a*math.log(m/r)) for r,n in H.items() if n)-W*m
lo,hi=0.,2e-2
for _ in range(80):
mid=(lo+hi)/2;lo,hi=(mid,hi) if g(mid)<0 else (lo,mid)
return lo
# 1) bank existing gauges: remove 5720 exterior children of width 60, W -= 5720*60/72
Hb=dict(H);Hb[60]-=5720;Wb=W-5720*60/72;ab=sav(Hb,Wb);print('banked existing gauges: %.6e (vs unbanked %.6e)'%(ab,sav(H,W)))
# 2) regauge candidates at sigma f: first transition r->r-f (3 copies), exterior 3f banked (free): mass -3f, W -3f/72
Hr=dict(Hb);Wr=Wb
for s in cand:
F=c.opframe[first_op[s]];r=C.dimf[F];f=inter([F]+[ev[t][0] for t in adj[s] if ev[t]])
if f<=0: continue
# previous increment into first op frame from start (0) is r
Hr[r]-=3
if r-f: Hr[r-f]=Hr.get(r-f,0)+3
Wr-=3*f/72
assert all(n>=0 for n in Hr.values())
print('regauge upper bound (no target-split cost): %.6e gain %+.3f%%'%(sav(Hr,Wr),100*(sav(Hr,Wr)/ab-1)))
# exact-ish: frames per role sigma (actual subspace), nested chains on targets
def interF(fs):
A=[r for f in set(fs) for r in C.A[f]];B,_=M.kernel(A,h)
return c.register(B) if B else None
info=[]
for s in cand:
F=c.opframe[first_op[s]];r=C.dimf[F]
sg=interF([F]+[ev[t][0] for t in adj[s] if ev[t]])
if sg is None: continue
f=C.dimf[sg];info.append((f,s,sg,r))
info.sort(key=lambda z:-z[0])
chains=defaultdict(list) # target -> accepted sigma frames
acc=[]
for f,s,sg,r in info:
ok=all(all(C.sub(sg,o) or C.sub(o,sg) for o in chains[t]) for t in adj[s])
if ok:
acc.append((f,s,sg,r))
for t in adj[s]: chains[t].append(sg)
print('accepted',len(acc),'of',len(info))
# rebuild: role side
Hx=dict(Hb);Wx=Wb
for f,s,sg,r in acc:
Hx[r]-=3
if r-f: Hx[r-f]=Hx.get(r-f,0)+3
Wx-=3*f/72
# target side: first increment d1 of each touched target split along its distinct sigma dims
for t,fs in chains.items():
d1=C.dimf[ev[t][0]];ds=sorted(set(C.dimf[x] for x in fs))
Hx[d1]-=3;prev=0
for d in ds+[d1]:
if d>prev: Hx[d-prev]=Hx.get(d-prev,0)+3
prev=d
assert all(n>=0 for n in Hx.values())
ax=sav(Hx,Wx);print('regauge with nested target splits: %.6e gain %+.3f%% over banked'%(ax,100*(ax/ab-1)))
# marginal greedy: accept only if exact saving improves
def tsplit(d1,ds):
out=Counter();prev=0
for d in sorted(set(ds))+[d1]:
if d>prev: out[d-prev]+=3
prev=d
return out
Hg=Counter(Hb);Wg=Wb;cur=ab;chains2=defaultdict(list);n=0
for f,s,sg,r in info:
if not all(all(C.sub(sg,o) or C.sub(o,sg) for o in chains2[t]) for t in adj[s]): continue
H2=Counter(Hg);H2[r]-=3
if r-f: H2[r-f]+=3
for t in adj[s]:
d1=C.dimf[ev[t][0]];old=[C.dimf[x] for x in chains2[t]]
if old: H2.subtract(tsplit(d1,old))
else: H2[d1]-=3
H2.update(tsplit(d1,old+[f]))
W2=Wg-3*f/72;a2=sav(+H2,W2)
if a2>cur:
Hg,Wg,cur=+H2,W2,a2;n+=1
for t in adj[s]: chains2[t].append(sg)
print('marginal greedy accepted',n,'saving %.6e gain %+.3f%% over banked'%(cur,100*(cur/ab-1)))
# target entrance gauges: tau_t = first event frame E_t; first increment d1 (3 copies) -> one fused child 3*d1
v=c.v;Ht=Counter(Hb);n=0;d1s=Counter()
for t in range(v):
if not ev[t]: continue
d1=C.dimf[ev[t][0]];Ht[d1]-=3;Ht[3*d1]+=1;n+=1;d1s[d1]+=1
print('targets',n,'first-event dims',sorted(d1s.items()))
at=sav(+Ht,Wb);print('target gauges, fused correction child (unbanked): %+.3f%%'%(100*(at/ab-1)))
# variant: correction merged into the existing rank-2 final complement child of each data bank target
Hm=Counter(Ht)
for t in range(v):
if not ev[t]: continue
d1=C.dimf[ev[t][0]];Hm[3*d1]-=1;Hm[2]-=1;Hm[3*d1+2]+=1
am=sav(+Hm,Wb);print(' ... merged with final rank-2 complement: %+.3f%%'%(100*(am/ab-1)))