#!/usr/bin/env python3 """TGA 2.1 acceptance tests. Explicit unittest checks survive python -O.""" import math import tempfile import unittest from dataclasses import replace from pathlib import Path import tga_verifier as t SAMPLE = (-3.0, -2.0, -1.0, 1.0, 2.0, 3.0) class TGA21(unittest.TestCase): def test_01_tga20_bytes_unchanged(self): for name, (size, digest) in t.TGA20_FILES.items(): blob = (t.TGA20_DIR / name).read_bytes() self.assertEqual(len(blob), size) self.assertEqual(t.hashlib.sha256(blob).hexdigest(), digest) def test_02_relationship_count_matches_graph(self): report = t.build_report() edges = report["graph"]["edges"] self.assertEqual(report["graph"]["relationship_count"], len(edges)) self.assertEqual(len(report["graph"]["certificates"]), len(edges)) self.assertEqual(sum(1 for edge in edges if edge["introduced_in"] == "2.0"), 19) self.assertGreater(len(edges), 19) categories = {edge["alignment"]["relation"] for edge in edges} self.assertEqual(categories, set(report["graph"]["relation_categories"])) self.assertTrue(all(item["admitted"] is False for item in report["proposals_only"])) self.assertNotEqual(report["publication"]["status"], report["mathematical_justification"]["note"]) def test_03_scaling_and_label_order(self): for factor in (0.5, 1.0, 2.0): scaled = t.scale_marks(SAMPLE, factor) self.assertEqual(scaled, tuple(factor * v for v in SAMPLE)) result = t.run_operation(t.OP_SCALE, SAMPLE, r=factor, beta=None) self.assertEqual(result["configuration"]["label_order"], list(t.LABELS)) self.assertEqual(result["configuration"]["coordinate_units"], "dimensionless") self.assertEqual(result["configuration"]["beta_declaration"], "phi/(phi+pi)") self.assertEqual(result["configuration"]["r"], factor) self.assertTrue(result["reversible_badge"]) def test_04_path_identities_scales_and_angles(self): scales = (0.5, 1.0, 2.0) angles = (t.CANONICAL_EPSILON, math.pi / 2, 1.0, math.pi) amplitudes = (0.5, 1.0, 2.0) betas = (None, 1.0, 4.0) for amplitude in amplitudes: for angle in angles: source = t.geometry_marks(amplitude, angle) for factor in scales: for beta in betas: soft = t.path_certificate(t.SCHEMA_SOFTMAX, source, r=factor, beta=beta) four = t.path_certificate(t.SCHEMA_FOURIER, source, r=factor, beta=beta) self.assertTrue(soft["admitted"], soft) self.assertTrue(four["admitted"], four) self.assertLess(soft["certificate"]["numerical_execution"]["max_abs_residual"], 1e-8) self.assertLess(four["certificate"]["numerical_execution"]["max_abs_residual"], 1e-8) self.assertIn("trusted analytic schema", soft["certificate"]["mathematical_justification"]) self.assertNotEqual(soft["certificate"]["mathematical_justification"], soft["certificate"]["numerical_execution"]["meaning"]) self.assertEqual(soft["certificate"]["retained_context"]["label_order"], list(t.LABELS)) def test_05_power_laws_and_inverse_roundtrip(self): probs = t.softmax(SAMPLE, None) self.assertEqual(t.power_probability(probs, 1), probs) for left, right, product in ((2.0, 0.5, 1.0), (0.5, 2.0, 1.0), (2.0, 3.0, 6.0), (0.5, 0.5, 0.25)): composed = t.power_probability(t.power_probability(probs, right), left) direct = t.power_probability(probs, product) self.assertLess(max(abs(a - b) for a, b in zip(composed, direct)), 1e-10) roundtrip = t.power_probability(t.power_probability(probs, 2.0), 0.5) self.assertLess(max(abs(a - b) for a, b in zip(roundtrip, probs)), 1e-10) back = t.centered_log(t.softmax(t.scale_marks(SAMPLE, 2.0), 4.0), 4.0) self.assertLess(max(abs(a - b) for a, b in zip(back, tuple(2 * v for v in SAMPLE))), 1e-8) def test_06_fourier_dc_phase_and_labels(self): spectrum = t.marked_fourier(SAMPLE) self.assertLess(abs(spectrum[0] - 6 * t.C0), 1e-9) scaled = t.scale_fourier(spectrum, 2) self.assertEqual(scaled[0], spectrum[0]) for k in range(1, 6): self.assertLess(abs(spectrum[6 - k] + spectrum[k].conjugate()), 1e-8) if abs(spectrum[k]) > 1e-10: self.assertLess(abs(cmath_phase(scaled[k]) - cmath_phase(spectrum[k])), 1e-10) result = t.run_operation(t.OP_DSCALE, spectrum, r=2, beta=None) self.assertEqual(result["configuration"]["label_order"], list(t.LABELS)) self.assertEqual(result["configuration"]["fourier_bin_order"][0], "k0") restored = t.marked_fourier_inverse(spectrum) self.assertLess(max(abs(a - b) for a, b in zip(restored, SAMPLE)), 1e-8) def test_07_membership_recovers_parameters(self): cases = ( (1.0, t.CANONICAL_EPSILON, None, "canonical"), (0.5, math.pi / 2, 1.0, "family"), (2.0, 1.0, 4.0, "family"), (1.5, math.pi, None, "family"), ) for amplitude, angle, beta, mode in cases: source = t.geometry_marks(amplitude, angle) probs = t.softmax(source, beta) report = t.six_mark_membership(probs, beta=beta, mode=mode) self.assertEqual(report["probability_type"], "valid_positive_probability_vector") self.assertEqual(report["numerical_status"], "numerically_consistent", report) self.assertIsNone(report["exact_membership_certificate"]) beta_value = t.LAMBDA if beta is None else beta self.assertLess(abs(report["recovered"]["a"] - amplitude) / amplitude, 1e-6) self.assertLess(abs(report["recovered"]["epsilon"] - angle), 1e-6) self.assertEqual(report["recovered"]["label_order"], list(t.LABELS)) self.assertAlmostEqual(report["recovered"]["beta"], beta_value) canonical = t.softmax(t.geometry_marks(1.0, t.CANONICAL_EPSILON), None) family_only = t.six_mark_membership(t.softmax(t.geometry_marks(1.0, math.pi / 2), None), mode="canonical") self.assertEqual(family_only["numerical_status"], "not_canonical_angle") self.assertEqual(family_only["family_numerical_status"], "numerically_consistent") exact = t.six_mark_membership(canonical, mode="canonical") self.assertEqual(exact["numerical_status"], "numerically_consistent") self.assertTrue(exact["canonical_angle"]) def test_08_generic_and_uniform_probabilities(self): generic = (0.05, 0.10, 0.15, 0.20, 0.22, 0.28) self.assertLess(abs(math.fsum(generic) - 1), 1e-12) report = t.six_mark_membership(generic) self.assertEqual(report["probability_type"], "valid_positive_probability_vector") self.assertEqual(report["numerical_status"], "not_member") self.assertEqual(report["six_mark_type"], "not_the_six_mark_family") self.assertIsNone(report["exact_membership_certificate"]) uniform = (1 / 6,) * 6 flat = t.six_mark_membership(uniform) self.assertEqual(flat["probability_type"], "valid_positive_probability_vector") self.assertEqual(flat["numerical_status"], "not_positive_scale") powered = t.power_probability(generic, 2) self.assertEqual(t.six_mark_membership(powered)["probability_type"], "valid_positive_probability_vector") def test_09_uncertain_boundary_is_not_clamped(self): source = list(t.geometry_marks(1.0, math.pi / 2)) # Push the third gap just above the closed endpoint without editing the verifier. beta = 1.0 probs = list(t.softmax(source, beta)) gaps = [math.log(probs[i + 1] / probs[i]) for i in range(5)] g2 = gaps[1] s_over = 1 + 5e-9 gaps[2] = 2 * s_over * g2 forced = gaps_to_probability(gaps) report = t.six_mark_membership(forced, beta=beta) self.assertEqual(report["numerical_status"], "uncertain_boundary", report) self.assertGreater(report["residuals"]["s_unclamped"], 1) self.assertIsNone(report["recovered"]) self.assertIsNone(report["diagnostics"]["epsilon"]) tiny = t.geometry_marks(1e-12, math.pi / 2) tiny_report = t.six_mark_membership(t.softmax(tiny, 1.0), beta=1.0) self.assertEqual(tiny_report["numerical_status"], "uncertain_boundary") self.assertIsNone(tiny_report["recovered"]) def test_10_rejections_do_not_certify_or_clip(self): bad_probabilities = { (0.0, 0.2, 0.2, 0.2, 0.2, 0.2): "NOT_STRICTLY_POSITIVE", (-0.1, 0.3, 0.2, 0.2, 0.2, 0.2): "NOT_STRICTLY_POSITIVE", (math.nan, 0.2, 0.2, 0.2, 0.2, 0.2): "NONFINITE", (math.inf, 0.0, 0.0, 0.0, 0.0, 0.0): "NONFINITE", (0.2, 0.2, 0.2, 0.2, 0.2, 0.2): "MALFORMED_NORMALIZATION", (1, 1, 1, 1, 1, 1): "MALFORMED_NORMALIZATION", } for value, code in bad_probabilities.items(): with self.assertRaises(t.Reject) as caught: t.power_probability(value, 2) self.assertEqual(caught.exception.code, code) report = t.six_mark_membership(value) self.assertIsNone(report["exact_membership_certificate"]) self.assertFalse(report["reversible_badge"]) self.assertIsNone(report["recovered"]) for factor in (0, -1, math.nan): with self.assertRaises(t.Reject) as caught: t.scale_marks(SAMPLE, factor) self.assertIn(caught.exception.code, {"PARAMETER_REJECTED", "NONFINITE"}) for beta in (0, -2, math.inf): with self.assertRaises(t.Reject) as caught: t.softmax(SAMPLE, beta) self.assertIn(caught.exception.code, {"PARAMETER_REJECTED", "NONFINITE"}) for args in ((0, math.pi / 2), (-1, 1), (1, 0), (1, -0.2), (1, math.pi + 0.01), (math.nan, 1)): with self.assertRaises(t.Reject): t.geometry_marks(*args) wide = (-1e6, -1e6, -1e6, 1e6, 1e6, 1e6) failed = t.run_operation(t.OP_SOFTMAX, wide, r=1, beta=1) self.assertEqual(failed["status"], "LEFT_POSITIVE_DOMAIN") self.assertIsNone(failed["value"]) self.assertFalse(failed["reversible_badge"]) issued = t.path_certificate(t.SCHEMA_SOFTMAX, wide, r=1, beta=1) self.assertFalse(issued["admitted"]) self.assertEqual(issued["condition"], "LEFT_POSITIVE_DOMAIN") self.assertIsNone(issued["certificate"]) self.assertFalse(issued["reversible_badge"]) def test_11_unsupported_schema_and_bad_paths(self): for schema_id in ("tga.2.1/proof/not-a-theorem", "1+1=2", "", "tga.2.1/proof/power-composition"): issued = t.path_certificate(schema_id, SAMPLE, r=2) self.assertFalse(issued["admitted"]) self.assertEqual(issued["condition"], "UNSUPPORTED_PROOF_SCHEMA") self.assertIsNone(issued["certificate"]) self.assertNotIn("numerical_execution", issued) mismatch = t.path_certificate(t.SCHEMA_SOFTMAX, SAMPLE, r=2, paths={"left": [t.OP_FOURIER, t.OP_DSCALE], "right": [t.OP_SOFTMAX, t.OP_POWER]}) self.assertEqual(mismatch["condition"], "INCOMPATIBLE_PATH_TYPES") self.assertIsNone(mismatch["certificate"]) missing = t.run_path(["tga.2.1/not-an-operation"], SAMPLE, r=2, beta=None) self.assertEqual(missing["status"], "PATH_UNDEFINED") self.assertFalse(missing["reversible_badge"]) uncentered = t.path_certificate(t.SCHEMA_SOFTMAX, (1, 2, 3, 4, 5, 6), r=2) self.assertFalse(uncentered["admitted"]) self.assertEqual(uncentered["condition"], "CONTRACT_VIOLATION") self.assertIsNone(uncentered["certificate"]) def test_12_derivation_heading_is_required(self): with tempfile.TemporaryDirectory() as tmp: path = Path(tmp) / "PROOFS.md" path.write_text("# nothing\n\n## other\n\n", encoding="utf-8") issued = t.path_certificate(t.SCHEMA_SOFTMAX, SAMPLE, r=2, proofs_path=path) self.assertFalse(issued["admitted"]) self.assertEqual(issued["condition"], "DERIVATION_MISSING") self.assertIsNone(issued["certificate"]) with self.assertRaises(t.Reject) as caught: t.verify_local(t.make_local("softmax_beta"), proofs_path=path) self.assertEqual(caught.exception.code, "DERIVATION_MISSING") def test_13_schema_tampering_rejected(self): spec = t.make_local("power_probability") with self.assertRaises(t.Reject): t.verify_local(replace(spec, alignment=replace(spec.alignment, relation=t.tga20.Relation.APPROXIMATION))) with self.assertRaises(t.Reject): t.verify_local(replace(spec, implementation="clip")) with self.assertRaises(t.Reject): t.make_local("shared_symbol_proves_physics") with self.assertRaises(t.Reject): t.execute_local("path_softmax_scale", SAMPLE, r=2) def test_14_rendered_proof_matches_source(self): source = t.PROOFS_PATH.read_text(encoding="utf-8") rendered = t.render_proofs_html(source) self.assertEqual(rendered, t.HTML_PATH.read_text(encoding="utf-8")) for heading in ("softmax-scale-power", "fourier-mark-scale", "power-composition", "six-mark-membership", "normalization-policy", "tolerance-policy", "centered-log-ratio", "path-certificate"): self.assertIn(f'

