import json
import os
import numpy as np
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.join(HERE, "..")
FIXTURE_DIR = os.path.join(ROOT, "tests", "fixtures", "coupled_gauge")
NETWORK_JSON = os.path.join(FIXTURE_DIR, "network.json")
REF_JSON = os.path.join(FIXTURE_DIR, "reference.json")
R_MOON = 1_737_400.0
REL_TOL = 1e-9
GRAM_TOL = 1e-9
def assemble_fisher(rows, sigma: float) -> np.ndarray:
A = np.array(rows, dtype=np.float64) A = A.copy() A[:, 3:7] /= R_MOON w = 1.0 / (sigma ** 2)
return w * (A.T @ A)
def gram_rank(U_sub: np.ndarray) -> int:
if U_sub.shape[1] == 0:
return 0
gram = U_sub @ U_sub.T
evals = np.linalg.eigvalsh(gram)
return int(np.sum(evals > GRAM_TOL))
def classify(F: np.ndarray, rel_tol: float = REL_TOL) -> dict:
evals, evecs = np.linalg.eigh(F) lmax = float(evals[-1]) if evals.size else 0.0
null_mask = evals <= rel_tol * lmax
d = int(np.sum(null_mask))
if d == 0:
return {
"defect": 0,
"dim_spatial": 0,
"dim_temporal": 0,
"coupled_dim": 0,
"p_st_norm": 0.0,
}
U = evecs[:, null_mask]
U_S = U[0:7, :] U_T = U[7:9, :]
rs = gram_rank(U_S) rt = gram_rank(U_T)
dim_spatial = d - rt
dim_temporal = d - rs
coupled_dim = max(0, rs + rt - d)
P = U @ U.T p_st = P[0:7, 7:9] p_st_norm = float(np.linalg.norm(p_st, "fro"))
return {
"defect": d,
"dim_spatial": dim_spatial,
"dim_temporal": dim_temporal,
"coupled_dim": coupled_dim,
"p_st_norm": p_st_norm,
}
def marginal_eigs(F: np.ndarray) -> list:
K = [3, 7]
M = [0, 1, 2, 4, 5, 6, 8]
I_KK = F[np.ix_(K, K)] I_KM = F[np.ix_(K, M)] I_MM = F[np.ix_(M, M)]
D_inv = np.linalg.pinv(I_MM) S = I_KK - I_KM @ D_inv @ I_KM.T
evals = np.linalg.eigvalsh(S) return [float(x) for x in evals]
def process_network(rows: list, sigma: float) -> dict:
F = assemble_fisher(rows, sigma)
evals_all = np.linalg.eigvalsh(F)
lmax = float(evals_all[-1])
cls = classify(F)
m_eigs = marginal_eigs(F)
return {
"eigenvalues": [float(x) for x in evals_all],
"lambda_max": lmax,
"defect": cls["defect"],
"dim_spatial": cls["dim_spatial"],
"dim_temporal": cls["dim_temporal"],
"coupled_dim": cls["coupled_dim"],
"p_st_norm": cls["p_st_norm"],
"marginal_eigs": m_eigs,
}
with open(NETWORK_JSON) as fh:
net = json.load(fh)
sigma = float(net["sigma"])
results = {}
for name, nw in net["networks"].items():
rows = nw["rows"]
r = process_network(rows, sigma)
results[name] = r
print(f"\n{name} ({nw['n_rows']} rows):")
print(f" eigenvalues (9): {[f'{x:.4e}' for x in r['eigenvalues']]}")
print(f" defect={r['defect']}, dim_spatial={r['dim_spatial']}, "
f"dim_temporal={r['dim_temporal']}, coupled_dim={r['coupled_dim']}")
print(f" p_st_norm = {r['p_st_norm']:.6e}")
print(f" marginal_eigs (scale, offset): {[f'{x:.4e}' for x in r['marginal_eigs']]}")
reference = {
"description": (
"Validated anchor reference for `tests/lunar_coupled_gauge_reference.rs`. "
"Computed independently by numpy/LAPACK from the rows in "
"`network.json` (built by `examples/gen_coupled_gauge_rows.rs` with real "
"DE440 Moon PA orientation). "
"Validated claim: kshana's coupled-gauge linear algebra reproduces these "
"values to rel<1e-3 AND abs<1e-3 on real-DE440-derived rows."
),
"oracle": "numpy/LAPACK (np.linalg.eigvalsh, np.linalg.eigh, np.linalg.pinv)",
"R_MOON_M": R_MOON,
"rel_tol": REL_TOL,
"gram_tol": GRAM_TOL,
"networks": results,
}
os.makedirs(FIXTURE_DIR, exist_ok=True)
with open(REF_JSON, "w") as fh:
json.dump(reference, fh, indent=1)
print(f"\nwrote {REF_JSON}")