4MVVscCjYu / repro /src /core.py
DineshAI's picture
Add claim-by-claim Adam-DA reproduction evidence
e0f5bb6 verified
Raw
History Blame Contribute Delete
3.21 kB
"""Numerical primitives for the frozen judged-baseline reconstruction.
The game is
min_x max_y (a/2) x^2 + c x y - (b/2) y^2,
so its GDA Jacobian is [[-a, -c], [c, -b]].
"""
from __future__ import annotations
import numpy as np
def make_game(a: float, b: float, c: float) -> dict[str, object]:
jacobian = np.array([[-a, -c], [c, -b]], dtype=float)
return {
"a": float(a),
"b": float(b),
"c": float(c),
"jacobian": jacobian,
"lam": np.linalg.eigvals(jacobian),
}
def gradf(state: tuple[float, float], game: dict[str, object]) -> tuple[float, float]:
x, y = state
a = float(game["a"])
b = float(game["b"])
c = float(game["c"])
return a * x + c * y, c * x - b * y
def simulate(
game: dict[str, object],
x0: float,
y0: float,
beta: float,
rho: float,
eps: float,
h: float,
steps: int,
) -> np.ndarray:
"""Run the simultaneous, bias-corrected Adam-DA update from the paper."""
x, y = float(x0), float(y0)
mx = my = vx = vy = 0.0
trajectory = np.empty((steps + 1, 2), dtype=float)
trajectory[0] = (x, y)
for n in range(1, steps + 1):
gx, gy = gradf((x, y), game)
mx = beta * mx + (1.0 - beta) * gx
my = beta * my + (1.0 - beta) * gy
vx = rho * vx + (1.0 - rho) * gx * gx
vy = rho * vy + (1.0 - rho) * gy * gy
m_bias = 1.0 - beta**n
v_bias = 1.0 - rho**n
x -= h * (mx / m_bias) / np.sqrt(vx / v_bias + eps)
y += h * (my / m_bias) / np.sqrt(vy / v_bias + eps)
trajectory[n] = (x, y)
if not np.isfinite(x + y) or max(abs(x), abs(y)) > 1e8:
trajectory[n:] = np.nan
break
return trajectory
def converges(
game: dict[str, object],
beta: float,
rho: float,
eps: float,
h: float,
T: int = 1500,
) -> bool:
trajectory = simulate(game, 0.5, 0.5, beta, rho, eps, h, T)
if not np.isfinite(trajectory).all():
return False
radius = np.linalg.norm(trajectory, axis=1)
tail = radius[-max(100, T // 10) :]
return bool(tail.mean() < 0.08 * radius[0] and tail[-1] < 0.1 * radius[0])
def bound_continuous(game: dict[str, object], beta: float, eps: float) -> float:
"""Theorem 4.3, minimized over interaction-dominated eigenvalues."""
bounds: list[float] = []
for lam in np.asarray(game["lam"]):
re, im = abs(float(lam.real)), abs(float(lam.imag))
if im > re and re > 0.0:
bounds.append(2.0 * np.sqrt(eps) * (1.0 - beta) * re / ((1.0 + beta) * (im**2 - re**2)))
return float(min(bounds)) if bounds else 0.0
def bound_discrete(game: dict[str, object], beta: float, eps: float) -> float:
"""Theorem 4.4, minimized over the full Jacobian spectrum."""
bounds: list[float] = []
for lam in np.asarray(game["lam"]):
re, im = abs(float(lam.real)), abs(float(lam.imag))
if re == 0.0:
return 0.0
denominator = (1.0 + beta**2) * abs(lam) ** 2 + 2.0 * beta * (im**2 - re**2)
if denominator > 0.0:
bounds.append(2.0 * np.sqrt(eps) * (1.0 - beta**2) * re / denominator)
return float(min(bounds)) if bounds else 0.0