import csv
from pathlib import Path
import glmm
from _oracle import TOL_BETA_REL, TOL_SE_HESSIAN_REL, TOL_STDDEV_REL, check_rel, load_golden
DATA_PATH = Path(__file__).resolve().parents[3] / "validation" / "data" / "empirical" / "cbpp.csv"
with open(DATA_PATH, newline="") as f:
rows = list(csv.DictReader(f))
incidence = [float(r["incidence"]) for r in rows]
size = [float(r["size"]) for r in rows]
data = {
"prop": [i / s for i, s in zip(incidence, size)],
"period": [r["period"] for r in rows],
"herd": [r["herd"] for r in rows],
}
fit_laplace = glmm.fit(data, "prop ~ period + (1 | herd)", family="binomial", weights=size, nagq=1)
fit_agq = glmm.fit(data, "prop ~ period + (1 | herd)", family="binomial", weights=size, nagq=7)
print("=== nagq=1 (Laplace) ===")
fit_laplace.summary()
print("loglik:", fit_laplace.loglik)
print("\n=== nagq=7 (adaptive Gauss-Hermite) ===")
fit_agq.summary()
print("loglik:", fit_agq.loglik)
print("\nLaplace -> AGQ(7) movement on this data:")
for i, name in enumerate(fit_agq.names):
d = fit_agq.beta[i] - fit_laplace.beta[i]
rel = abs(d) / abs(fit_laplace.beta[i])
print(f" beta[{name}]: laplace={fit_laplace.beta[i]:.10g} agq7={fit_agq.beta[i]:.10g} "
f"delta={d:.3g} rel={rel:.3g}")
loglik_delta = fit_agq.loglik - fit_laplace.loglik
print(f" loglik: laplace={fit_laplace.loglik:.10g} agq7={fit_agq.loglik:.10g} delta={loglik_delta:.3g}")
print("\noracle cross-check vs goldens/cbpp_agq_k7.json (manifest rung 5 at nagq=7):")
print("(beta, se_hessian, herd stddev only -- see module docstring on why loglik is excluded)")
g = load_golden("cbpp_agq_k7")
est = g["estimates"]
for i, name in enumerate(g["coef_names"]):
check_rel(f"beta[{name}]", fit_agq.beta[i], est["beta"][i], TOL_BETA_REL)
for i, name in enumerate(g["coef_names"]):
check_rel(f"se_hessian[{name}]", fit_agq.se[i], est["se_hessian"][i], TOL_SE_HESSIAN_REL)
sd, _corr = fit_agq.stddev_corr(0)
check_rel("herd stddev", sd[0], est["varcomp"][0]["stddev"][0], TOL_STDDEV_REL)