Entropy-Feedback Zeroth-Order Cooling / verify_entropy_cooling.py

Mechanism confirmed, baseline not beaten

Raw ⬇ ZIP
 1import json, math
 2import numpy as np
 3
 4
 5def sigmoid(x):
 6    return 1.0 / (1.0 + np.exp(-np.clip(x, -60, 60)))
 7
 8
 9def weights(losses, tau):
10    z = -(losses - np.min(losses)) / max(tau, 1e-15)
11    z -= np.max(z)
12    w = np.exp(np.clip(z, -80, 0))
13    return w / w.sum()
14
15
16def entropy(w):
17    return float(-(w * np.log(np.maximum(w, 1e-300))).sum())
18
19
20def controller_rate(h, alpha=.05, eps=.02, hc=.5, delta=.05):
21    b = sigmoid((h-hc)/delta)
22    return alpha * (eps + (1-eps)*b)
23
24
25def main():
26    rng = np.random.default_rng(1234)
27    N = 128; hc=.5; delta=.05; alpha=.05; eps=.02
28    # Prediction 1: ESS identity and transition ESS, across random populations.
29    identity_errors=[]
30    for _ in range(100):
31        losses=rng.normal(size=N)*rng.uniform(.1, 5)
32        w=weights(losses, rng.uniform(.01, 3))
33        H=entropy(w); h=H/math.log(N); ess=math.exp(H)
34        identity_errors.append(abs(ess/N - math.exp(-(1-h)*math.log(N))))
35    transition_pred=N**hc
36    # Make a population with exactly uniform weights over K candidates; h=log(K)/log(N).
37    K=round(transition_pred)
38    w=np.zeros(N); w[:K]=1/K
39    h_transition=entropy(w)/math.log(N)
40    ess_transition=math.exp(entropy(w))
41
42    # Prediction 2: tau log slope is controller_rate in fixed-entropy regimes.
43    rate_rows=[]
44    for h in [.1, .9, .5]:
45        tau=1.0; logs=[]
46        for _ in range(200):
47            logs.append(math.log(tau)); tau *= math.exp(-controller_rate(h,alpha,eps,hc,delta))
48        observed=-(logs[-1]-logs[0])/(len(logs)-1)
49        rate_rows.append({'h':h, 'predicted_abs_slope':controller_rate(h,alpha,eps,hc,delta), 'observed_abs_slope':observed})
50
51    # Prediction 3: entropy threshold crossing in a temperature sweep. Candidate losses are
52    # 0 for K good candidates and 1 for the rest; solve/search tau where h ~= hc.
53    sweep=[]
54    for K0 in [1, 2, 4, 8, 16, 32, 64]:
55        taus=np.logspace(-3,2,500)
56        hs=[]
57        for tau in taus:
58            ll=np.ones(N); ll[:K0]=0
59            hs.append(entropy(weights(ll,tau))/math.log(N))
60        idx=int(np.argmin(np.abs(np.asarray(hs)-hc)))
61        sweep.append({'good_candidates':K0, 'tau_at_hc':float(taus[idx]), 'h':float(hs[idx])})
62
63    # Mini optimizer: diagonal ill-conditioned quadratic, same perturbations for all methods per seed.
64    d=24; T=180; pop=64; sigma=.18; gamma=1.0
65    curv=np.geomspace(1, 20, d)
66    def run(seed, mode):
67        r=np.random.default_rng(seed); theta=r.normal(0, 2, d); tau=1.0
68        vals=[]; hs=[]
69        for t in range(T):
70            e=r.normal(size=(pop,d)); cand=theta[None,:]+sigma*e
71            loss=.5*np.sum(curv[None,:]*cand*cand,axis=1)
72            if mode=='constant': tau_use=1.0
73            else: tau_use=tau
74            w=weights(loss,tau_use); H=entropy(w); h=H/math.log(pop)
75            theta=(1-gamma)*theta+gamma*(w[:,None]*cand).sum(axis=0)
76            if mode=='feedback': tau*=math.exp(-controller_rate(h,alpha,eps,hc,delta))
77            elif mode=='fixed': tau*=math.exp(-alpha)
78            vals.append(float(.5*np.sum(curv*theta*theta))); hs.append(h)
79        return {'final':vals[-1], 'best':min(vals), 'mean_h_last20':float(np.mean(hs[-20:])), 'tau_final':tau, 'loss_curve':vals}
80    results={}
81    for mode in ['feedback','fixed','constant']:
82        runs=[run(s,mode) for s in range(5)]
83        results[mode]={'final_mean':float(np.mean([x['final'] for x in runs])), 'final_std':float(np.std([x['final'] for x in runs])), 'best_mean':float(np.mean([x['best'] for x in runs])), 'h_last20_mean':float(np.mean([x['mean_h_last20'] for x in runs])), 'tau_final_mean':float(np.mean([x['tau_final'] for x in runs]))}
84
85    out={'config':{'N':N,'hc':hc,'delta':delta,'alpha':alpha,'epsilon':eps},
86         'prediction_1_ess_identity_max_abs_error':max(identity_errors),
87         'prediction_1_transition':{'predicted_ESS':transition_pred,'constructed_K':K,'observed_h':h_transition,'observed_ESS':ess_transition},
88         'prediction_2_rates':rate_rows,
89         'prediction_3_temperature_sweep':sweep,
90         'mini_experiment':results}
91    with open('results.json','w') as f: json.dump(out,f,indent=2)
92    print(json.dumps(out,indent=2))
93
94if __name__=='__main__': main()