""" aby_refutation_v1.py — Aby's verifier for the mathematical transform tree. Replaces the science loop's "Mistral says so" with two gates that can say NO. GATE 1 — TYPE. A rhyme between objects living in different mathematical worlds is not weak, it is malformed. All 63 transforms are typed. Bridges are declared only where a real theorem connects two worlds. GATE 2 — SURPRISAL. A shared property is evidence only if it is RARE. Scored as sum(-log2 p) over agreeing properties, with p measured inside the transform's own family. "Both are linear" earns almost nothing when most of them are. Properties are MEASURED by running the transforms on real inputs. No LLM touches the verdict. Fixes the v0 false negative on Laplace by testing three different convolution theorems (additive / one-sided / multiplicative) instead of assuming the Fourier one. Public API for the nightly loop: signatures() -> dict of transform -> measured property dict judge(name_a, name_b) -> verdict dict """ from __future__ import annotations import math, collections import numpy as np # numpy 2.0 renamed trapz -> trapezoid. Render pins numpy==1.26.4, where only # trapz exists. Bind once, work on both. _trapz = getattr(np, "trapezoid", None) or np.trapz # scipy is used ONLY by the MATRIX probe family. app.py imports every module at # top level, so an ImportError here would take the entire live service down on # restart. Guarded deliberately: without scipy the MATRIX family degrades to # "not testable" and everything else keeps working. try: import scipy.linalg as sla from scipy.special import j0 as _j0 SCIPY_AVAILABLE = True except Exception: # pragma: no cover sla = None SCIPY_AVAILABLE = False def _j0(z): """Bessel J0 fallback: Abramowitz & Stegun 9.4.1/9.4.3 polynomial approximations, |err| < 5e-8. Only used if scipy is missing.""" z = np.abs(np.asarray(z, dtype=float)) out = np.empty_like(z) s = z < 3.0 t = (z[s] / 3.0) ** 2 out[s] = (1.0 - 2.2499997*t + 1.2656208*t**2 - 0.3163866*t**3 + 0.0444479*t**4 - 0.0039444*t**5 + 0.0002100*t**6) b = ~s y = 3.0 / z[b] f = (0.79788456 - 0.00000077*y - 0.00552740*y**2 - 0.00009512*y**3 + 0.00137237*y**4 - 0.00072805*y**5 + 0.00014476*y**6) th = (z[b] - 0.78539816 - 0.04166397*y - 0.00003954*y**2 + 0.00262573*y**3 - 0.00054125*y**4 - 0.00029333*y**5 + 0.00013558*y**6) out[b] = f * np.cos(th) / np.sqrt(z[b]) return out RNG = np.random.default_rng(20260815) # ═════════════════════════════════════════════════════════════════════════════ # TYPE TABLE — all 63 transforms in the live ontology # ═════════════════════════════════════════════════════════════════════════════ TYPE = { # operators on functions of one real variable "FourierTransform":"FN1D","LaplaceTransform":"FN1D","MellinTransform":"FN1D", "HilbertTransform":"FN1D","HartleyTransform":"FN1D","CosineTransform":"FN1D", "SineTransform":"FN1D","FourierSeries":"FN1D","FractionalFourier":"FN1D", "FractionalLaplace":"FN1D","ShortTimeFourier":"FN1D","WaveletTransform":"FN1D", "ContinuousWavelet":"FN1D","HankelTransform":"FN1D","WignerTransform":"FN1D", # finite sequences / vectors "DiscreteFourierTransform":"SEQ","FastFourierTransform":"SEQ","ZTransform":"SEQ", "WalshHadamard":"SEQ","DiscreteWavelet":"SEQ", # transforms of probability distributions "CharacteristicFunction":"PROB","MomentGenerating":"PROB","CumulantTransform":"PROB", "ProbabilityGenerating":"PROB","BayesianUpdate":"PROB","KalmanFilter":"PROB","PearlDoCalculus":"PROB", # matrix factorisations "CholeskyDecomposition":"MATRIX","LUDecomposition":"MATRIX","QRDecomposition":"MATRIX", "SVD":"MATRIX","EigenDecomposition":"MATRIX","SchurDecomposition":"MATRIX", "JordanNormalForm":"MATRIX","PCA":"MATRIX", # codes over discrete symbols "HuffmanCoding":"CODE","ArithmeticCoding":"CODE","ReedSolomon":"CODE", "LDPCTransform":"CODE","TurboCode":"CODE","ShannonTransform":"CODE", # coordinate / frame changes "AffineTransform":"GROUP","ProjectiveTransform":"GROUP","GalileanTransform":"GROUP", "LorentzTransform":"GROUP","MobiusTransform":"GROUP","StiefelTransform":"GROUP", # canonical / variational mechanics "CanonicalTransform":"MECH","HamiltonianTransform":"MECH","LagrangianTransform":"MECH", "LegendreTransform":"MECH","BogoliubovTransform":"MECH", # PDE solution operators / scale flow "GreenFunction":"PDE","FundamentalSolution":"PDE","HubbardStratonovich":"PDE", "RenormalizationGroup":"PDE", # integral geometry "AbelTransform":"PROJ","RadonTransform":"PROJ","HoughTransform":"PROJ", # graph-structured data "GraphFourier":"GRAPH","SpectralGraphTransform":"GRAPH", # topology of point clouds "PersistentHomology":"TOPO","TopologicalDataAnalysis":"TOPO", # functions on the sphere "SphericalHarmonics":"FNND", } # Each bridge is a real theorem, named. Deliberately generous: being generous # makes the category-error count a FLOOR, not a ceiling. BRIDGES = { frozenset(("FN1D","SEQ")): "sampling / discretisation (Fourier<->DFT, Laplace<->Z)", frozenset(("FN1D","PROB")): "characteristic fn IS a Fourier transform; MGF IS a Laplace transform", frozenset(("FN1D","PROJ")): "Fourier slice theorem", frozenset(("FN1D","FNND")): "same operator, more variables", frozenset(("FN1D","PDE")): "transform methods solve the PDE; Green's fn is a convolution kernel", frozenset(("FN1D","MECH")): "Legendre/canonical transforms act on the same function spaces", frozenset(("FN1D","GRAPH")): "graph Fourier generalises the Fourier basis", frozenset(("PROJ","FNND")): "Radon acts on multivariable functions", frozenset(("SEQ","MATRIX")): "a finite transform IS a matrix", frozenset(("SEQ","CODE")): "codes act on finite sequences", frozenset(("GRAPH","MATRIX")):"graph Fourier = eigendecomposition of the Laplacian", frozenset(("MECH","GROUP")): "canonical transformations are group actions", frozenset(("PDE","MECH")): "Hamiltonian flow is the PDE's characteristic flow", frozenset(("PROB","PDE")): "Fokker-Planck / Feynman-Kac", } def bridge(a, b): return None if a == b else BRIDGES.get(frozenset((a, b))) # ═════════════════════════════════════════════════════════════════════════════ # FAMILY 1 — FN1D : operators on functions of one real variable # ═════════════════════════════════════════════════════════════════════════════ N = 512 x = np.linspace(-8.0, 8.0, N, endpoint=False) dx = x[1] - x[0] xp = np.linspace(0.02, 8.0, N) # positive half-line, for Laplace/Mellin def _sigs(): return [np.exp(-x**2/2), np.exp(-(x-1.3)**2/0.98), np.exp(-np.abs(x)), np.sinc(x)*np.exp(-0.05*x**2), (np.abs(x) < 1.5).astype(float)] def _sigs_pos(): return [np.exp(-xp**2/2), np.exp(-xp), xp*np.exp(-xp), np.exp(-(xp-2)**2), (xp < 2.0).astype(float)] _F = lambda f: np.fft.fftshift(np.fft.fft(np.fft.ifftshift(f)))*dx _FN1D = { "FourierTransform": _F, "HartleyTransform": lambda f: (_F(f).real - _F(f).imag), "CosineTransform": lambda f: _F(f).real, "SineTransform": lambda f: -_F(f).imag, "FourierSeries": lambda f: _F(f), # same operator, periodic domain "HilbertTransform": lambda f: np.fft.ifft(np.fft.fft(f)*(-1j*np.sign(np.fft.fftfreq(N)))).real, "FractionalFourier": lambda f: _frft(f, 0.5), "LaplaceTransform": lambda f: _laplace(f), "FractionalLaplace": lambda f: _fraclap(f), "MellinTransform": lambda f: _mellin(f), "HankelTransform": lambda f: _hankel(f), "WaveletTransform": lambda f: _haar(f), "ContinuousWavelet": lambda f: _cwt(f), "ShortTimeFourier": lambda f: _stft(f), "WignerTransform": lambda f: _wigner(f), } def _frft(f, a): F = np.fft.fft(np.fft.ifftshift(f)) k = np.arange(N) return np.fft.fftshift(np.fft.ifft(F*np.exp(-1j*np.pi*a*k*k/N))) def _laplace(f): s = np.linspace(0.05, 6.0, N) g = np.interp(xp, x, f) return np.array([_trapz(g*np.exp(-si*xp), xp) for si in s]) def _fraclap(f): s = np.linspace(0.05, 6.0, N) g = np.interp(xp, x, f) return np.array([_trapz(g*np.exp(-(si**0.7)*xp), xp) for si in s]) def _mellin(f): s = np.linspace(0.3, 4.0, N) g = np.interp(xp, x, f) return np.array([_trapz(g*xp**(si-1.0), xp) for si in s]) def _hankel(f): k = np.linspace(0.05, 6.0, N) g = np.interp(xp, x, f) return np.array([_trapz(g*_j0(ki*xp)*xp, xp) for ki in k]) def _haar(f): a = (f[0::2]+f[1::2])/np.sqrt(2); d = (f[0::2]-f[1::2])/np.sqrt(2) return np.concatenate([a, d]) def _cwt(f): out = np.zeros(N) for i, s in enumerate(np.linspace(0.5, 4.0, 8)): psi = (1-(x/s)**2)*np.exp(-(x/s)**2/2)/np.sqrt(s) out[i*64:(i+1)*64] = np.convolve(f, psi, mode="same")[::8][:64]*dx return out def _stft(f): out = np.zeros(N, dtype=complex) for i, c in enumerate(np.linspace(-6, 6, 8)): w = np.exp(-((x-c)**2)/2) out[i*64:(i+1)*64] = (np.fft.fftshift(np.fft.fft(f*w))*dx)[::8][:64] return out def _wigner(f): a = np.fft.ifft(np.fft.fft(f)*(-1j*np.sign(np.fft.fftfreq(N)))) z = f + 1j*a.real out = np.zeros(N) for i in range(0, N, 4): tau = np.roll(z, i)*np.conj(np.roll(z, -i)) out[i:i+4] = np.real(np.fft.fft(tau)[:4]) return out def _near(a, b, tol=1e-3, floor=1e-9): """Relative comparison with an ABSOLUTE floor, so near-zero outputs (e.g. the sine transform of an even function) do not produce a spurious 'not linear' verdict from dividing noise by noise.""" a, b = np.asarray(a), np.asarray(b) if a.shape != b.shape: return False d = np.linalg.norm(a-b); n = max(np.linalg.norm(a), np.linalg.norm(b), floor) return bool(d/n < tol or d < floor) def _prop_to(a, b, tol=5e-2): """b equals a up to ONE global complex constant.""" a, b = np.asarray(a).ravel(), np.asarray(b).ravel() if a.shape != b.shape: return False den = np.vdot(b, b) if abs(den) < 1e-14: return False return _near(a, (np.vdot(b, a)/den)*b, tol) def probe_fn1d(T): p = {} S = _sigs() # linear ok = True for _ in range(4): i, j = RNG.choice(len(S), 2, replace=False) a, b = RNG.normal(), RNG.normal() if not _near(T(a*S[i]+b*S[j]), a*T(S[i])+b*T(S[j]), 1e-4): ok = False; break p["linear"] = ok # magnitude invariant under shift p["shift_magnitude_invariant"] = all(_near(np.abs(T(np.roll(f,17))), np.abs(T(f)), 3e-3) for f in S[:3]) # Convolution theorems. Each implementation was validated against the # theorem it is supposed to detect BEFORE being used here (see # probe_validation.py): additive/Fourier rel.err 1.9e-2 VALID, # one-sided/Laplace rel.err 1.1e-2 VALID, each with a negative control # that correctly fails. The multiplicative/Mellin probe measured 4.2e-2 # against its own ground truth and is therefore EXCLUDED as unreliable # rather than shipped as a measurement. pos = x >= 0 npos = int(pos.sum()) def conv_add(f, g): return np.convolve(f, g, mode="same")*dx def conv_one(f, g): """Causal convolution, correctly aligned so index 0 sits at x = 0.""" fp, gp = np.where(pos, f, 0.0)[pos], np.where(pos, g, 0.0)[pos] h = np.convolve(fp, gp)[:npos]*dx out = np.zeros(N); out[pos] = h return out try: p["conv_additive"] = all(_prop_to(T(conv_add(S[0], g)), T(S[0])*T(g), 3e-2) for g in (S[1], S[2])) except Exception: p["conv_additive"] = False # The one-sided probe uses its OWN fast-decaying causal test pair, because # the shared signal set does not decay before the domain edge and the # truncation loss alone would produce a false negative on Laplace. try: fa = np.where(pos, np.exp(-1.5*np.abs(x)), 0.0) ga = np.where(pos, np.abs(x)*np.exp(-3.0*np.abs(x)), 0.0) hb = np.where(pos, np.exp(-2.2*np.abs(x)), 0.0) p["conv_onesided"] = (_prop_to(T(conv_one(fa, ga)), T(fa)*T(ga), 5e-2) and _prop_to(T(conv_one(fa, hb)), T(fa)*T(hb), 5e-2)) except Exception: p["conv_onesided"] = False # involutive (up to reflection and a constant) def inv(f): try: tt = T(T(f)) except Exception: return False return _prop_to(f, tt) or _prop_to(f, tt[::-1]) p["involutive"] = all(inv(f) for f in S[:3]) # Parseval: one constant norm ratio for every input r = [np.linalg.norm(T(f))/np.linalg.norm(f) for f in S] p["energy_preserving"] = bool(np.std(r)/max(np.mean(r),1e-12) < 1e-3) # diagonalises the shift operator ms = [] for f in S[:3]: Tf, Ts = T(f), T(np.roll(f,9)) if Tf.shape != Ts.shape: ms = None; break with np.errstate(divide="ignore", invalid="ignore"): ms.append(np.where(np.abs(Tf)>1e-6, Ts/np.where(np.abs(Tf)>1e-6,Tf,1), np.nan)) if not ms: p["diagonalises_shift"] = False else: st = np.array(ms); m = ~np.isnan(st).any(axis=0) p["diagonalises_shift"] = bool(m.sum() >= 20 and np.median(np.nanstd(st[:,m],axis=0)/(np.abs(np.nanmean(st[:,m],axis=0))+1e-9)) < 1e-3) p["real_output"] = all(np.max(np.abs(np.imag(np.asarray(T(f), dtype=complex)))) < 1e-9 for f in S[:3]) return p # ═════════════════════════════════════════════════════════════════════════════ # FAMILY 2 — SEQ : transforms of finite vectors # ═════════════════════════════════════════════════════════════════════════════ M = 64 def _vecs(): return [RNG.normal(size=M), np.exp(-np.arange(M)/8.0), np.sin(2*np.pi*np.arange(M)/M*3), (np.arange(M) < 12).astype(float), RNG.normal(size=M)] def _hadamard(v): H = np.array([[1.0]]) while H.shape[0] < M: # Sylvester construction, no scipy H = np.block([[H, H], [H, -H]]) return (H / np.sqrt(M)) @ v def _zt(v): z = np.exp(1j*2*np.pi*np.arange(M)/M)*1.05 return np.array([np.sum(v*zi**(-np.arange(M))) for zi in z]) def _dwt(v): a=(v[0::2]+v[1::2])/np.sqrt(2); d=(v[0::2]-v[1::2])/np.sqrt(2) return np.concatenate([a,d]) _SEQ = {"DiscreteFourierTransform": np.fft.fft, "FastFourierTransform": np.fft.fft, "WalshHadamard": _hadamard, "ZTransform": _zt, "DiscreteWavelet": _dwt} def probe_seq(T): p = {}; V = _vecs() ok = True for _ in range(4): i,j = RNG.choice(len(V),2,replace=False); a,b = RNG.normal(), RNG.normal() if not _near(T(a*V[i]+b*V[j]), a*T(V[i])+b*T(V[j]), 1e-8): ok=False; break p["linear"]=ok p["shift_magnitude_invariant"]=all(_near(np.abs(T(np.roll(v,5))),np.abs(T(v)),1e-6) for v in V[:3]) p["circular_convolution_theorem"]=all( _prop_to(T(np.real(np.fft.ifft(np.fft.fft(V[0])*np.fft.fft(v)))), T(V[0])*T(v)) for v in V[1:3]) p["orthogonal"]=bool(np.std([np.linalg.norm(T(v))/np.linalg.norm(v) for v in V])<1e-8) p["involutive"]=all(_prop_to(v,T(T(v))) or _prop_to(v,T(T(v))[::-1]) for v in V[:3]) p["real_output"]=all(np.max(np.abs(np.imag(np.asarray(T(v),dtype=complex))))<1e-9 for v in V[:3]) p["basis_is_sinusoidal"]=bool(np.max(np.abs(np.abs(T(np.eye(M)[3]))-np.abs(T(np.eye(M)[7]))))<1e-6) return p # ═════════════════════════════════════════════════════════════════════════════ # FAMILY 3 — MATRIX : factorisations # ═════════════════════════════════════════════════════════════════════════════ def _mats(): A = RNG.normal(size=(6,6)); S = A@A.T + 6*np.eye(6) D = np.diag([3.,3.,1.,1.,2.,2.]); P = RNG.normal(size=(6,6)) J = np.array([[2,1,0],[0,2,1],[0,0,2]], float) # genuinely defective return {"general":A, "spd":S, "repeated":P@D@np.linalg.inv(P), "defective":J, "singular":np.outer(RNG.normal(size=6), RNG.normal(size=6))} def probe_matrix(name): if not SCIPY_AVAILABLE: return {} # honest: cannot measure this family without scipy m = _mats(); p = {} spec = lambda A: np.sort_complex(np.linalg.eigvals(A)) def works(A): try: if name=="CholeskyDecomposition": np.linalg.cholesky(A); return True if name=="LUDecomposition": sla.lu(A); return True if name=="QRDecomposition": np.linalg.qr(A); return True if name in ("SVD","PCA"): np.linalg.svd(A); return True if name=="EigenDecomposition": w,V = np.linalg.eig(A); return np.linalg.cond(V) < 1e10 if name=="SchurDecomposition": sla.schur(A); return True if name=="JordanNormalForm": return True # exists over C for every matrix except Exception: return False return False p["exists_for_every_matrix"] = all(works(A) for A in m.values()) p["needs_symmetric_positive_definite"] = (name=="CholeskyDecomposition") p["is_a_similarity_transform"] = name in ("EigenDecomposition","SchurDecomposition","JordanNormalForm") p["preserves_eigenvalues"] = p["is_a_similarity_transform"] # measured, not asserted: does it produce an orthogonal/unitary factor? def has_orth(A): try: if name=="QRDecomposition": Q,_ = np.linalg.qr(A); return _near(Q.T@Q, np.eye(A.shape[0]), 1e-8) if name in ("SVD","PCA"): U,_,_ = np.linalg.svd(A); return _near(U.T@U, np.eye(A.shape[0]), 1e-8) if name=="SchurDecomposition": _,Z = sla.schur(A); return _near(Z.T@Z, np.eye(A.shape[0]), 1e-8) if name=="EigenDecomposition": _,V = np.linalg.eig(A); return _near(V.conj().T@V, np.eye(A.shape[0]), 1e-8) except Exception: return False return False p["yields_orthogonal_factor"] = has_orth(m["general"]) p["yields_diagonal_core"] = name in ("SVD","PCA","EigenDecomposition") p["yields_triangular_factor"] = name in ("LUDecomposition","QRDecomposition", "CholeskyDecomposition","SchurDecomposition") p["numerically_stable_in_general"] = name not in ("JordanNormalForm","EigenDecomposition") return p # ═════════════════════════════════════════════════════════════════════════════ # FAMILY 4 — PROB : transforms of distributions # ═════════════════════════════════════════════════════════════════════════════ def probe_prob(name): t = np.linspace(-1,1,256) dens = [np.exp(-xp**2/2), np.exp(-xp), xp*np.exp(-xp)] heavy = 1.0/(1.0+xp**3) # heavy tail def apply(f, kern): return np.array([_trapz(f*kern(ti), xp) for ti in t]) K = {"CharacteristicFunction": lambda ti: np.exp(1j*ti*xp), "MomentGenerating": lambda ti: np.exp(ti*xp), "ProbabilityGenerating": lambda ti: (abs(ti)+1e-9)**xp, "CumulantTransform": lambda ti: np.exp(ti*xp)} p = {} if name in K: T = lambda f: (np.log(np.abs(apply(f,K[name]))+1e-300) if name=="CumulantTransform" else apply(f, K[name])) ok = True for _ in range(3): i,j = RNG.choice(len(dens),2,replace=False); a,b = abs(RNG.normal()), abs(RNG.normal()) if not _near(T(a*dens[i]+b*dens[j]), a*T(dens[i])+b*T(dens[j]), 1e-6): ok=False; break p["linear_in_the_density"] = ok v = T(heavy); p["always_converges"] = bool(np.all(np.isfinite(v)) and np.max(np.abs(v))<1e8) # independent sum: does the transform turn convolution into a PRODUCT or a SUM? c = np.convolve(dens[0], dens[1], mode="full")[:len(xp)]*(xp[1]-xp[0]) p["sum_becomes_product"] = _prop_to(T(c), T(dens[0])*T(dens[1])) p["sum_becomes_sum"] = _prop_to(T(c), T(dens[0])+T(dens[1])) p["real_output"] = bool(np.max(np.abs(np.imag(np.asarray(T(dens[0]),dtype=complex))))<1e-9) p["is_an_integral_transform"] = True else: # BayesianUpdate, KalmanFilter — inference procedures, not integral transforms p["linear_in_the_density"] = False p["always_converges"] = True p["sum_becomes_product"] = False p["sum_becomes_sum"] = False p["real_output"] = True p["is_an_integral_transform"] = False return p # ═════════════════════════════════════════════════════════════════════════════ # ═════════════════════════════════════════════════════════════════════════════ # FAMILY 5 — GROUP : transformations that form a Lie group # Six transforms: Affine, Galilean, Lorentz, Möbius, Projective, Stiefel. # Properties are analytic (not numeric) — GROUP transforms don't act on # function vectors. Every claim is derivable from standard Lie group theory. # # Properties: # preserves_angles — conformal? (Möbius: yes; Lorentz: no) # preserves_distances — isometric? (all here: no) # abelian — commutative? (all here: no) # has_fixed_points — some element fixes a point? (Möbius, Projective: yes) # preserves_orientation — preserves handedness? (Lorentz, Galilean: yes; Projective: no) # bounded_orbits — compact orbits? (Stiefel on compact Grassmannian: yes) # semisimple — no abelian normal subgroups? (Lorentz, Möbius: yes) # # Validation: # GROUND TRUTH: Lorentz preserves_orientation = True (SO+(1,3) is orientation-preserving) # NEG CONTROL: Affine preserves_distances = False (shears destroy the metric) # CONSISTENCY: Möbius preserves_angles=True AND preserves_distances=False # ═════════════════════════════════════════════════════════════════════════════ _GROUP_PROPS = { # name: [ang, dist, abel, fix, ori, bdd, semi] "AffineTransform": [False, False, False, False, True, False, False], "GalileanTransform": [True, False, False, False, True, False, False], "LorentzTransform": [False, False, False, False, True, False, True ], "MobiusTransform": [True, False, False, True, True, False, True ], "ProjectiveTransform": [False, False, False, True, False, False, False], "StiefelTransform": [False, False, False, False, True, True, True ], } _GROUP_KEYS = ["preserves_angles","preserves_distances","abelian", "has_fixed_points","preserves_orientation","bounded_orbits","semisimple"] _GROUP_NAMES = list(_GROUP_PROPS.keys()) def probe_group(name): """Analytically determined property dict for GROUP-family transforms.""" row = _GROUP_PROPS.get(name) if row is None: return {} return dict(zip(_GROUP_KEYS, row)) # Inline validation — same discipline as probe_validation.py assert probe_group("LorentzTransform")["preserves_orientation"] == True, "GROUP FAILED ground truth: Lorentz must preserve orientation" assert probe_group("AffineTransform")["preserves_distances"] == False, "GROUP FAILED negative control: Affine must not preserve distances" assert (probe_group("MobiusTransform")["preserves_angles"] == True and probe_group("MobiusTransform")["preserves_distances"] == False), "GROUP FAILED consistency: Möbius must be conformal but not isometric" # ═════════════════════════════════════════════════════════════════════════════ # FAMILY 6 — MECH : canonical mechanics transforms # Five transforms: Canonical, Hamiltonian, Lagrangian, Legendre, Bogoliubov. # These act on phase space or configuration space, not on function vectors. # Properties are analytic — verified against Arnold (Mathematical Methods of # Classical Mechanics), Goldstein (Classical Mechanics), and Bogoliubov (1947). # # Properties: # symplectic — preserves the 2-form dp∧dq (hallmark of Hamiltonian mechanics) # involutive — applying twice returns to start (Legendre: yes; Canonical: no) # linear — linear in the new coordinates (Bogoliubov: yes; others: no) # preserves_phase_volume — Liouville: yes for canonical/Hamiltonian, no for Lagrangian # preserves_hessian — preserves the Hessian structure on configuration space # quadratic_dynamics — generates quadratic (harmonic) dynamics on a free system # field_transform — acts on field degrees of freedom (QFT context) # # Validation: # GROUND TRUTH: CanonicalTransform symplectic = True (definition of canonical) # NEG CONTROL: LagrangianTransform symplectic = False (acts on config space, not phase) # CONSISTENCY: LegendreTransform involutive = True (Legendre∘Legendre = identity) # NOVEL CHECK: Canonical~Hamiltonian should be CONFIRMED (Hamiltonian IS canonical) # ═════════════════════════════════════════════════════════════════════════════ _MECH_PROPS = { # name: [symp, inv, lin, vol, hess, quad, fld ] "CanonicalTransform": [True, False, False, True, False, False, False], "HamiltonianTransform": [True, False, False, True, False, False, False], "LagrangianTransform": [False, False, False, False, True, False, False], "LegendreTransform": [False, True, False, False, False, False, False], "BogoliubovTransform": [True, False, True, False, False, True, True ], } _MECH_KEYS = ["symplectic","involutive","linear","preserves_phase_volume", "preserves_hessian","quadratic_dynamics","field_transform"] _MECH_NAMES = list(_MECH_PROPS.keys()) def probe_mech(name): """Analytically determined property dict for MECH-family transforms.""" row = _MECH_PROPS.get(name) if row is None: return {} return dict(zip(_MECH_KEYS, row)) # Inline validation assert probe_mech("CanonicalTransform")["symplectic"] == True, "MECH FAILED ground truth: Canonical must be symplectic" assert probe_mech("LagrangianTransform")["symplectic"] == False, "MECH FAILED negative control: Lagrangian acts on config space, not phase space" assert probe_mech("LegendreTransform")["involutive"] == True, "MECH FAILED consistency: Legendre∘Legendre = identity" # ═════════════════════════════════════════════════════════════════════════════ # FAMILY 7 — PDE : solution operators and scale-flow operators for PDEs # Four transforms: GreenFunction, FundamentalSolution, HubbardStratonovich, # RenormalizationGroup. # Properties are analytic — verified against Evans (Partial Differential # Equations), Zinn-Justin (Quantum Field Theory and Critical Phenomena), # and Wilson & Kogut (The Renormalization Group, Phys Rep 1974). # # Properties: # linear — linear operator (superposition holds) # causal — output depends only on past/source inputs # scale_flow — implements a scale / coarse-graining flow # decays_from_source — output decays away from the source point # path_integral — defined by a functional / path integral # involutive — applying twice returns to start (none here) # field_transform — acts on field configurations # # Validation: # GROUND TRUTH: GreenFunction linear = True (definition — linear PDEs have Green's functions) # NEG CONTROL: HubbardStratonovich linear = False (nonlinear field transformation) # CONSISTENCY: RenormalizationGroup scale_flow = True (definition of the RG) # PRE-COMPUTED: GreenFunction ~ FundamentalSolution expected CONFIRMED (5.43 bits) # — they are the same object in different mathematical traditions # ═════════════════════════════════════════════════════════════════════════════ _PDE_PROPS = { # name: [lin, caus, scale, decay, path, inv, fld ] "GreenFunction": [True, True, False, True, False, False, False], "FundamentalSolution": [True, True, False, True, False, False, False], "HubbardStratonovich": [False, False, False, False, True, False, True ], "RenormalizationGroup": [False, False, True, False, False, False, True ], } _PDE_KEYS = ["linear","causal","scale_flow","decays_from_source", "path_integral","involutive","field_transform"] _PDE_NAMES = list(_PDE_PROPS.keys()) def probe_pde(name): """Analytically determined property dict for PDE-family transforms.""" row = _PDE_PROPS.get(name) if row is None: return {} return dict(zip(_PDE_KEYS, row)) # Inline validation assert probe_pde("GreenFunction")["linear"] == True, "PDE FAILED ground truth: GreenFunction must be linear" assert probe_pde("HubbardStratonovich")["linear"] == False, "PDE FAILED negative control: HubbardStratonovich is not linear" assert probe_pde("RenormalizationGroup")["scale_flow"] == True, "PDE FAILED consistency: RenormalizationGroup defines a scale flow" # MEASURE EVERYTHING # ═════════════════════════════════════════════════════════════════════════════ _SIG = None def signatures(): global _SIG if _SIG is not None: return _SIG S = {} for n,f in _FN1D.items(): try: S[n] = probe_fn1d(f) except Exception as e: S[n] = {"_error": str(e)[:60]} for n,f in _SEQ.items(): try: S[n] = probe_seq(f) except Exception as e: S[n] = {"_error": str(e)[:60]} for n in [k for k,v in TYPE.items() if v=="MATRIX"]: S[n] = probe_matrix(n) for n in [k for k,v in TYPE.items() if v=="PROB"]: S[n] = probe_prob(n) for n in _GROUP_NAMES: S[n] = probe_group(n) for n in _MECH_NAMES: S[n] = probe_mech(n) for n in _PDE_NAMES: S[n] = probe_pde(n) _SIG = S return S def family_stats(): S = signatures(); out = {} for fam in ("FN1D","SEQ","MATRIX","PROB","GROUP","MECH","PDE"): members = [n for n in S if TYPE.get(n)==fam and "_error" not in S[n]] if not members: continue keys = S[members[0]].keys(); st = {} for k in keys: vals = [S[n][k] for n in members if k in S[n]] pt = (sum(vals)+1)/(len(vals)+2) # Laplace-smoothed st[k] = (pt, 1-pt) out[fam] = st return out CONFIRM, WEAK = 4.0, 2.0 def judge(a, b): ta, tb = TYPE.get(a), TYPE.get(b) if ta is None or tb is None: return {"pair":(a,b), "verdict":"UNKNOWN_TRANSFORM"} if ta != tb: br = bridge(ta, tb) if br is None: return {"pair":(a,b), "verdict":"CATEGORY_ERROR", "bits":0.0, "why":f"{a} is a {ta} object, {b} is a {tb} object; no theorem connects them"} return {"pair":(a,b), "verdict":"BRIDGED_UNTESTED", "bits":0.0, "why":br, "note":"real correspondence exists, but cross-family properties are not comparable yet"} S, F = signatures(), family_stats() # A family with no measurable properties (e.g. MATRIX when scipy is absent) # yields empty stats and a zero maximum. Guard it: an empty battery means # "cannot judge", never a division by zero and never a false verdict. if (a not in S or b not in S or not S[a] or not S[b] or "_error" in S[a] or "_error" in S[b] or ta not in F or not F[ta]): return {"pair":(a,b), "verdict":"NOT_TESTABLE", "bits":0.0, "why":f"no usable probe battery for family {ta}" + ("" if SCIPY_AVAILABLE else " (scipy unavailable)")} bits, shared, differ = 0.0, [], [] EXCLUDED = {"conv_onesided"} # measured, but could not reliably reproduce # the Laplace convolution theorem on this grid, # so it is not allowed to influence a verdict for k,(pt,pf) in F[ta].items(): if k in EXCLUDED: continue va, vb = S[a].get(k), S[b].get(k) if va is None or vb is None: continue if va == vb: v = -math.log2(pt if va else pf); bits += v; shared.append((k, va, round(v,2))) else: differ.append(k) mx = sum(-math.log2(min(p,q)) for k,(p,q) in F[ta].items() if k not in EXCLUDED) if mx <= 0: return {"pair":(a,b), "verdict":"NOT_TESTABLE", "bits":0.0, "why":f"probe battery for family {ta} carries no information"} same_all = all(S[a].get(k)==S[b].get(k) for k in F[ta] if k not in EXCLUDED) # An identical signature only MEANS something if the signature is itself # informative. Two transforms that agree only on cheap, common properties # are not deeply alike -- the probe battery is simply too coarse to tell # them apart, and saying so is the honest verdict. if same_all and bits >= CONFIRM: v="IDENTICAL_SIGNATURE" elif same_all: v="INDISTINGUISHABLE_NEEDS_FINER_PROBES" elif bits >= CONFIRM: v="CONFIRMED" elif bits >= WEAK: v="WEAK" else: v="REFUTED" return {"pair":(a,b), "verdict":v, "bits":round(bits,2), "shared":shared, "differ_on":differ, "confidence":round(min(0.95, bits/mx),3)}