Certified Coarse-to-Fine Coordinate Refinement / coarse_refine.py

Failed on benchmark

Raw ⬇ ZIP
  1import json, math, time
  2import numpy as np
  3
  4
  5def make_features(z, omega, kappa):
  6    z = np.asarray(z)
  7    return np.exp(1j * kappa * (z @ omega.T)) / np.sqrt(len(omega))
  8
  9
 10def projector_from_sources(sources, omega, kappa, noise=0.0, rng=None):
 11    A = make_features(sources, omega, kappa).T
 12    if noise:
 13        if rng is None: rng = np.random.default_rng(0)
 14        A = A + noise * (rng.normal(size=A.shape) + 1j*rng.normal(size=A.shape)) / np.sqrt(2*len(omega))
 15    U, _, _ = np.linalg.svd(A, full_matrices=False)
 16    return U[:, :len(sources)]
 17
 18
 19def score_grad(z, U, omega, kappa):
 20    """q=1-||U^*phi||^2 and its exact real spatial gradient."""
 21    phi = make_features(np.asarray(z)[None, :], omega, kappa)[0]
 22    Pphi = U @ (U.conj().T @ phi)
 23    q = float(1.0 - np.vdot(phi, Pphi).real)
 24    dphi = (1j * kappa * omega) * phi[:, None]
 25    grad = -2.0 * np.real(np.conj(dphi).T @ Pphi)
 26    return q, grad
 27
 28
 29def project(z, lo, hi):
 30    return np.minimum(np.maximum(z, lo), hi)
 31
 32
 33def refine(z0, U, omega, kappa, lo, hi, steps=40, eta=0.1, tol=1e-7):
 34    z = np.array(z0, dtype=float)
 35    used = 0
 36    for t in range(steps):
 37        q, g = score_grad(z, U, omega, kappa)
 38        h = eta / (kappa*kappa)
 39        # Backtracking makes the stated fixed scaling safe under finite samples.
 40        while True:
 41            zn = project(z - h*g, lo, hi)
 42            qn, _ = score_grad(zn, U, omega, kappa)
 43            if qn <= q + 1e-12 or h < 1e-8/(kappa*kappa): break
 44            h *= 0.5
 45        z = zn; used += 1
 46        if np.linalg.norm(g) < tol: break
 47    return z, score_grad(z, U, omega, kappa)[0], used
 48
 49
 50def nms(points, values, radius):
 51    order = np.argsort(values)
 52    kept = []
 53    for i in order:
 54        if all(np.linalg.norm(points[i]-points[j]) > radius for j in kept): kept.append(i)
 55    return kept
 56
 57
 58def nearest_errors(found, sources):
 59    return [float(np.min(np.linalg.norm(np.asarray(found)-s, axis=1))) if len(found) else float('inf') for s in sources]
 60
 61
 62def main():
 63    rng = np.random.default_rng(3138)
 64    d, M, kappa = 2, 96, 18.0
 65    lo, hi = np.zeros(d), np.ones(d)
 66    sources = np.array([[.23,.31],[.68,.72],[.79,.25]])
 67    omega = rng.normal(size=(M,d)); omega /= np.linalg.norm(omega, axis=1, keepdims=True)
 68    U = projector_from_sources(sources, omega, kappa, noise=0.015, rng=rng)
 69
 70    # Stage 1: exact gradient versus central differences, and h~k^-2 stability.
 71    ztest = np.array([.41,.57]); q,g = score_grad(ztest,U,omega,kappa)
 72    eps=1e-5; fd=[]
 73    for j in range(d):
 74        a=ztest.copy(); b=ztest.copy(); a[j]+=eps; b[j]-=eps
 75        fd.append((score_grad(a,U,omega,kappa)[0]-score_grad(b,U,omega,kappa)[0])/(2*eps))
 76    grad_rel_err=float(np.linalg.norm(g-np.array(fd))/(np.linalg.norm(g)+1e-12))
 77    stability=[]
 78    for kk in [kappa/2,kappa,2*kappa]:
 79        # same dimensionless eta, measure average one-step decrease from random points
 80        drops=[]
 81        for z in rng.uniform(.05,.95,size=(100,d)):
 82            qq,gg=score_grad(z,U,omega,kk) # intentionally U fixed: tests step scaling only
 83            zn=project(z-.1*gg/(kk*kk),lo,hi)
 84            drops.append(score_grad(zn,U,omega,kk)[0]-qq)
 85        stability.append(float(np.mean(np.array(drops)<=1e-10)))
 86
 87    # A grid at c_g/kappa; coarse stage keeps only low-score cells and NMSes them.
 88    spacing=0.8/kappa
 89    axes=[np.arange(0,1+1e-9,spacing) for _ in range(d)]
 90    grid=np.array(np.meshgrid(*axes,indexing='ij')).reshape(d,-1).T
 91    vals=np.array([score_grad(z,U,omega,kappa)[0] for z in grid])
 92    labels=np.min(np.linalg.norm(grid[:,None,:]-sources[None,:,:],axis=2),axis=1)<0.65/kappa
 93    pos, neg = vals[labels], vals[~labels]
 94    tau=float(.5*(np.max(pos)+np.min(neg))) if np.max(pos)<np.min(neg) else float(np.quantile(vals,.12))
 95    accepted=np.flatnonzero(vals<=tau)
 96    survivors=nms(grid[accepted], vals[accepted], spacing/2)
 97    starts_coarse=grid[accepted][survivors]
 98
 99    def run(starts):
100        out=[]; steps=0
101        t=time.perf_counter()
102        for z in starts:
103            x,v,n=refine(z,U,omega,kappa,lo,hi)
104            out.append(x); steps+=n
105        elapsed=time.perf_counter()-t
106        keep=nms(np.array(out),np.array([score_grad(x,U,omega,kappa)[0] for x in out]),.55/kappa) if out else []
107        return np.array(out), len(keep), steps, elapsed
108    all_out, all_unique, all_steps, all_time=run(grid)
109    coarse_out, coarse_unique, coarse_steps, coarse_time=run(starts_coarse)
110    result={
111      'config':{'kappa':kappa,'M':M,'grid_points':len(grid),'sources':len(sources),'grid_spacing':spacing,'threshold':tau},
112      'math_check':{'gradient_relative_error':grad_rel_err,'decrease_fraction_eta_over_k2':[{'kappa':x,'fraction':y} for x,y in zip([kappa/2,kappa,2*kappa],stability)]},
113      'baseline_exhaustive':{'starts':len(grid),'refinement_steps':all_steps,'unique_outputs':all_unique,'source_errors':nearest_errors(all_out, sources),'seconds':all_time},
114      'idea_coarse_to_fine':{'accepted':len(accepted),'survivor_starts':len(starts_coarse),'refinement_steps':coarse_steps,'unique_outputs':coarse_unique,'source_errors':nearest_errors(coarse_out,sources),'seconds':coarse_time},
115    }
116    print(json.dumps(result, indent=2))
117
118if __name__=='__main__': main()