Degree-Calibrated Stable Residual Flow / run_experiment.py
Mechanism confirmed, baseline not beaten
1import json, math, random
2from pathlib import Path
3import numpy as np
4
5SEED = 3127
6rng = np.random.default_rng(SEED)
7
8# Degree-calibrated flow: f=-a*r^m*z + (I-zz'/||z||^2)h(z).
9def tangent_project(z, h, eps=1e-12):
10 q = np.sum(z*z, axis=-1, keepdims=True)
11 return h - z * (np.sum(z*h, axis=-1, keepdims=True) / (q + eps))
12
13def calibrated_f(z, W, a, m):
14 r = 0.5*np.sum(z*z, axis=-1, keepdims=True)
15 h = np.tanh(z @ W.T)
16 return -0.5*a*(r**m)*z + tangent_project(z, h)
17
18def simulate(z0, W, a, m, dt, steps, calibrated=True):
19 z = z0.copy()
20 norms, radial_errors = [], []
21 for _ in range(steps):
22 r = 0.5*np.sum(z*z, axis=1, keepdims=True)
23 if calibrated:
24 f = calibrated_f(z, W, a, m)
25 allowed = -a*(r**(m+1))
26 else:
27 f = np.tanh(z @ W.T)
28 allowed = np.zeros_like(r)
29 radial = np.sum(z*f, axis=1, keepdims=True)
30 radial_errors.append(float(np.max(radial-allowed)))
31 norms.append(float(np.max(np.linalg.norm(z, axis=1))))
32 z = z + dt*f
33 norms.append(float(np.max(np.linalg.norm(z, axis=1))))
34 return np.asarray(norms), np.asarray(radial_errors)
35
36def slope(x, y):
37 return float(np.polyfit(np.log(x), np.log(np.maximum(y, 1e-30)), 1)[0])
38
39def main():
40 random.seed(SEED); np.random.seed(SEED)
41 d, n, a, steps = 8, 256, 1.0, 30000
42 # Small initial states avoid numerical stiffness for m>0 while retaining a clear tail.
43 z0 = rng.normal(size=(n,d)); z0 *= rng.uniform(.6,1.4,size=(n,1)) / np.linalg.norm(z0,axis=1,keepdims=True)
44 W = rng.normal(scale=.7/math.sqrt(d), size=(d,d))
45
46 decay = {}
47 for m in (0,1,2):
48 z = z0.copy(); rs=[]
49 dt=.01
50 for _ in range(steps):
51 rs.append(float(np.mean(.5*np.sum(z*z,axis=1))))
52 z += dt*calibrated_f(z,W,a,m)
53 rs=np.asarray(rs)
54 # Fit sufficiently late, but before float underflow / Euler floor.
55 lo, hi = (100, 1500) if m == 0 else (3000, 25000)
56 if m == 0:
57 fit = float(np.polyfit(np.arange(lo,hi)*dt, np.log(rs[lo:hi]), 1)[0])
58 expected = -a
59 observed = fit
60 else:
61 fit = slope(np.arange(lo,hi)*dt, rs[lo:hi])
62 expected = -1.0/m
63 observed = fit
64 decay[str(m)] = {"observed_log_r_slope": observed, "expected": expected,
65 "initial_r": float(rs[0]), "final_r": float(rs[-1]),
66 "max_abs_radial_identity_error": None}
67 # Exact derivative check, independent of Euler discretization.
68 zcheck = rng.normal(size=(1000,d)); f=calibrated_f(zcheck,W,a,m)
69 rr=.5*np.sum(zcheck*zcheck,axis=1,keepdims=True)
70 err=np.max(np.abs(np.sum(zcheck*f,axis=1,keepdims=True)+a*rr**(m+1)))
71 decay[str(m)]["max_abs_radial_identity_error"] = float(err)
72
73 # Stability control: same learned field and Euler step, with/without radial calibration.
74 stability={}
75 for dt in (0.01, 0.1, 0.5, 1.0):
76 base_n, base_e = simulate(z0,W,a,1,dt,300,False)
77 idea_n, idea_e = simulate(z0,W,a,1,dt,300,True)
78 stability[str(dt)]={
79 "baseline_final_max_norm":float(base_n[-1]),
80 "idea_final_max_norm":float(idea_n[-1]),
81 "baseline_peak_norm":float(np.max(base_n)),
82 "idea_peak_norm":float(np.max(idea_n)),
83 "idea_max_continuous_radial_violation":float(np.max(idea_e)),
84 "baseline_max_radial_derivative":float(np.max(base_e))
85 }
86 # After input removal, calibrated state shrinks while unconstrained residual state persists/grows.
87 result={"seed":SEED,"dimension":d,"batch":n,"a":a,"decay":decay,"stability":stability,
88 "note":"Continuous radial identity is tested exactly; trajectory tests use explicit Euler."}
89 Path("results.json").write_text(json.dumps(result,indent=2))
90 print(json.dumps(result,indent=2))
91
92if __name__ == '__main__': main()