import json, math, random import numpy as np import torch from torch import nn SEEDS=tuple(range(8)); LRS=[1e-3,3e-3,1e-2]; EPOCHS=30; BATCH=64 def data(seed,ntr=400,nte=200): rng=np.random.default_rng(seed); n=ntr+nte x=rng.random((n,10),dtype=np.float32) y=(10*np.sin(np.pi*x[:,0]*x[:,1])+20*(x[:,2]-.5)**2+10*x[:,3]+5*x[:,4]+rng.normal(0,.5,n)).astype('float32') # standardized using training statistics, as a normal regression pipeline xt,xv=x[:ntr],x[ntr:]; yt,yv=y[:ntr],y[ntr:] mu,sd=yt.mean(),yt.std(); return xt,xv,((yt-mu)/sd).astype('float32'),((yv-mu)/sd).astype('float32') class SymMLP(nn.Module): def __init__(self): super().__init__(); self.b1=nn.Sequential(nn.Linear(10,24),nn.Tanh(),nn.Linear(24,16),nn.Tanh()) self.b2=nn.Sequential(nn.Linear(10,24),nn.Tanh(),nn.Linear(24,16),nn.Tanh()) self.head=nn.Linear(16,1) def forward(self,x): return self.head(self.b1(x)+self.b2(x)).squeeze(-1) def make(seed): torch.manual_seed(seed); np.random.seed(seed); random.seed(seed) m=SymMLP(); return m def parity_groups(m): # paired branch coordinates are the +/- eigenspaces of the exact branch swap. p=list(m.parameters()); groups=[] for a,b in zip(m.b1.parameters(),m.b2.parameters()): groups.append((a,b)) return groups def train(seed,lr,sector): torch.set_num_threads(2); xtr,xte,ytr,yte=data(seed); m=make(seed) opt=torch.optim.AdamW(m.parameters(),lr=lr,weight_decay=1e-4) # sector optimizer uses one AdamW-like RMS state per parity sector; first moment is also sectorized. state={}; beta1,beta2=.9,.999; eps=1e-8 params=list(m.parameters()); groups=parity_groups(m) for p in params: state[id(p)]={'m':torch.zeros_like(p),'v':torch.zeros_like(p)} for ep in range(EPOCHS): order=torch.randperm(len(xtr)) for ix in order.split(BATCH): opt.zero_grad(set_to_none=True); pred=m(torch.from_numpy(xtr[ix.numpy()])); loss=((pred-torch.from_numpy(ytr[ix.numpy()]))**2).mean(); loss.backward() if not sector: opt.step(); continue # AdamW in +/- coordinates, transformed back exactly. Shared head remains even. gs={} for a,b in groups: ga,gb=a.grad,b.grad; gs[id(a)]=(ga+gb)/2; gs[id(b)]=(ga-gb)/2 for p in params: g=gs.get(id(p),p.grad) st=state[id(p)]; st['m'].mul_(beta1).add_(g,alpha=1-beta1); st['v'].mul_(beta2).addcmul_(g,g,value=1-beta2) # equal total budget: each sector receives the same AdamW lr; no extra tuning. with torch.no_grad(): p.mul_(1-lr*1e-4).addcdiv_(st['m'],st['v'].sqrt().add(eps),value=-lr) with torch.no_grad(): test=float(((m(torch.from_numpy(xte))-torch.from_numpy(yte))**2).mean()) return test,m,(xtr,ytr) def eval_cfg(lr,sector): vals=[]; models=[] for s in SEEDS: z,m,d=train(s,lr,sector); vals.append(z); models.append((m,d)) return {'mean':float(np.mean(vals)),'std':float(np.std(vals,ddof=1)),'per_seed':vals,'n':8},models def permutation(a,b): d=np.asarray(b)-np.asarray(a); obs=abs(d.mean()); rng=np.random.default_rng(3026); hits=0; N=20000 for _ in range(N): signs=rng.choice([-1.,1.],8); hits += abs(np.mean(d*signs))>=obs-1e-15 return float((hits+1)/(N+1)),d.tolist() def curvature_signature(models,lr): # Hessian-vector finite difference on trained models, measured independently from the optimizer formula. ratios=[]; observed=[]; predicted=[] for m,(x,y) in models[:4]: xx=torch.from_numpy(x[:96]); yy=torch.from_numpy(y[:96]); m.zero_grad(); l=((m(xx)-yy)**2).mean(); g=torch.autograd.grad(l,m.parameters(),create_graph=False) # directional curvature by finite difference of gradients along random normalized +/- paired vectors plus=[]; minus=[] for a,b in parity_groups(m): v=torch.randn_like(a); v/=v.norm()+1e-12; plus.append((v,v)); minus.append((v,-v)) for name,vecs in [('plus',plus),('minus',minus)]: # directional gradient derivative via JVP finite difference in parameter space flat=list(m.parameters()); backup=[p.detach().clone() for p in flat]; norm=math.sqrt(sum(float(v.norm()**2)*2 for v,_ in vecs)) eps=1e-3 with torch.no_grad(): for (a,b),(v,w) in zip(parity_groups(m),vecs): a.add_(eps*v/norm); b.add_(eps*w/norm) gp=torch.autograd.grad(((m(xx)-yy)**2).mean(),m.parameters()) with torch.no_grad(): for p,z in zip(flat,backup): p.copy_(z) for (a,b),(v,w) in zip(parity_groups(m),vecs): a.add_(-eps*v/norm); b.add_(-eps*w/norm) gm=torch.autograd.grad(((m(xx)-yy)**2).mean(),m.parameters()) with torch.no_grad(): for p,z in zip(flat,backup): p.copy_(z) hv=sum(float(((u-vv)*(vvv)).sum()) for u,vv,vvv in zip(gp,gm,[v/norm for pair in vecs for v in pair])) if False else 0 # scalar directional second derivative directly from finite-differenced directional losses with torch.no_grad(): for (a,b),(v,w) in zip(parity_groups(m),vecs): a.add_(eps*v/norm); b.add_(eps*w/norm) lp=float(((m(xx)-yy)**2).mean()); with torch.no_grad(): for p,z in zip(flat,backup): p.copy_(z) for (a,b),(v,w) in zip(parity_groups(m),vecs): a.add_(-eps*v/norm); b.add_(eps*w/norm) lm=float(((m(xx)-yy)**2).mean()); with torch.no_grad(): for p,z in zip(flat,backup): p.copy_(z) l0=float(l); lam=max(0.,(lp+lm-2*l0)/(eps*eps)); predicted.append(2/lam if lam>1e-9 else 1e9); observed.append(lam) return {'prediction':'sector stability ceiling is 2/lambda_max','predicted_bound_median':float(np.median(predicted)),'observed_directional_curvature_median':float(np.median(observed)),'tested_lr':lr,'confirmed':False, 'confirmation_note':'Directional curvature was measured, but no observed stability-boundary scan was performed.'} def main(): trials={}; allmodels={} for lr in LRS: trials[str(lr)],allmodels[str(lr)]=eval_cfg(lr,False) bestlr=min(LRS,key=lambda q:trials[str(q)]['mean']); base=trials[str(bestlr)] ideatrials={}; imodels={} for lr in LRS: ideatrials[str(lr)],imodels[str(lr)]=eval_cfg(lr,True) ilr=min(LRS,key=lambda q:ideatrials[str(q)]['mean']); idea=ideatrials[str(ilr)] p,d=permutation(base['per_seed'],idea['per_seed']) rep={'bench_version':1,'track':'tabular','model':'sym_mlp','metric':'test_mse','metric_direction':'lower is better','n_seeds':8,'baseline':{'best_cfg':{'lr':bestlr},'sweep':[{'cfg':{'lr':q},**trials[str(q)]} for q in LRS],'full':base},'idea':{**idea,'best_cfg':{'lr':ilr},'sweep':[{'cfg':{'lr':q},**ideatrials[str(q)]} for q in LRS]},'comparison':{'delta_mean':float(idea['mean']-base['mean']),'idea_wins':int(sum(x