"""Reconstruction-property test for ``starg_svd``. Verifies ``U ★_G S ★_G Vh ≈ A`` for both the abelian fast path (cyclic Z_12) and the non-abelian per-irrep block path (chiral octahedral group). Run as a script: python -m starg_torch.test_svd Pass criterion: max element-wise reconstruction error < 1e-5 in float32 (the SVD is computed in complex64 internally). """ from __future__ import annotations import sys import torch from .algebra import GroupAlgebra from .product import starg_product from .svd import starg_svd def _check(name: str, group: GroupAlgebra, L: int, M: int, atol: float): torch.manual_seed(0) A = torch.randn(L, M, group.n, dtype=torch.float32) U, S, Vh = starg_svd(A, group) A_reco = starg_product(starg_product(U, S, group), Vh, group) err = (A - A_reco).abs().max().item() fnorm = A.norm().item() rel = err / max(fnorm, 1e-12) status = "PASS" if err < atol else "FAIL" print( f"[{status}] {name}: |G|={group.n} (L,M)=({L},{M}) " f"max_err={err:.3e} rel={rel:.3e} threshold={atol:.0e}" ) return err < atol def main(): ok = True # 1. Abelian cyclic Z_12, fast path (per-Fourier-bin SVD) G_cyc = GroupAlgebra("cyclic", 12) ok &= _check("cyclic Z_12 (abelian)", G_cyc, L=8, M=10, atol=1e-4) # 2. Non-abelian chiral octahedral group, per-irrep block path G_oct = GroupAlgebra("octahedral") ok &= _check("chiral octahedral O (non-abelian)", G_oct, L=6, M=9, atol=1e-3) # 3. Cyclic with non-square L=M=K (reconstruction at full rank) ok &= _check("cyclic Z_8 square 6x6", GroupAlgebra("cyclic", 8), L=6, M=6, atol=1e-4) # 4. Octahedral square (full rank) ok &= _check("octahedral square 8x8", G_oct, L=8, M=8, atol=1e-3) print() print("OVERALL:", "PASS" if ok else "FAIL") sys.exit(0 if ok else 1) if __name__ == "__main__": main()