Second-order fusion prior for point-set diffusion / run_experiment.py
Failed on benchmark
1import json, math, random
2import numpy as np
3import mpmath as mp
4
5SEED=1234
6np.random.seed(SEED); random.seed(SEED)
7
8def kappa(m,beta):
9 if m*beta <= 1: raise ValueError('requires m beta > 1')
10 return beta*beta/(8*(m*beta-1)*(2*m+1))
11
12def V(a):
13 a=np.asarray(a); return sum((a[i]-a[j])**2 for i in range(len(a)) for j in range(i+1,len(a)))
14
15def rho_det_mp(x):
16 mp.mp.dps=80
17 x=[mp.mpf(str(v)) for v in x]; m=len(x)
18 A=mp.matrix(m)
19 for i in range(m):
20 for j in range(m):
21 d=x[i]-x[j]
22 A[i,j]=1/(2*mp.pi) if d==0 else mp.sin(d/2)/(mp.pi*d)
23 return mp.det(A)
24
25def normalized_ratio_mp(e,a,beta=2):
26 e=mp.mpf(str(e)); aa=[mp.mpf(str(v)) for v in a]; m=len(aa)
27 lead=abs(e)**(beta*m*(m-1)/2)
28 for i in range(m):
29 for j in range(i+1,m): lead*=abs(aa[i]-aa[j])**beta
30 return rho_det_mp([e*v for v in aa])/lead
31
32def prior_score(x,beta=2,delta=.02,include_correction=True):
33 x=np.asarray(x,float); m=len(x); kap=kappa(m,beta) if include_correction else 0.
34 d=x[:,None]-x[None,:]; den=d*d+delta*delta
35 rep=np.divide(d,den,out=np.zeros_like(d),where=den>0)
36 np.fill_diagonal(rep,0); np.fill_diagonal(d,0)
37 return beta*np.sum(rep,axis=1)-2*kap*np.sum(d,axis=1)
38
39def langevin(kind, n=8, beta=2, steps=2800, burn=800, dt=.0015, delta=.03):
40 x=np.sort(np.random.randn(n)); samples=[]
41 for it in range(steps):
42 if kind=='baseline': g=-x
43 elif kind=='repulsion': g=-x+prior_score(x,beta,delta,False)
44 else: g=-x+prior_score(x,beta,delta,True)
45 x=x+dt*g+math.sqrt(2*dt)*np.random.randn(n)
46 if it>=burn: samples.append(np.sort(x.copy()))
47 return np.asarray(samples)
48
49def metrics(samples):
50 gaps=np.diff(samples,axis=1).ravel(); gaps=gaps/(np.mean(gaps)+1e-12)
51 return {'collision_rate_gap_lt_0.10':float(np.mean(gaps<.10)), 'gap_std':float(np.std(gaps)), 'min_gap_p05':float(np.quantile(gaps,.05))}
52
53def theorem_check(a):
54 m=len(a); kap=kappa(m,2); es=np.array([.004,.006,.009,.013,.018,.025,.035,.05])
55 rs=np.array([float(normalized_ratio_mp(e,a)) for e in es])
56 # R(e)=C + B e^2 + D e^4; theorem predicts -B/(C V)=kappa.
57 z=es**2; A=np.column_stack([np.ones(len(z)),z,z*z])
58 C,B,_=np.linalg.lstsq(A,rs,rcond=None)[0]
59 est=-B/(C*V(a))
60 return {'m':m,'theory_kappa':kap,'estimated_kappa':float(est),'relative_error':float(abs(est-kap)/kap), 'leading_constant':float(C)}
61
62def main():
63 checks=[theorem_check([0.,1.]),theorem_check([0.,1.,2.])]
64 x=np.array([-.71,-.11,.63]); b=1.7; h=1e-6
65 def logp(y): return b*sum(math.log(abs(y[i]-y[j])) for i in range(3) for j in range(i+1,3))-kappa(3,b)*V(y)
66 fd=np.array([(logp(x+np.eye(3)[i]*h)-logp(x-np.eye(3)[i]*h))/(2*h) for i in range(3)])
67 analytic=prior_score(x,b,0.0,True)
68 score={'max_abs_error':float(np.max(abs(fd-analytic))),'finite_difference':fd.tolist(),'analytic':analytic.tolist()}
69 sam={k:metrics(langevin(k)) for k in ['baseline','repulsion','full']}
70 result={'seed':SEED,'theorem_checks':checks,'score_check':score,'sampler':sam}
71 print(json.dumps(result,indent=2)); open('results.json','w').write(json.dumps(result,indent=2))
72
73if __name__=='__main__': main()