# beta_backend_python.py import numpy as np from scipy.special import gamma from scipy.optimize import minimize_scalar def loglike_beta(beta, s): """ Log-likelihood of Wigner surmise for Dyson index beta: P(s;β) = aβ * s^β * exp(-bβ * s^2) """ if beta <= 0: return -np.inf bβ = (gamma((beta + 2) / 2) / gamma((beta + 1) / 2)) ** 2 aβ = 2 * (bβ ** ((beta + 1) / 2)) / gamma((beta + 1) / 2) return np.sum(np.log(aβ) + beta * np.log(s) - bβ * s * s) def beta_mle(spacings): """ Python version of Julia's beta_mle(spacings) """ s = spacings / np.mean(spacings) # normalize to ⟨s⟩ = 1 # maximize log-likelihood → minimize negative log-likelihood def objective(beta): return -loglike_beta(beta, s) result = minimize_scalar( objective, bounds=(0.1, 5.0), method="bounded", options={"xatol": 1e-5}, ) if not result.success: raise RuntimeError("β optimization failed: " + result.message) return float(result.x) def compute_beta_file(path): """ Reads a text file of spacings and prints β̂. """ with open(path, "r") as f: raw = f.read() # replace commas → spaces for c in [",", "\n", "\t"]: raw = raw.replace(c, " ") toks = raw.split() if len(toks) == 0: raise ValueError("No valid numbers found.") spacings = np.array([float(t) for t in toks], dtype=float) beta_hat = beta_mle(spacings) print(beta_hat) if __name__ == "__main__": import sys if len(sys.argv) != 1 + 1: raise SystemExit("Usage: python beta_backend_python.py ") compute_beta_file(sys.argv[1])