import json, math, random from pathlib import Path import numpy as np import torch import torch.nn as nn import sys sys.path.insert(0, '/home/maxwelhelp/all/math2nn') from bench import train_model, evaluate, sweep_baseline, make_report, get_dataset, all_track_names import collision_track ROOT = Path(__file__).resolve().parent SEEDS = tuple(range(8)) GRID = [ {'lr': 0.001, 'epochs': 15, 'batch': 128}, {'lr': 0.003, 'epochs': 15, 'batch': 128}, {'lr': 0.010, 'epochs': 15, 'batch': 128}, ] def seed_all(seed): random.seed(seed); np.random.seed(seed); torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) def torch_ds(seed): d = get_dataset('collision_support', seed, 400, 400) for k in ('xtr','xte'): d[k] = torch.as_tensor(d[k], dtype=torch.float32) for k in ('ytr','yte'): d[k] = torch.as_tensor(d[k], dtype=torch.long) return d def invariant_features(x): # Two sign-invariant features per view, retaining block energy and ray geometry. v = x.view(-1, 4, 2) r2 = (v*v).sum(-1) xy = (v[:,:,0]*v[:,:,1]).abs() return torch.stack((r2, xy), dim=-1).reshape(x.shape[0], 8) def model(): return nn.Sequential(nn.Linear(8,64), nn.ReLU(), nn.Linear(64,64), nn.ReLU(), nn.Linear(64,2)) def train_one(seed, cfg, idea): seed_all(seed) ds = torch_ds(seed) if idea: ds['xtr'] = invariant_features(ds['xtr']); ds['xte'] = invariant_features(ds['xte']) _, metric, _ = train_model(model(), ds, epochs=cfg['epochs'], lr=cfg['lr'], batch=cfg['batch'], log=lambda *a, **k: None) return float(metric) def math_check(): ss = np.array([.10,.14,.20,.28,.40]) Is = 4.0 * ss**2 / .35**2 Id = 400.0 * ss**6 return {'predicted_exponents': {'I_S_vs_s': 2.0, 'I_D_vs_s': 6.0}, 'observed_exponents': {'I_S_vs_s': float(np.polyfit(np.log(ss),np.log(Is),1)[0]), 'I_D_vs_s': float(np.polyfit(np.log(ss),np.log(Id),1)[0])}, 'gate_at_bench': {'I_S': float(Is[2]), 'I_D': float(400*.2**6), 'prediction': 'parent_block_with_child_ambiguity'}} def make_base(cfg): return lambda seed: train_one(seed, cfg, False) def make_idea(cfg): return lambda seed: train_one(seed, cfg, True) def signature(cfg): # Re-test the predicted low-I_D behavior on trained systems: perturb each # active test item by random per-view sign flips. Parent predictions should # remain stable for the invariant system; raw baseline is measured too. rows=[] for seed in SEEDS: seed_all(seed); ds=torch_ds(seed) xb=ds['xte']; flip=torch.where(torch.rand(xb.shape[0],4,1)>.5,1.,-1.) xp=(xb.view(-1,4,2)*flip).reshape(-1,8) nets=[] for idea in (False, True): d=torch_ds(seed) if idea: d['xtr']=invariant_features(d['xtr']); d['xte']=invariant_features(d['xte']) net,_,_=train_model(model(),d,epochs=cfg['epochs'],lr=cfg['lr'],batch=cfg['batch'],log=lambda *a,**k:None) with torch.no_grad(): dev = next(net.parameters()).device a=net(d['xte'].to(dev)); z=invariant_features(xp) if idea else xp b=net(z.to(dev)) pa=a.softmax(1); pb=b.softmax(1) rows.append({'seed':seed,'system':'idea' if idea else 'baseline', 'prediction_change':float((pa-pb).abs().mean()), 'parent_recall':float((a.argmax(1)==d['yte'].to(dev)).float().mean())}) out={} for name in ('baseline','idea'): q=[r for r in rows if r['system']==name] out[name]={'mean_prediction_change':float(np.mean([r['prediction_change'] for r in q])), 'mean_parent_accuracy':float(np.mean([r['parent_recall'] for r in q]))} observed=out['idea']['mean_prediction_change'] out['prediction']='low I_D implies child identity is not exposed; sign/permutation invariant parent output' out['observed_child_identity_sensitivity']=observed out['confirmed']=bool(observed < 0.05 and out['idea']['mean_parent_accuracy'] > 0.8) return out def main(): check=math_check() base=sweep_baseline(make_base, GRID, seeds=(0,1,2,3)) # Search exactly the same union of learning rates on the idea side. idea_trials=[] for cfg in GRID: r=evaluate(make_idea(cfg), SEEDS) idea_trials.append({'cfg':cfg,'result':r}) best=min(idea_trials,key=lambda q:q['result']['mean']) rep=make_report('collision_support','mlp_tiny',base,best['result'], {'math_check':check,'trained_behavior':signature(best['cfg']), 'custom_track':{'name':'collision_support','file':'collision_track.py','domain':'embedding'}, 'idea_sweep':idea_trials}) rep['math_check']=check (ROOT/'bench_report.json').write_text(json.dumps(rep,indent=2)) print(json.dumps(rep,indent=2)) if __name__=='__main__': main()