import sys, json, math, random from pathlib import Path import numpy as np import torch sys.path.insert(0, '/home/maxwelhelp/all/math2nn') from bench import get_dataset, make_model, train_model, evaluate, sweep_baseline, make_report SEED=2092 EPOCHS=12 NTRAIN=400 NTEST=400 H=5 # Search-space parity: every idea lr is also in the baseline grid. LRS=[1e-3,3e-3,6e-3] STEPS=[1,3,5] COSTS=[0.0005,0.0015,0.0030] def seed_all(s): random.seed(s); np.random.seed(s); torch.manual_seed(s) if torch.cuda.is_available(): torch.cuda.manual_seed_all(s) def math_check(): # Exact finite-horizon Bellman recursion on a stochastic score chain. scores=np.linspace(0,1,21); H0=5; cs=[0,.02,.035,.04,.05] out=[] for c in cs: V=np.zeros((H0+1,len(scores))); V[0]=scores pol=[]; residual=[] for left in range(1,H0+1): p=.1+.75*(1-scores) ev=(1-p)*V[left-1]+p*V[left-1][np.minimum(np.arange(len(scores))+1,len(scores)-1)] q=-c+ev; V[left]=np.maximum(scores,q); pol.append(q>scores) residual.append(np.max(np.abs(V[left]-np.maximum(scores,q)))) out.append((V[H0,0], [bool(x) for x in pol[-1]], max(residual))) thresholds=[] for _,p,_ in out: z=np.flatnonzero(~np.asarray(p)); thresholds.append(int(z[0]) if len(z) else 21) return {'max_bellman_residual':float(max(x[2] for x in out)), 'value_nonincreasing_with_cost':bool(all(out[i][0]>=out[i+1][0]-1e-12 for i in range(len(out)-1))), 'stop_boundary_nonincreasing_with_cost':bool(all(thresholds[i]>=thresholds[i+1] for i in range(len(thresholds)-1))), 'costs':cs,'initial_values':[float(x[0]) for x in out],'threshold_indices':thresholds} def refined_predictions(net, ds, cost, fixed=None, collect=False): dev=next(net.parameters()).device x=ds['xte'].to(dev); y=ds['yte'].to(dev) net.eval() # A verifier score from observable self-consistency: stable successive candidates score high. with torch.no_grad(): p=net(x) calls=torch.zeros(len(x),device=dev) deltas=[]; observed_gains=[] for k in range(H): # Candidate refinement feeds the current candidate into the final observed theta. xx=x.clone(); xx[:, -3]=p[:,0] nxt=net(xx) d=(nxt[:,0]-p[:,0]).abs() # score in [0,1], with scale matched to normalized dynamics outputs score=1.0/(1.0+d/0.05) # one-step Bellman proxy: predicted score gain from another refinement xx2=xx.clone(); xx2[:, -3]=nxt[:,0] nxt2=net(xx2) d2=(nxt2[:,0]-nxt[:,0]).abs() next_score=1.0/(1.0+d2/0.05) # terminal payoff is verifier score; finite-horizon deterministic approximation # (the score is the observable state and cost is measured in normalized MSE units). continue_dec=(next_score-score)>cost if fixed is not None: continue_dec=torch.full_like(continue_dec, k+10).float().mean().item())}) return mse, result def train_eval(cfg, seed, idea=False, collect=False): seed_all(seed) d=get_dataset('dynamics', seed, n_train=NTRAIN, n_test=NTEST) net=make_model('rnn_small',d['input_shape'],d['out_dim']) net,metric,_=train_model(net,d,epochs=EPOCHS,lr=cfg['lr'],batch=128,log=lambda *_:None) if net is None: return float('nan') if not idea: mse,_=refined_predictions(net,d,cost=0.0,fixed=cfg['steps'],collect=False) return mse mse,extra=refined_predictions(net,d,cost=cfg['cost'],fixed=None,collect=collect) if collect: SIGNATURE_DATA.append(extra) return mse SIGNATURE_DATA=[] def make_base(cfg): return lambda s: train_eval(cfg,s,False) def make_idea(cfg): return lambda s: train_eval(cfg,s,True) def main(): mc=math_check() base_grid=[{'lr':lr,'steps':st} for lr in LRS for st in STEPS] base=sweep_baseline(make_base,base_grid) best_lr=base['best_cfg']['lr'] idea_grid=[{'lr':best_lr,'cost':c} for c in COSTS] # Same-sized idea sweep; all idea lrs occurred in baseline sweep. best=None tried=[] for cfg in idea_grid: r=evaluate(make_idea(cfg)) tried.append({'cfg':cfg,'mean':r['mean']}) if best is None or r['mean']=fr[i+1]-1e-9 for i in range(len(fr)-1))) report=make_report('dynamics','rnn_small',base,idea,{'math_check':mc,**sig}) report['idea_sweep']=idea_block report['protocol_notes']={'structural_match':'dynamics: actuated pendulum rollout and sequential refinement','epochs':EPOCHS,'n_train':NTRAIN,'n_test':NTEST,'paired_seeds':8,'baseline_knobs_swept':['lr','fixed refinement steps'],'idea_knobs_swept':['lr','Bellman cost']} Path('bench_report.json').write_text(json.dumps(report,indent=2)) print(json.dumps(report,indent=2)) if __name__=='__main__': main()