', rendered) self.assertIn(f"## {heading}\n", source) def test_15_inherited_ledger_still_rejects_bad_remainder(self): rows = t.tga20.execute(t.tga20.make_spec("ledger"), 399) self.assertEqual(rows[0], 639958766566422) self.assertEqual(t.tga20.execute(t.tga20.make_spec("unledger"), rows), 399) with self.assertRaises(t.tga20.Reject) as caught: t.tga20.execute(t.tga20.make_spec("unledger"), (rows[0] + 1,) + rows[1:]) self.assertIn("REVERSE_DIVISIBILITY", str(caught.exception)) def test_16_reversed_labels_are_not_the_family(self): probs = t.softmax(t.geometry_marks(1.0, t.CANONICAL_EPSILON), None) flipped = t.six_mark_membership(tuple(reversed(probs))) self.assertEqual(flipped["probability_type"], "valid_positive_probability_vector") self.assertIn(flipped["numerical_status"], {"not_member", "not_positive_scale"}) self.assertIsNone(flipped["exact_membership_certificate"]) def cmath_phase(value: complex) -> float: return math.atan2(value.imag, value.real) def gaps_to_probability(gaps: list[float]) -> tuple[float, ...]: logs = [0.0] for gap in gaps: logs.append(logs[-1] + gap) mean = math.fsum(logs) / 6 centered = tuple((value - mean) for value in logs) return t.softmax(centered, 1.0) if __name__ == "__main__": unittest.main()