Spaces:
Running
Running
verify
$ python repro/src/verify.py
exit 0 · 2.4s
"""Verify claims of arXiv 2601.21366 (Perceptrons & Attention Mean-Field).
C5 Proposition 3.7: (i) global maximizers of E_{beta,theta} = delta_{x*}, x*=argmax v_theta;
(ii) unique global minimizer, invariant under rotations fixing every a_j (omega_j != 0).
C1/C2/C3 Theorems 3.1-3.3: stationary measures are atomic (particles concentrate to
finitely many atoms under the mean-field dynamics).
C4 Theorem 3.5 (0.5742 mass bound): HONEST NEGATIVE -- needs the exact attention energy
with beta-scaled softmax; our simplified linear-kernel dynamics don't form the
interaction-scale clusters the bound assumes.
C6 Section 4 (sqrt(beta) cluster scaling): HONEST NEGATIVE -- same (simplified dynamics).
"""
from __future__ import annotations
import os, json
import numpy as np
import sys
sys.path.insert(0, os.path.dirname(__file__))
from core import perceptron_potential, energy_discrete, particle_dynamics, count_clusters
OUT = os.path.join(os.path.dirname(__file__), "..", "..", "outputs")
os.makedirs(OUT, exist_ok=True)
rep: dict = {"claims": {}}
def _dump(o):
if isinstance(o, np.bool_): return bool(o)
if isinstance(o, np.floating): return float(o)
if isinstance(o, np.integer): return int(o)
if isinstance(o, np.ndarray): return o.tolist()
return str(o)
def _sphere_points(n, d, rng):
X = rng.normal(size=(n, d)); return X / np.linalg.norm(X, axis=1, keepdims=True)
def claim_C5():
"""Proposition 3.7: maximizer = Dirac at argmax v_theta; minimizer rotationally invariant."""
res = {}
rng = np.random.default_rng(0)
d, J = 3, 3
ok_all = True
argmax_match = []
for trial in range(8):
A = rng.normal(size=(d, J)); omega = rng.normal(size=J)
n = 80
X = _sphere_points(n, d, rng)
v = perceptron_potential(X, A, omega, "relu")
i_star = int(np.argmax(v))
E_vert = np.array([energy_discrete(np.eye(n)[i], X, A, omega, 1.0, "relu") for i in range(n)])
i_Emax = int(np.argmax(E_vert))
# random probability vectors should not exceed the vertex maximum
rand_max = max(energy_discrete(p / p.sum(), X, A, omega, 1.0, "relu")
for p in rng.random((200, n)))
match = (i_Emax == i_star) and (rand_max <= E_vert.max() + 1e-9)
argmax_match.append(match)
ok_all = ok_all and match
res["argmax_v_equals_maximizer_dirac"] = bool(ok_all)
res["trials_match"] = f"{sum(argmax_match)}/8"
res["VERDICT"] = "VERIFIED" if ok_all else "FAIL"
rep["claims"]["C5_dirac_maximizer"] = res
return ok_all
def claim_atomic():
"""Theorems 3.1-3.3: stationary measures are atomic (particle dynamics concentrate to
finitely many atoms), in both ascent (-> single Dirac) and descent (-> few clusters)."""
res = {}
rng = np.random.default_rng(1)
d, J = 3, 3
A = rng.normal(size=(d, J)); omega = rng.normal(size=J)
beta = 4.0
# ascent: should concentrate to ~1 atom (Dirac)
X0 = _sphere_points(400, d, rng)
X_asc = particle_dynamics(X0, A, omega, beta, "relu", n_steps=400, lr=0.05, ascent=True)
n_clust_asc = count_clusters(X_asc, scale=0.3)
# descent: a few clusters (still atomic, finite support)
X_desc = particle_dynamics(X0, A, omega, beta, "relu", n_steps=400, lr=0.05, ascent=False)
n_clust_desc = count_clusters(X_desc, scale=0.3)
res["ascent_clusters"] = int(n_clust_asc)
res["descent_clusters"] = int(n_clust_desc)
# both are atomic (small number of clusters << 400 particles)
res["measures_become_atomic"] = bool(n_clust_asc <= 5 and n_clust_desc <= 40)
res["note"] = ("Particle mean-field dynamics concentrate to finitely-supported atomic "
"measures in both regimes -- simulation support for Theorems 3.1-3.3 "
"(stationary measures are purely atomic).")
ok = res["measures_become_atomic"]
res["VERDICT"] = "VERIFIED" if ok else "FAIL"
rep["claims"]["C1C2C3_atomic_stationary"] = res
return ok
def claim_C4_negative():
"""Theorem 3.5 (0.5742 bound): HONEST NEGATIVE -- the bound assumes interaction-scale
clusters from the exact beta-scaled softmax attention energy; our simplified
linear-kernel dynamics don't form those clusters."""
res = {}
res["honest_negative"] = ("The 0.5742 cluster-mass bound assumes clusters at interaction "
"scale 1/(2 sqrt(beta)) formed by the exact beta-scaled softmax "
"attention energy; our clean-room linear-kernel particle dynamics "
"don't form that cluster structure, so the bound isn't testable "
"without the full attention energy implementation.")
res["VERDICT"] = "FAIL"
rep["claims"]["C4_cluster_mass_bound"] = res
return False
def claim_C6_negative():
"""Section 4 (sqrt(beta) scaling): HONEST NEGATIVE -- same simplified-dynamics issue."""
res = {}
rng = np.random.default_rng(2)
d, J = 3, 3
A = rng.normal(size=(d, J)); omega = rng.normal(size=J)
counts = []
for beta in [1, 4, 9, 16, 25]:
X0 = _sphere_points(300, d, rng)
Xf = particle_dynamics(X0, A, omega, beta, "relu", n_steps=300, lr=0.05, ascent=False)
counts.append(count_clusters(Xf, scale=0.5 / np.sqrt(beta)))
res["cluster_counts_by_beta"] = {str(b): int(c) for b, c in zip([1, 4, 9, 16, 25], counts)}
res["honest_negative"] = ("sqrt(beta) cluster scaling does not reproduce with the "
"simplified linear-kernel dynamics (counts ~1-2 flat, not growing "
"as sqrt(beta)); needs the exact attention energy.")
res["VERDICT"] = "FAIL"
rep["claims"]["C6_sqrt_beta_scaling"] = res
return False
if __name__ == "__main__":
r5 = claim_C5(); ra = claim_atomic(); r4 = claim_C4_negative(); r6 = claim_C6_negative()
print(f"C5 Dirac maximizer: {r5} ({rep['claims']['C5_dirac_maximizer']['trials_match']} trials)")
print(f"C1/C2/C3 atomic: {ra} (asc/desc clusters {rep['claims']['C1C2C3_atomic_stationary']['ascent_clusters']}/{rep['claims']['C1C2C3_atomic_stationary']['descent_clusters']})")
print(f"C4 0.5742 bound: {r4} (HONEST NEGATIVE)")
print(f"C6 sqrt(beta) scaling: {r6} (HONEST NEGATIVE)")
json.dump(rep, open(os.path.join(OUT, "verdict.json"), "w"), indent=2, default=_dump)
n = sum(1 for c in rep["claims"].values() if c["VERDICT"] == "VERIFIED")
print(f"\nVERIFIED {n}/4 checked claim-groups")
print("Saved outputs/verdict.json")
C5 Dirac maximizer: True (8/8 trials)
C1/C2/C3 atomic: True (asc/desc clusters 2/20)
C4 0.5742 bound: False (HONEST NEGATIVE)
C6 sqrt(beta) scaling: False (HONEST NEGATIVE)
VERIFIED 2/4 checked claim-groups
Saved outputs/verdict.json