"""test_spectral_codebook.py — Gap-aware spectral codebook round-trip tests. Validates the spectral_codebook module against the 250-matrix PIST corpus: exact char-poly fingerprints (Cayley–Hamilton in integer arithmetic), pure-stdlib vs NumPy spectral-radius agreement, gap-aware quantization invariants, and the encode/decode round trip over all 250 equations. """ from __future__ import annotations import sys import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "python")) import spectral_codebook as sc def _mat_mul(a, b): n = len(a) return [ [sum(a[i][t] * b[t][j] for t in range(n)) for j in range(n)] for i in range(n) ] class TestSpectralCodebook(unittest.TestCase): @classmethod def setUpClass(cls): cls.matrices = sc.parse_matrices_lean() cls.codebook = sc.Codebook(cls.matrices) # ── parsing ───────────────────────────────────────────────────── def test_parse_250_8x8(self): self.assertEqual(len(self.matrices), 250) for eid, mat in self.matrices.items(): self.assertEqual(len(mat), 8, eid) self.assertTrue(all(len(r) == 8 for r in mat), eid) self.assertTrue(all(x >= 0 for r in mat for x in r), eid) # ── exact char poly ───────────────────────────────────────────── def test_charpoly_identity(self): # det(λI − I) = (λ − 1)^8 → coefficients are signed binomials ident = tuple(tuple(1 if i == j else 0 for j in range(8)) for i in range(8)) expect = (-8, 28, -56, 70, -56, 28, -8, 1) self.assertEqual(sc.charpoly_coeffs(ident), expect) def test_cayley_hamilton_integer(self): """p(M) = 0 exactly in integer arithmetic (spot check).""" for eid in sorted(self.matrices)[::50]: # 5 spread-out matrices m = [list(r) for r in self.matrices[eid]] coeffs = sc.charpoly_coeffs(m) n = len(m) acc = [[1 if i == j else 0 for j in range(n)] for i in range(n)] # M^0 total = [[coeffs[-1] if i == j else 0 for j in range(n)] for i in range(n)] for k in range(1, n + 1): acc = _mat_mul(acc, m) # M^k c = 1 if k == n else coeffs[n - 1 - k] for i in range(n): for j in range(n): total[i][j] += c * acc[i][j] self.assertTrue( all(x == 0 for row in total for x in row), f"Cayley–Hamilton failed for {eid}", ) def test_charpoly_trace_relation(self): for eid, mat in self.matrices.items(): coeffs = self.codebook.profiles[eid]["charpoly"] self.assertEqual(coeffs[0], -sum(mat[i][i] for i in range(8)), eid) # ── spectral radius ───────────────────────────────────────────── def test_pure_root_finder_matches_numpy(self): """Durand–Kerner on the exact char poly agrees with the fast path.""" for eid in sorted(self.matrices)[::10]: # 25 matrices p = self.codebook.profiles[eid] pure = sc._durand_kerner_max_modulus(p["charpoly"]) self.assertAlmostEqual(pure, p["spectral_radius"], places=4, msg=eid) def test_peripheral_spectra_are_unit(self): """The 9 'mid band' λ in the committed raw JSON (0.5 ≤ λ < 1) are power-iteration non-convergence artifacts: exact ρ = 1 for all 9.""" import json raw_path = Path(__file__).resolve().parent.parent / "data" / "spectral_codebook_raw.json" raw = json.loads(raw_path.read_text()) artifacts = [ e["equation_id"] for e in raw["entries"] if 0.5 <= e["spectral_radius"] < 1.0 ] self.assertEqual(len(artifacts), 9) for eid in artifacts: self.assertAlmostEqual( self.codebook.profiles[eid]["spectral_radius"], 1.0, places=6, msg=eid ) def test_nilpotent_class(self): """Every ρ = 0 matrix has char poly exactly x^8 (nilpotent), and the pure path detects it with no iteration.""" zeros = [ eid for eid, p in self.codebook.profiles.items() if p["spectral_radius"] == 0.0 ] self.assertEqual(len(zeros), 35) for eid in zeros: coeffs = self.codebook.profiles[eid]["charpoly"] self.assertEqual(list(coeffs), [0] * 8, eid) self.assertEqual(sc._durand_kerner_max_modulus(coeffs), 0.0) # ── fingerprints & collisions ─────────────────────────────────── def test_charpoly_strictly_finer_than_lambda(self): col = self.codebook.collision_report() self.assertEqual(col["corpus_size"], 250) self.assertEqual(col["distinct_matrices"], 238) self.assertEqual(col["duplicate_matrix_groups"], 11) self.assertEqual(col["duplicate_matrix_members"], 23) self.assertGreater(col["unique_charpoly"], col["unique_lambda_4dp"]) self.assertGreater( col["identified_by_charpoly"], col["identified_by_lambda_4dp"] ) # char poly is NOT injective: collision classes must be explicit self.assertGreater(col["charpoly_collision_groups"], 0) self.assertEqual( sum(len(v) for v in col["charpoly_collision_classes"].values()), col["charpoly_collision_members"], ) # ── quantization invariants ───────────────────────────────────── def test_boundaries_sorted_and_gapped(self): b = self.codebook.boundaries self.assertEqual(b, sorted(b)) self.assertGreater(len(b), 0) # no λ value sits on a boundary for p in self.codebook.profiles.values(): self.assertNotIn(p["spectral_radius"], b) def test_min_support_guard(self): """Every cluster holds ≥ MIN_SUPPORT distinct matrices.""" for row in self.codebook.cluster_table(): self.assertGreaterEqual( row["distinct_matrices"], sc.MIN_SUPPORT, row["codeword"] ) def test_cluster_partition_covers_corpus(self): table = self.codebook.cluster_table() self.assertEqual(sum(r["count"] for r in table), 250) self.assertEqual(sum(r["distinct_matrices"] for r in table), 238) # ── round trip ────────────────────────────────────────────────── def test_decode_is_bijective_over_250(self): seen = set() for eid in self.matrices: cw, idx = self.codebook.codeword_of(eid) self.assertNotIn((cw, idx), seen) seen.add((cw, idx)) self.assertEqual(self.codebook.decode(cw, idx), eid) self.assertEqual(len(seen), 250) def test_encode_decode_round_trip(self): """encode(matrix) → decode must return the same equation for every unique matrix, and a byte-identical matrix for exact duplicates (identical inputs are information-theoretically indistinguishable).""" dup_members = { eid for ids in self.codebook.matrix_groups.values() if len(ids) > 1 for eid in ids } for eid, mat in self.matrices.items(): cw, idx = self.codebook.encode([list(r) for r in mat]) self.assertIsNotNone(idx, eid) decoded = self.codebook.decode(cw, idx) if eid in dup_members: self.assertEqual(self.matrices[decoded], mat, eid) else: self.assertEqual(decoded, eid) def test_encode_novel_matrix(self): novel = [[3 if i == j else 1 for j in range(8)] for i in range(8)] cw, idx = self.codebook.encode(novel) self.assertIsNone(idx) self.assertTrue(cw.startswith("C")) # ── 278-row manifold ──────────────────────────────────────────── def test_manifold_278_no_new_gaps(self): mc = sc.manifold_check(self.codebook) self.assertEqual(mc["rows"], 278) self.assertEqual(mc["unique_ids"], 250) self.assertEqual(mc["extra_rows"], 28) self.assertEqual(mc["ids_without_matrix"], []) self.assertTrue(mc["boundaries_match_250"]) if __name__ == "__main__": unittest.main()