mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-31 01:25:21 +00:00
STEP 1 — integer spiral-index packing (EXACT): pack_spiral_index/ unpack_spiral_index with corpus-wide base=2·max|c|+1 and offset-encoded digits, recorded in the codebook JSON header; round-trip verified over all 250 matrices. Fixes the sign bug in integration_sprint.py's integer path (unoffset signed packing collapsed (-1,1) with (1,0) in base 2). STEP 2 — f(n) layout (DECORATIVE): per-entry radius_sq + angle_frac, computed in decimal arithmetic (indices reach ~1e44 >> 2^52); verified against VERIFICATION_LOG V007 f(20121); min angular separation ≈4.64e-6 of a turn reported. STEP 3 — Cartan Δ-floor (--cartan-floor): Δ=17/1792 exact (CartanConnection.lean:70) as Fisher-distance resolution floor on Δ₇; 13 sub-Δ pairs merge 196 fingerprints into 187 Δ-resolution codewords vs 9 gap-rule clusters; emitted alongside, not replacing, the 3×-median rule. Caveat asserted in tests: the |c|/Σ|c| simplex projection is lossy (one corpus pair at Fisher distance 0) — similarity, not identity. STEP 4 — torus-winding saturation fix: TorusWinding gains a_exact/b_exact (plain ℤ, no Q16.16 clamp); torus_to_spiral_index prefers them, making the round trip lossless (regression-tested at n=1e9). BraidEigensolid.lean needs the same widening — noted, Lean untouched. Also corrects charpoly_codebook.py's stale docstring counts (192/180 → 196/182, cross-checked against the exact Faddeev–LeVerrier fingerprints: identical on all 250 matrices). Tests: 43 passed (19 new). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
733 lines
25 KiB
Python
733 lines
25 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
PIST + BRAID BRIDGE — Connecting Sprint Results to Lean Formalism
|
||
===================================================================
|
||
|
||
This module bridges the integration_sprint.py results with the Lean 4
|
||
formal infrastructure:
|
||
- PIST.Spectral (Q16_16 fixed-point spectral analysis)
|
||
- BraidEigensolid (Torus carrier, golden centering, eigensolid)
|
||
- BraidField (PIST operator B/G/A/P, RG flow)
|
||
- BraidSpherionBridge (Cross-mode ↔ eigensolid correspondence)
|
||
|
||
Mappings implemented:
|
||
1. Spectral coefficients → Q16_16 → PIST SpectralProfile
|
||
2. Spiral index → TorusWinding (a, b) on T²
|
||
3. 4-mode receipt → PIST field (B, G, A, P)
|
||
4. Cross-mode agreement → Eigensolid convergence check
|
||
5. Φ-corkscrew ↔ Golden centering (φ⁻¹ = 40560/65536)
|
||
|
||
Author: SilverSight Integration Layer
|
||
"""
|
||
|
||
import json
|
||
import math
|
||
import struct
|
||
from typing import Dict, List, Tuple, Optional
|
||
from dataclasses import dataclass, asdict
|
||
|
||
import numpy as np
|
||
|
||
# ========================================================================
|
||
# §1. Q16_16 FIXED-POINT ARITHMETIC (matches Lean SilverSight.FixedPoint)
|
||
# ========================================================================
|
||
|
||
Q16_SCALE = 65536 # 2^16
|
||
Q16_MAX_RAW = 2147483647 # 2^31 - 1
|
||
Q16_MIN_RAW = -2147483648 # -2^31
|
||
|
||
|
||
def q16_clamp(x: int) -> int:
|
||
"""Saturating clamp to Q16_16 range."""
|
||
if x > Q16_MAX_RAW:
|
||
return Q16_MAX_RAW
|
||
if x < Q16_MIN_RAW:
|
||
return Q16_MIN_RAW
|
||
return x
|
||
|
||
|
||
def float_to_q16(x: float) -> int:
|
||
"""Convert float to Q16_16 raw value."""
|
||
return q16_clamp(int(round(x * Q16_SCALE)))
|
||
|
||
|
||
def q16_to_float(raw: int) -> float:
|
||
"""Convert Q16_16 raw value to float."""
|
||
return raw / Q16_SCALE
|
||
|
||
|
||
def q16_add(a: int, b: int) -> int:
|
||
return q16_clamp(a + b)
|
||
|
||
|
||
def q16_sub(a: int, b: int) -> int:
|
||
return q16_clamp(a - b)
|
||
|
||
|
||
def q16_mul(a: int, b: int) -> int:
|
||
"""Multiply two Q16_16 values, keeping Q16_16 precision."""
|
||
return q16_clamp((a * b) // Q16_SCALE)
|
||
|
||
|
||
def q16_div(a: int, b: int) -> int:
|
||
"""Divide two Q16_16 values."""
|
||
if b == 0:
|
||
return Q16_MAX_RAW
|
||
return q16_clamp((a * Q16_SCALE) // b)
|
||
|
||
|
||
def q16_sqrt(raw: int) -> int:
|
||
"""Integer square root of Q16_16 value. Returns floor(√x) in Q16_16."""
|
||
if raw <= 0:
|
||
return 0
|
||
# √x in Q16_16 = √(x / 65536) * 65536 = √(x * 65536)
|
||
val = raw if raw >= 0 else 0
|
||
return int(math.isqrt(val * Q16_SCALE))
|
||
|
||
|
||
# Golden centering constant: φ⁻¹ ≈ 0.618033988...
|
||
# In Lean: Q16_16.ofRawInt 40560
|
||
# 40560 / 65536 = 0.618896484375
|
||
PHI_INV_Q16 = 40560
|
||
PHI = (1.0 + 5.0 ** 0.5) / 2.0
|
||
PSI = 2.0 * math.pi / (PHI ** 2)
|
||
|
||
|
||
# ========================================================================
|
||
# §2. PIST.SPECTRAL BRIDGE
|
||
# ========================================================================
|
||
|
||
@dataclass
|
||
class PISTSpectralProfile:
|
||
"""Python mirror of SilverSight.PIST.Spectral.SpectralProfile."""
|
||
matrix_size: int # Q16_16 raw
|
||
rank: int # Q16_16 raw
|
||
spectral_gap: int # Q16_16 raw
|
||
density: int # Q16_16 raw
|
||
trace_val: int # Q16_16 raw
|
||
frobenius_norm: int # Q16_16 raw
|
||
laplacian_zero_count: int # Q16_16 raw
|
||
adjacency_eigenvalue_max: int # Q16_16 raw
|
||
laplacian_eigenvalue_max: int # Q16_16 raw
|
||
singular_value_max: int # Q16_16 raw
|
||
|
||
def to_float_dict(self) -> Dict[str, float]:
|
||
return {
|
||
"matrix_size": q16_to_float(self.matrix_size),
|
||
"rank": q16_to_float(self.rank),
|
||
"spectral_gap": q16_to_float(self.spectral_gap),
|
||
"density": q16_to_float(self.density),
|
||
"trace_val": q16_to_float(self.trace_val),
|
||
"frobenius_norm": q16_to_float(self.frobenius_norm),
|
||
"laplacian_zero_count": q16_to_float(self.laplacian_zero_count),
|
||
"adjacency_eigenvalue_max": q16_to_float(self.adjacency_eigenvalue_max),
|
||
"laplacian_eigenvalue_max": q16_to_float(self.laplacian_eigenvalue_max),
|
||
"singular_value_max": q16_to_float(self.singular_value_max),
|
||
}
|
||
|
||
|
||
def power_iteration_q16(mat: List[List[int]], max_iter: int = 100,
|
||
detect_convergence: bool = True) -> Tuple[int, bool]:
|
||
"""Dominant eigenvalue via power iteration in Q16_16.
|
||
|
||
Matches: SilverSight.PIST.Spectral.powerIteration
|
||
|
||
Returns (eigenvalue_q16, converged) where converged=False indicates
|
||
the iteration may have failed (peripheral spectrum, oscillation).
|
||
|
||
Known failure mode: matrices with eigenvalues on the unit circle at
|
||
60° angles cause power iteration to oscillate. For these matrices,
|
||
use exact_eigenvalue_q16() instead.
|
||
"""
|
||
n = len(mat)
|
||
if n == 0:
|
||
return 0, True
|
||
|
||
init_val = Q16_SCALE // n
|
||
v = [init_val] * n
|
||
prev_lam = 0
|
||
oscillation_count = 0
|
||
|
||
for iteration in range(max_iter):
|
||
# Matrix-vector multiply
|
||
mv = [0] * n
|
||
for i in range(n):
|
||
s = 0
|
||
for j in range(n):
|
||
s += mat[i][j] * (v[j] if j < len(v) else 0)
|
||
mv[i] = s # Keep in raw integer space
|
||
|
||
# Norm squared
|
||
nm2 = sum(x * x for x in mv)
|
||
if nm2 <= 0:
|
||
break
|
||
|
||
nm = int(math.isqrt(nm2))
|
||
if nm == 0:
|
||
break
|
||
|
||
# Normalize
|
||
v = [q16_clamp((x * Q16_SCALE) // nm) for x in mv]
|
||
|
||
# Convergence check: Rayleigh quotient should stabilize
|
||
if detect_convergence and iteration > 10:
|
||
mv_check = [0] * n
|
||
for i in range(n):
|
||
s = 0
|
||
for j in range(n):
|
||
s += mat[i][j] * v[j]
|
||
mv_check[i] = s
|
||
num = sum(v[i] * mv_check[i] for i in range(n))
|
||
den = sum(x * x for x in v)
|
||
if den > 0:
|
||
lam = (num * Q16_SCALE) // den
|
||
# Check for oscillation (Rayleigh quotient bouncing between values)
|
||
if abs(lam - prev_lam) < 100: # Converged
|
||
pass
|
||
elif iteration > 20 and abs(lam - prev_lam) > Q16_SCALE // 10:
|
||
oscillation_count += 1
|
||
prev_lam = lam
|
||
|
||
# Rayleigh quotient: v^T A v / v^T v
|
||
mv = [0] * n
|
||
for i in range(n):
|
||
s = 0
|
||
for j in range(n):
|
||
s += mat[i][j] * (v[j] if j < len(v) else 0)
|
||
mv[i] = s
|
||
|
||
num = sum(v[i] * mv[i] for i in range(n))
|
||
den = sum(x * x for x in v)
|
||
if den <= 0:
|
||
return 0, True
|
||
|
||
result = q16_clamp((num * Q16_SCALE) // den)
|
||
converged = oscillation_count < 3
|
||
return result, converged
|
||
|
||
|
||
def exact_eigenvalue_q16(mat: List[List[int]]) -> int:
|
||
"""Exact dominant eigenvalue via numpy (characteristic polynomial).
|
||
|
||
Use this as fallback when power_iteration_q16 reports non-convergence.
|
||
Returns Q16_16 raw value.
|
||
|
||
This is NOT a drop-in replacement for the Lean powerIteration —
|
||
it uses float64 internally. But it's exact for integer matrices
|
||
whose eigenvalues are representable in float64.
|
||
"""
|
||
try:
|
||
import numpy as np
|
||
np_mat = np.array(mat, dtype=float)
|
||
evals = np.linalg.eigvals(np_mat)
|
||
spectral_radius = float(max(abs(evals)))
|
||
return q16_clamp(int(spectral_radius * Q16_SCALE))
|
||
except Exception:
|
||
return 0
|
||
|
||
|
||
def compute_pist_spectral(eigenvalues: np.ndarray) -> PISTSpectralProfile:
|
||
"""Compute PIST spectral profile from eigenvalues (float → Q16_16).
|
||
|
||
Mirrors: SilverSight.PIST.Spectral.computeSpectral
|
||
"""
|
||
if len(eigenvalues) == 0:
|
||
return PISTSpectralProfile(*([0] * 10))
|
||
|
||
k = min(8, len(eigenvalues))
|
||
evals = np.sort(eigenvalues)[::-1][:k]
|
||
|
||
# Build 8x8 symmetric matrix from eigenvalues (diagonalization approximation)
|
||
n = 8
|
||
mat = [[0] * n for _ in range(n)]
|
||
for i in range(min(len(evals), n)):
|
||
val = float_to_q16(float(evals[i]))
|
||
mat[i][i] = val
|
||
# Add some off-diagonal coupling for realism
|
||
if i + 1 < n:
|
||
coupling = float_to_q16(float(evals[i]) * 0.1)
|
||
mat[i][i + 1] = coupling
|
||
mat[i + 1][i] = coupling
|
||
|
||
# Symmetrize
|
||
sym = [[(mat[i][j] + mat[j][i]) // 2 for j in range(n)] for i in range(n)]
|
||
|
||
# Laplacian
|
||
lap = [[0] * n for _ in range(n)]
|
||
for i in range(n):
|
||
deg = sum(sym[i])
|
||
for j in range(n):
|
||
lap[i][j] = deg if i == j else -sym[i][j]
|
||
|
||
ev_max, converged = power_iteration_q16(sym)
|
||
if not converged:
|
||
# Fallback to exact eigenvalue computation
|
||
ev_max = exact_eigenvalue_q16(sym)
|
||
|
||
# Shift-deflation for second eigenvalue
|
||
shift = (ev_max * 58982) // Q16_SCALE # 0.9 * ev_max
|
||
shifted = [[sym[i][j] for j in range(n)] for i in range(n)]
|
||
for i in range(n):
|
||
shifted[i][i] = q16_sub(shifted[i][i], shift)
|
||
ev_shift, converged2 = power_iteration_q16(shifted)
|
||
if not converged2:
|
||
ev_shift = exact_eigenvalue_q16(shifted)
|
||
ev_second = q16_sub(ev_max, ev_shift) if ev_shift < ev_max else ev_max
|
||
spectral_gap = q16_sub(ev_max, ev_second)
|
||
|
||
lap_max, converged3 = power_iteration_q16(lap)
|
||
if not converged3:
|
||
lap_max = exact_eigenvalue_q16(lap)
|
||
|
||
# Density
|
||
total = sum(sum(row) for row in mat)
|
||
density = q16_clamp((total * Q16_SCALE) // (n * n)) if n > 0 else 0
|
||
|
||
# Trace
|
||
trace_val = sum(mat[i][i] for i in range(n))
|
||
|
||
# Frobenius norm
|
||
frob_sq = sum(sum(x * x for x in row) for row in mat)
|
||
frob_norm = int(math.isqrt(frob_sq))
|
||
|
||
# Rank (count non-zero rows)
|
||
rank = sum(1 for row in mat if any(x != 0 for x in row))
|
||
|
||
# Laplacian zero count
|
||
lap_zero = sum(1 for i in range(n) if sum(mat[i]) - mat[i][i] == 0)
|
||
|
||
# ATA max singular value
|
||
ata = [[0] * n for _ in range(n)]
|
||
for i in range(n):
|
||
for j in range(n):
|
||
s = 0
|
||
for k_idx in range(n):
|
||
s += mat[k_idx][i] * mat[k_idx][j]
|
||
ata[i][j] = s
|
||
ata_ev, converged4 = power_iteration_q16(ata)
|
||
if not converged4:
|
||
ata_ev = exact_eigenvalue_q16(ata)
|
||
sv_max = q16_sqrt(ata_ev)
|
||
|
||
return PISTSpectralProfile(
|
||
matrix_size=float_to_q16(n),
|
||
rank=float_to_q16(rank),
|
||
spectral_gap=spectral_gap,
|
||
density=density,
|
||
trace_val=float_to_q16(trace_val),
|
||
frobenius_norm=float_to_q16(frob_norm),
|
||
laplacian_zero_count=float_to_q16(lap_zero),
|
||
adjacency_eigenvalue_max=ev_max,
|
||
laplacian_eigenvalue_max=lap_max,
|
||
singular_value_max=sv_max,
|
||
)
|
||
|
||
|
||
# ========================================================================
|
||
# §3. TORUS WINDING ↔ Φ-CORKSCREW
|
||
# ========================================================================
|
||
|
||
@dataclass
|
||
class TorusWinding:
|
||
"""Torus winding counts: H₁(T²; Z) = Z⟨a⟩ ⊕ Z⟨b⟩.
|
||
|
||
Matches: SilverSight.BraidEigensolid.TorusWinding
|
||
a = spatial winding (latitude cycle)
|
||
b = phase/torsion winding (longitude cycle)
|
||
|
||
The Q16_16 raws are LOSSY above value 32767 (Q16_MAX_RAW clamp);
|
||
a_exact/b_exact carry the plain-ℤ winding with no clamp and are the
|
||
authoritative values when present. BraidEigensolid.lean's
|
||
TorusWinding needs the same widening (Int fields alongside the
|
||
Q16_16 raws) before this exact layer can be mirrored formally.
|
||
"""
|
||
a: int # Q16_16 raw — saturates for values > 32767
|
||
b: int # Q16_16 raw — saturates for values > 32767
|
||
a_exact: Optional[int] = None # plain ℤ winding, no clamp
|
||
b_exact: Optional[int] = None # plain ℤ winding, no clamp
|
||
|
||
def to_float(self) -> Tuple[float, float]:
|
||
return q16_to_float(self.a), q16_to_float(self.b)
|
||
|
||
|
||
def spiral_to_torus_winding(spiral_index: int) -> TorusWinding:
|
||
"""Map spiral index to torus winding counts.
|
||
|
||
The golden spiral f(n) = (√n·cos(nψ), √n·sin(nψ)) with ψ = 2π/φ²
|
||
lives on a torus because ψ/2π = 1/φ² is irrational.
|
||
|
||
Winding counts:
|
||
a = spiral_index mod φ_step (spatial winding)
|
||
b = spiral_index // φ_step (phase winding)
|
||
|
||
where φ_step = round(φ) = 2 (since φ ≈ 1.618)
|
||
|
||
⚠️ SATURATION WARNING: b_raw uses Q16.16 encoding, which clamps at
|
||
Q16_MAX_RAW / 65536 ≈ 32767.99. For spiral_index > 65535, the
|
||
phase winding b silently saturates. The a_exact/b_exact fields carry
|
||
the unclamped integers; torus_to_spiral_index prefers them, so the
|
||
round trip is exact for every spiral_index.
|
||
|
||
This mirrors: TorusWinding in BraidEigensolid.lean
|
||
"""
|
||
phi_step = int(round(PHI)) # 2
|
||
a_val = spiral_index % phi_step
|
||
b_val = spiral_index // phi_step
|
||
a_raw = float_to_q16(float(a_val))
|
||
b_raw = float_to_q16(float(b_val))
|
||
return TorusWinding(a=a_raw, b=b_raw, a_exact=a_val, b_exact=b_val)
|
||
|
||
|
||
def spiral_to_torus_winding_safe(spiral_index: int) -> Tuple[TorusWinding, bool]:
|
||
"""Map spiral index to torus winding with saturation detection.
|
||
|
||
Returns (winding, saturated) where saturated=True if the Q16.16
|
||
encoding cannot represent the phase winding losslessly.
|
||
|
||
For indices > 65535, the caller should use the raw integer
|
||
spiral_index directly instead of the torus winding.
|
||
"""
|
||
phi_step = int(round(PHI)) # 2
|
||
a_val = spiral_index % phi_step
|
||
b_val = spiral_index // phi_step
|
||
max_q16_val = Q16_MAX_RAW // 65536 # ≈ 32767
|
||
saturated = b_val > max_q16_val
|
||
a_raw = float_to_q16(float(a_val))
|
||
b_raw = float_to_q16(float(b_val))
|
||
return TorusWinding(a=a_raw, b=b_raw, a_exact=a_val, b_exact=b_val), saturated
|
||
|
||
|
||
def torus_to_spiral_index(w: TorusWinding) -> int:
|
||
"""Inverse: recover spiral index from torus winding.
|
||
|
||
n = φ_step · b + a
|
||
|
||
Prefers the exact ℤ fields when present (lossless for all n);
|
||
falls back to the Q16.16 raws, which saturate for
|
||
spiral_index > 65535 — use spiral_to_torus_winding_safe() to
|
||
detect that case on legacy windings without exact fields.
|
||
"""
|
||
phi_step = int(round(PHI))
|
||
if w.a_exact is not None and w.b_exact is not None:
|
||
return phi_step * w.b_exact + w.a_exact
|
||
b_int = int(round(q16_to_float(w.b)))
|
||
a_int = int(round(q16_to_float(w.a)))
|
||
return phi_step * b_int + a_int
|
||
|
||
|
||
# ========================================================================
|
||
# §4. PIST FIELD ↔ 4-MODE SPRINT RECEIPT
|
||
# ========================================================================
|
||
|
||
@dataclass
|
||
class PISTField:
|
||
"""PIST operator: q_{t+1} = PIST(q_t; B, G, A, P).
|
||
|
||
Matches: SilverSight.BraidField.PISTField
|
||
B = Burden (load, cost, attention)
|
||
G = Geometry (basins, manifolds, gradients)
|
||
A = Adaptation (sorting rate, pacing, convergence)
|
||
P = Protection (compression, thresholding, overload)
|
||
"""
|
||
burden: int # Q16_16 raw
|
||
geometry: int # Q16_16 raw
|
||
adaptation: int # Q16_16 raw
|
||
protection: int # Q16_16 raw
|
||
|
||
def to_float_dict(self) -> Dict[str, float]:
|
||
return {
|
||
"burden": q16_to_float(self.burden),
|
||
"geometry": q16_to_float(self.geometry),
|
||
"adaptation": q16_to_float(self.adaptation),
|
||
"protection": q16_to_float(self.protection),
|
||
}
|
||
|
||
|
||
def sprint_receipt_to_pist(result: Dict) -> PISTField:
|
||
"""Convert a single sprint mode result to PIST field.
|
||
|
||
B = execution_time_ms (how expensive was this mode?)
|
||
G = dominant_eigenvalue + spectral_gap (what did we learn about the graph?)
|
||
A = checks_passed / checks_total (how well did we adapt?)
|
||
P = 1.0 if checks_passed == checks_total else 0.0 (did we protect against errors?)
|
||
"""
|
||
B = float_to_q16(result.get("executionTimeMs", 0.0) / 100.0)
|
||
|
||
geom = result.get("dominantEigenvalue", 0.0) + result.get("spectralGap", 0.0)
|
||
G = float_to_q16(geom / 10.0)
|
||
|
||
checks_total = result.get("checks_total", 7)
|
||
checks_passed = result.get("checks_passed", 7)
|
||
A = float_to_q16(checks_passed / checks_total if checks_total > 0 else 0.0)
|
||
|
||
P = Q16_SCALE if checks_passed == checks_total else Q16_SCALE // 2
|
||
|
||
return PISTField(burden=B, geometry=G, adaptation=A, protection=P)
|
||
|
||
|
||
def compare_pist_fields(p1: PISTField, p2: PISTField, tolerance: float = 0.05) -> bool:
|
||
"""Check if two PIST fields agree within Q16_16 tolerance."""
|
||
for field in ["burden", "geometry", "adaptation", "protection"]:
|
||
v1 = q16_to_float(getattr(p1, field))
|
||
v2 = q16_to_float(getattr(p2, field))
|
||
if abs(v1 - v2) > tolerance:
|
||
return False
|
||
return True
|
||
|
||
|
||
# ========================================================================
|
||
# §5. EIGENSOLID CONVERGENCE CHECK
|
||
# ========================================================================
|
||
|
||
def check_eigensolid_convergence(results: List[Dict]) -> Dict:
|
||
"""Verify that all modes converge to the same eigensolid.
|
||
|
||
Theorem analog: SilverSight.BraidEigensolid.eigensolid_convergence
|
||
|
||
All modes should produce:
|
||
- Same dominant eigenvalue (within numerical tolerance)
|
||
- Same spiral index (exact agreement)
|
||
- Same DNA sequence (exact agreement)
|
||
- Same PIST field (within Q16_16 tolerance)
|
||
"""
|
||
if len(results) < 2:
|
||
return {"converged": False, "reason": "need_at_least_2_modes"}
|
||
|
||
# Check exact agreement on discrete invariants
|
||
spirals = [r.get("spiral_index") for r in results]
|
||
dnas = [r.get("dnaSequence") for r in results]
|
||
|
||
spiral_agree = len(set(spirals)) == 1
|
||
dna_agree = len(set(dnas)) == 1
|
||
|
||
# Check approximate agreement on continuous invariants
|
||
lambdas = [r.get("dominantEigenvalue", 0.0) for r in results]
|
||
lambda_cv = np.std(lambdas) / np.mean(lambdas) if np.mean(lambdas) > 0 else 0
|
||
|
||
gaps = [r.get("spectralGap", 0.0) for r in results]
|
||
gap_cv = np.std(gaps) / np.mean(gaps) if np.mean(gaps) > 0 else 0
|
||
|
||
# PIST field agreement
|
||
pist_fields = [sprint_receipt_to_pist(r) for r in results]
|
||
pist_agree = all(
|
||
compare_pist_fields(pist_fields[0], pf) for pf in pist_fields[1:]
|
||
)
|
||
|
||
converged = spiral_agree and dna_agree and lambda_cv < 0.01 and gap_cv < 0.01 and pist_agree
|
||
|
||
return {
|
||
"converged": converged,
|
||
"spiral_agree": spiral_agree,
|
||
"dna_agree": dna_agree,
|
||
"lambda_cv": float(lambda_cv),
|
||
"gap_cv": float(gap_cv),
|
||
"pist_agree": pist_agree,
|
||
"n_modes": len(results),
|
||
"pist_fields": [pf.to_float_dict() for pf in pist_fields],
|
||
}
|
||
|
||
|
||
# ========================================================================
|
||
# §6. GOLDEN CENTERING ↔ Φ-CORKSCREW
|
||
# ========================================================================
|
||
|
||
def golden_centering_compress(q16_val: int) -> int:
|
||
"""Apply golden centering contraction: x → φ⁻¹ · x.
|
||
|
||
Matches: goldenCentering in BraidEigensolid.lean
|
||
Uses the fixed-point constant 40560 = φ⁻¹ in Q16_16.
|
||
|
||
This is the compressor's contraction envelope — it keeps all crossing
|
||
weights in the Q0_2 range [0, 16384] after finite iteration.
|
||
"""
|
||
return q16_mul(q16_val, PHI_INV_Q16)
|
||
|
||
|
||
def phi_corkscrew_to_q16(spiral_index: int, n_coeffs: int = 9) -> List[int]:
|
||
"""Convert spiral index to Q16_16 spectral coefficients.
|
||
|
||
The Φ-corkscrew packs spectral info into a single integer.
|
||
Unpack: recover coefficients via base-φ decomposition.
|
||
"""
|
||
coeffs = []
|
||
n = spiral_index
|
||
for i in range(n_coeffs):
|
||
digit = n % 8 # Hachimoji base-8
|
||
coeffs.append(float_to_q16(digit / 8.0))
|
||
n //= 8
|
||
return coeffs
|
||
|
||
|
||
def q16_to_phi_corkscrew(coeffs: List[int]) -> int:
|
||
"""Pack Q16_16 spectral coefficients into spiral index (inverse)."""
|
||
spiral = 0
|
||
for i, c in enumerate(coeffs):
|
||
digit = int(round(q16_to_float(c) * 8)) % 8
|
||
spiral += digit * (8 ** i)
|
||
return spiral
|
||
|
||
|
||
# ========================================================================
|
||
# §7. OCTAGONAL NORM ↔ FISHER-RAO BOUND
|
||
# ========================================================================
|
||
|
||
def octagonal_norm(x: float, y: float) -> float:
|
||
"""Octagonal norm: κ ≈ max(|x|,|y|) + 3/8·min(|x|,|y|).
|
||
|
||
Matches: PhaseVec.normApprox in BraidBracket.lean
|
||
"""
|
||
ax, ay = abs(x), abs(y)
|
||
hi, lo = max(ax, ay), min(ax, ay)
|
||
return hi + (3.0 / 8.0) * lo
|
||
|
||
|
||
def fisher_rao_distance(p: np.ndarray, q: np.ndarray) -> float:
|
||
"""Fisher-Rao distance on probability simplex: arccos(Σ√(pᵢqᵢ))."""
|
||
bc = np.sum(np.sqrt(p * q))
|
||
bc = np.clip(bc, -1.0, 1.0)
|
||
return np.arccos(bc)
|
||
|
||
|
||
def octagonal_fisher_bound(braid_state_8d: np.ndarray) -> float:
|
||
"""Show that octagonal norm upper-bounds Fisher-Rao distance.
|
||
|
||
For an 8-strand braid state interpreted as a point on Δ₇,
|
||
the octagonal norm of the phase vector upper-bounds the
|
||
Fisher-Rao distance from the uniform distribution.
|
||
|
||
Returns: ratio octagonal_norm / fisher_rao_distance (should be ≥ 1)
|
||
"""
|
||
# Normalize to probability simplex
|
||
s = braid_state_8d.sum()
|
||
if s <= 0:
|
||
return float('inf')
|
||
p = braid_state_8d / s
|
||
uniform = np.ones(8) / 8.0
|
||
|
||
fisher_dist = fisher_rao_distance(p, uniform)
|
||
|
||
# Octagonal norm on first two coordinates (phase vector)
|
||
x, y = p[0] - 1.0 / 8.0, p[1] - 1.0 / 8.0
|
||
oct_norm = octagonal_norm(x, y)
|
||
|
||
ratio = oct_norm / fisher_dist if fisher_dist > 1e-12 else float('inf')
|
||
return float(ratio)
|
||
|
||
|
||
# ========================================================================
|
||
# §8. MAIN — Load sprint receipt and run full bridge
|
||
# ========================================================================
|
||
|
||
def run_bridge(sprint_receipt_path: str = "sprint_receipt.json") -> Dict:
|
||
"""Load sprint receipt and run all bridge analyses."""
|
||
try:
|
||
with open(sprint_receipt_path, 'r') as f:
|
||
receipt = json.load(f)
|
||
except FileNotFoundError:
|
||
return {"error": f"Receipt not found: {sprint_receipt_path}"}
|
||
|
||
results = receipt.get("results", [])
|
||
if not results:
|
||
return {"error": "No results in receipt"}
|
||
|
||
output = {
|
||
"quimb_backend": receipt.get("quimb_backend", "unknown"),
|
||
"n_modes": len(results),
|
||
"bridge_analyses": {},
|
||
}
|
||
|
||
# 1. PIST Spectral for each mode
|
||
spectral_profiles = []
|
||
for r in results:
|
||
# Create synthetic 8x8 from the eigenvalues
|
||
ev_max = r.get("eigenvalue_max", 1.0)
|
||
ev_min = r.get("eigenvalue_min", 0.0)
|
||
gap = r.get("spectralGap", 0.0)
|
||
# Create a spectrum: dominant, dominant-gap, and the rest
|
||
spectrum = np.array([ev_max, ev_max - gap] + [ev_min] * 6)
|
||
profile = compute_pist_spectral(spectrum)
|
||
spectral_profiles.append(profile)
|
||
|
||
output["bridge_analyses"]["pist_spectral"] = {
|
||
"profiles": [p.to_float_dict() for p in spectral_profiles],
|
||
"mean_gap_q16": q16_to_float(
|
||
sum(p.spectral_gap for p in spectral_profiles) // len(spectral_profiles)
|
||
),
|
||
}
|
||
|
||
# 2. Torus winding for each mode
|
||
torus_windings = []
|
||
for r in results:
|
||
tw = spiral_to_torus_winding(r.get("spiral_index", 0))
|
||
torus_windings.append(tw)
|
||
|
||
output["bridge_analyses"]["torus_winding"] = {
|
||
"windings": [{"a": tw.to_float()[0], "b": tw.to_float()[1]}
|
||
for tw in torus_windings],
|
||
"inverse_check": [
|
||
torus_to_spiral_index(tw) == r.get("spiral_index", 0)
|
||
for tw, r in zip(torus_windings, results)
|
||
],
|
||
}
|
||
|
||
# 3. PIST field for each mode
|
||
pist_fields = [sprint_receipt_to_pist(r) for r in results]
|
||
output["bridge_analyses"]["pist_field"] = {
|
||
"fields": [pf.to_float_dict() for pf in pist_fields],
|
||
"all_agree": all(compare_pist_fields(pist_fields[0], pf)
|
||
for pf in pist_fields[1:]),
|
||
}
|
||
|
||
# 4. Eigensolid convergence check
|
||
output["bridge_analyses"]["eigensolid_convergence"] = \
|
||
check_eigensolid_convergence(results)
|
||
|
||
# 5. Golden centering compression check
|
||
max_eigenvalue_q16 = float_to_q16(
|
||
max(r.get("dominantEigenvalue", 0.0) for r in results)
|
||
)
|
||
compressed = golden_centering_compress(max_eigenvalue_q16)
|
||
output["bridge_analyses"]["golden_centering"] = {
|
||
"original_q16": max_eigenvalue_q16,
|
||
"compressed_q16": compressed,
|
||
"phi_inv": PHI_INV_Q16,
|
||
"phi_inv_float": q16_to_float(PHI_INV_Q16),
|
||
}
|
||
|
||
# 6. Φ-corkscrew ↔ Q16_16 roundtrip
|
||
if results:
|
||
spiral = results[0].get("spiral_index", 0)
|
||
coeffs = phi_corkscrew_to_q16(spiral)
|
||
recovered = q16_to_phi_corkscrew(coeffs)
|
||
output["bridge_analyses"]["phi_corkscrew_roundtrip"] = {
|
||
"original": spiral,
|
||
"recovered": recovered,
|
||
"match": spiral == recovered,
|
||
"n_coeffs": len(coeffs),
|
||
}
|
||
|
||
# Overall verdict
|
||
conv = output["bridge_analyses"]["eigensolid_convergence"]
|
||
pist_agree = output["bridge_analyses"]["pist_field"]["all_agree"]
|
||
corkscrew_ok = output["bridge_analyses"]["phi_corkscrew_roundtrip"]["match"]
|
||
output["bridge_verdict"] = {
|
||
"all_checks_pass": conv.get("converged", False) and pist_agree and corkscrew_ok,
|
||
"eigensolid_converged": conv.get("converged", False),
|
||
"pist_fields_agree": pist_agree,
|
||
"corkscrew_roundtrip_ok": corkscrew_ok,
|
||
"formal_backing": [
|
||
"BraidEigensolid.eigensolid_convergence",
|
||
"BraidEigensolid.receipt_invertible",
|
||
"BraidSpherionBridge.receipt_correspondence",
|
||
"BraidSpherionBridge.braidCross_merge_correspondence",
|
||
],
|
||
}
|
||
|
||
return output
|
||
|
||
|
||
if __name__ == "__main__":
|
||
import os
|
||
receipt_path = os.path.join(os.path.dirname(__file__), "sprint_receipt.json")
|
||
result = run_bridge(receipt_path)
|
||
print(json.dumps(result, indent=2, default=str))
|