process-calc / gaugebench.py
ApplePiesFromScratch's picture
Upload folder using huggingface_hub
ae01165 verified
Raw History Blame Contribute Delete
2.24 kB
#!/usr/bin/env python3
"""GaugeBench. Exact Q rate on listed polys. PROCESS vs float AD vs finite diff."""
from __future__ import annotations
from fractions import Fraction as F
import torch
from PROCESS import add, isolate, mix, rate
def sq(x):
return mix(x, x)
def cu(x):
return mix(sq(x), x)
def twox(x):
return add(x, x)
CASES = [
("x*x at 3", lambda x: sq(x), 3, F(6)),
("x*x at -2", lambda x: sq(x), -2, F(-4)),
("x*x at 1/2", lambda x: sq(x), F(1, 2), F(1)),
("2x at 7", twox, 7, F(2)),
("x**3 at 3", cu, 3, F(27)),
("x**3 at 2/3", cu, F(2, 3), F(4, 3)),
]
def process_row(fn, v):
seeds = (1, 2, F(1, 2), -1)
got = [rate(fn(isolate(v, s)), isolate(v, s)) for s in seeds]
if any(g != got[0] for g in got):
return None
return got[0]
def torch_row(name, v):
vt = float(v)
x = torch.tensor(vt, requires_grad=True)
if name.startswith("x*x"):
y = x * x
elif name.startswith("2x"):
y = x + x
elif name.startswith("x**3"):
y = x * x * x
else:
return None
y.backward()
return float(x.grad)
def fd_row(name, v, h=1e-6):
vt = float(v)
def f(z):
if name.startswith("x*x"):
return z * z
if name.startswith("2x"):
return z + z
if name.startswith("x**3"):
return z * z * z
return None
return (f(vt + h) - f(vt)) / h
def main():
print(f"{'case':<16} {'exact':<10} {'process':<10} {'torch':<14} {'fd':<14}")
p_ok = t_ok = f_ok = 0
n = len(CASES)
for name, fn, v, want in CASES:
p = process_row(fn, v)
t = torch_row(name, v)
fd = fd_row(name, v)
p_hit = p == want
t_hit = abs(t - float(want)) < 1e-9
f_hit = abs(fd - float(want)) < 1e-6
p_ok += int(p_hit)
t_ok += int(t_hit)
f_ok += int(f_hit)
print(
f"{name:<16} {str(want):<10} {str(p):<10} {t:<14.8g} {fd:<14.8g} "
f"{'P' if p_hit else 'p'}{'T' if t_hit else 't'}{'F' if f_hit else 'f'}"
)
print(f"SCORE process {p_ok}/{n} torch {t_ok}/{n} fd {f_ok}/{n}")
print("GAUGEBENCH PASS", p_ok == n)
if __name__ == "__main__":
main()