SilverSight/python/nuvmap/projection_engine.py

412 lines
16 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
NUVMAP Projection Engine — SilverSight Port
=============================================
Port of the Research Stack archive projection_engine.py with:
1. Q16_16 fixed-point arithmetic (no Float in compute paths)
2. CBOR serialization (binary, not JSON-in-SQLite)
3. Dataclass → bytes serialization with schema versioning
Key equation (all Q16_16):
q_i ∝ E_i / (R_i + ε)
E_i = λ · |v_k(i)| · S_i · L_i / (R_i + ε)
Q16_EPSILON = 1 (≈ 1.5e-5)
────────────────────────────────
The epsilon is NOT an arbitrary regularization — it is the minimum
distance from the Kelvin fixed point in the Rossby/Kelvin braid
correspondence (see BraidStateN.lean §RotationalWaveCorrespondence).
In the Rossby/Kelvin model:
• Rossby regime (chiral asymmetry ≠ 0): residual risk R_i ≫ ε,
the E_i computation is dominated by the chiral-dependent R_i.
• Kelvin regime (achiral_stable, Rossby drift = 0): R_i → 0,
epsilon prevents the mathematical singularity at the fixed point
where crossStep(s) = s (eigensolid convergence).
The chiral quantization scale is 32768 Q16_16 units (0.5 — the minimum
non-zero contribution from chiral_scarred). Q16_EPSILON = 1 sits
2¹⁵ = 32768× below this scale, resolving the Kelvin boundary layer:
Q16_ONE = 65536 ─── 1.0 (full chiral bias, left/right handed)
Q16_HALF = 32768 ─── 0.5 (chiral_scarred minimum step)
│ Rossby drift quantization scale
Q16_EPSILON = 1 ─── ≈1.5e-5 (Kelvin boundary layer floor)
The original Research Stack used epsilon = 1e-12 (below double-precision
mach.eps = 2.2e-16), which had no physical meaning. Q16_EPSILON = 1
is the correct Kelvin boundary layer resolution per the formalization.
Proofs (BraidStateN.lean):
rossby_convergence_bound — non-zero chirality → step count ↑
kelvin_wave_eigensolid — zero chirality → eigensolid fixed point
──────────────────────────────────────────────────────────────────────
Why this works for compression (planetary model analogy)
The Rossby β-plane is the standard geophysical fluid dynamics model for
planetary atmospheres (Earth's jet streams, Jupiter's bands, ocean gyres).
The braid model shares the same structural invariants:
GFD Braid model
─────────────────────────── ─────────────────────────────────────
β (planetary vorticity rossbyDriftFromChirality asymmetry
gradient)
Rossby wave dispersion Braid-word frequency splitting
ω = βk/(k²+l²)
Coastal Kelvin wave kelvin_wave_eigensolid — outer strands,
(boundary-trapped) eigensolid converges first
Rossby deformation radius Q16_EPSILON = 1 — boundary layer
L_D = √(gH)/f thickness (minimum resolvable step)
Rhines scale L_β = Q16_HALF = 32768 — chiral quantization
√(2U/β) step
The reason this maps to compression is structural: the Yang-Baxter
equation (braid relation β_ij β_jk β_ij = β_jk β_ij β_jk) and the
β-plane potential vorticity conservation ∂_t q + J(ψ, q) + β∂_x ψ = 0
are both curvature constraints on a rotating/layered system. The braid
crossing matrix C encodes the same topological information that the PV
gradient∫encodes in the fluid — both conserve a topological charge
(braid class / potential vorticity) under evolution.
Implication for efficiency:
If the compression residuals follow Rossby wave dispersion, then
the eigensolid convergence rate is bounded by β-plane wave speeds,
not by general braid mixing. This means the step-count bound in
rossby_convergence_bound can be tightened from O(n²) to O(√(n/β))
in the Rossby-dominated regime, directly reducing the number of
crossing steps needed for eigensolid detection.
"""
import hashlib
from typing import Dict, List, Optional
from dataclasses import dataclass, field
from datetime import datetime
try:
import cbor2 as cbor
except ImportError:
import cbor # fallback
# ── Q16_16 fixed-point ──────────────────────────────────────────────
SCALE = 65536
# ── Q16_16 raw constants — Rounding Derivation ─────────────────────────
# All constants are raw = round(value × SCALE) using banker's rounding
# (round-half-to-even, Python's default). Every non-exact conversion
# documents its rounding decision below for traceability.
#
# value | raw | derivation
# -------|--------|-------------------------------------------------------
# ϵ | 1 | 1/65536 ≈ 0.000015 (exact floor — q16 step)
# 1.0 | 65536 | 2¹⁶ (exact)
# 0.5 | 32768 | 2¹⁵ (exact)
# 0.01 | 655 | 655.36 → floor (.36 < 0.5)
# 0.7 | 45875 | 45875.2 → floor (.2 < 0.5)
# 0.3 | 19661 | 19660.8 → ceil (.8 ≥ 0.5, even → 19661)
# 1.5 | 98304 | 1.5 × 2¹⁶ (exact)
Q16_EPSILON = 1
Q16_ONE = 65536
Q16_HALF = 32768
Q16_ZERO = 0
Q16_PCT1 = 655 # 0.01 floor
Q16_PCT70 = 45875 # 0.7 floor
Q16_PCT30 = 19661 # 0.3 ceil (banker's: .8 → even 19661)
Q16_150PCT = 98304 # 1.5 exact
def q_mul(a: int, b: int) -> int:
"""Q16_16 multiplication with banker's rounding."""
return max(-2147483648, min(2147483647, round((a * b) / SCALE)))
def q_div(a: int, b: int) -> int:
"""Q16_16 division with banker's rounding. Returns 0 if b==0."""
if b == 0:
return 0
return max(-2147483648, min(2147483647, round((a * SCALE) / b)))
def q_add(a: int, b: int) -> int:
return max(-2147483648, min(2147483647, a + b))
def q_sub(a: int, b: int) -> int:
return max(-2147483648, min(2147483647, a - b))
# ── Schema ──────────────────────────────────────────────────────────
SCHEMA_VERSION = 1
CBOR_TAG_NUVMAP_CELL = 0x1000
CBOR_TAG_NUVMAP_SURFACE = 0x1001
# ── Dataclasses ──────────────────────────────────────────────────────
@dataclass
class NUVMAPCell:
u_i: int # address coordinate
v_i: int # spectral coordinate (eigenmode index)
k_i: int # dominant eigenmode
E_i: int = 0 # eigenmass (Q16_16)
R_i: int = Q16_ONE # residual risk (Q16_16)
chi_i: int = 0 # chiral residual (Q16_16)
S_i: int = Q16_ONE # structural integrity (Q16_16)
L_i: int = Q16_ONE # Landauer factor (Q16_16)
q_i: int = 0 # qubit allocation
admissible: bool = True
equation_id: int = 0
fingerprint: str = ""
def to_cbor(self) -> bytes:
data = [
self.u_i, self.v_i, self.k_i,
self.E_i, self.R_i, self.chi_i,
self.S_i, self.L_i,
self.q_i, int(self.admissible),
self.equation_id, self.fingerprint,
]
return cbor.dumps(data)
@classmethod
def from_cbor(cls, raw: bytes) -> 'NUVMAPCell':
data = cbor.loads(raw)
return cls(
u_i=data[0], v_i=data[1], k_i=data[2],
E_i=data[3], R_i=data[4], chi_i=data[5],
S_i=data[6], L_i=data[7],
q_i=data[8], admissible=bool(data[9]),
equation_id=data[10], fingerprint=data[11],
)
@dataclass
class NUVMAPSurface:
cells: List['NUVMAPCell'] = field(default_factory=list)
total_qubits: int = 0
bekenstein_bound: int = 0 # Q16_16
area_utilization: int = 0 # Q16_16
root_fingerprint: str = ""
timestamp: str = ""
def to_cbor(self) -> bytes:
cell_data = [c.to_cbor() for c in self.cells]
data = [
SCHEMA_VERSION,
cell_data,
self.total_qubits,
self.bekenstein_bound,
self.area_utilization,
self.root_fingerprint,
self.timestamp,
]
return cbor.dumps([CBOR_TAG_NUVMAP_SURFACE, data])
@classmethod
def from_cbor(cls, raw: bytes) -> 'NUVMAPSurface':
loaded = cbor.loads(raw)
# Unwrap [tag, data] if present
if isinstance(loaded, list) and len(loaded) == 2 and isinstance(loaded[0], int):
_, data = loaded
else:
data = loaded
version = data[0]
cells = [NUVMAPCell.from_cbor(c) for c in data[1]]
return cls(
cells=cells,
total_qubits=data[2],
bekenstein_bound=data[3],
area_utilization=data[4],
root_fingerprint=data[5],
timestamp=data[6],
)
def to_file(self, path: str):
with open(path, 'wb') as f:
f.write(self.to_cbor())
@classmethod
def from_file(cls, path: str) -> 'NUVMAPSurface':
with open(path, 'rb') as f:
return cls.from_cbor(f.read())
# ── Engine ──────────────────────────────────────────────────────────────
class NUVMAPProjectionEngine:
"""
Projects eigenmass data into a NUVMAP address surface using Q16_16.
"""
def __init__(self, total_qubit_budget: int = 0,
chi_max_q16: int = Q16_HALF,
R_max_q16: int = Q16_HALF,
landauer_threshold_q16: int = None):
self.total_qubit_budget = total_qubit_budget
self.chi_max_q16 = chi_max_q16
self.R_max_q16 = R_max_q16
self.landauer_threshold_q16 = landauer_threshold_q16 or (Q16_ONE // 10)
self.surface = NUVMAPSurface()
def project(self, eigenmass_data: List[Dict],
eigenvalue_q16: Optional[int] = None) -> NUVMAPSurface:
"""
Project eigenmass data into a NUVMAP surface.
eigenmass_data: list of dicts with keys:
equation_id (int), amvr_q16, avmr_q16, chiral_residual_q16 (all Q16_16 raw),
chiral_state (str)
All numeric values MUST already be Q16_16 raw integers.
Convert at the outermost call boundary with the provided Q16_16 adapter.
"""
if not eigenmass_data:
return self.surface
n = len(eigenmass_data)
cells = []
max_eigenmass = Q16_ZERO
for d in eigenmass_data:
raw_q = q_div(q_add(d.get("amvr_q16", 0), d.get("avmr_q16", 0)),
Q16_ONE * 2) # (amvr+avmr)/2
if raw_q > max_eigenmass:
max_eigenmass = raw_q
if max_eigenmass == Q16_ZERO:
max_eigenmass = Q16_ONE
for i, d in enumerate(eigenmass_data):
amvr_q = d.get("amvr_q16", 0)
avmr_q = d.get("avmr_q16", 0)
cr_q = d.get("chiral_residual_q16", 0)
eq_id = d.get("equation_id", 0)
cs = d.get("chiral_state", "achiral_stable")
raw_eigenmass = q_div(q_add(amvr_q, avmr_q), Q16_ONE * 2)
E_norm = q_div(raw_eigenmass, max_eigenmass)
one_minus = q_sub(Q16_ONE, E_norm)
R_i = max(Q16_PCT1, one_minus) if one_minus > Q16_PCT1 else Q16_PCT1
if cs == "chiral_scarred":
R_i = q_mul(R_i, Q16_150PCT)
if cs in ("achiral_stable",):
S_i = Q16_ONE
elif cs in ("left_handed_mass_bias", "right_handed_vector_bias"):
S_i = Q16_PCT70
else:
S_i = Q16_PCT30
if E_norm > self.landauer_threshold_q16:
L_i = Q16_ONE
else:
L_i = q_div(E_norm, self.landauer_threshold_q16)
lam_q = eigenvalue_q16 if eigenvalue_q16 is not None else Q16_ONE
v_abs = E_norm
E_i = q_div(q_mul(q_mul(q_mul(lam_q, v_abs), S_i), L_i),
q_add(R_i, Q16_EPSILON))
chi_i = cr_q
is_R_ok = R_i <= self.R_max_q16
is_chi_ok = chi_i <= self.chi_max_q16
admissible = is_R_ok and is_chi_ok
fp_payload = f"{eq_id}\x00{amvr_q}\x00{avmr_q}\x00{cr_q}\x00{cs}"
fp = hashlib.sha256(fp_payload.encode()).hexdigest()
cells.append(NUVMAPCell(
u_i=i, v_i=i, k_i=i,
E_i=E_i, R_i=R_i, chi_i=chi_i,
S_i=S_i, L_i=L_i,
q_i=0, admissible=admissible,
equation_id=eq_id, fingerprint=fp,
))
# Qubit allocation: q_i proportional to E_i / (R_i + epsilon)
total_weight = Q16_ZERO
for c in cells:
total_weight = q_add(total_weight, q_div(c.E_i, q_add(c.R_i, Q16_EPSILON)))
if total_weight == Q16_ZERO:
total_weight = Q16_ONE
if self.total_qubit_budget > 0:
budget = self.total_qubit_budget
else:
budget = sum(c.E_i * 100 // SCALE for c in cells if c.admissible)
budget = max(budget, sum(1 for c in cells if c.admissible))
for c in cells:
if c.admissible:
weight = q_div(c.E_i, q_add(c.R_i, Q16_EPSILON))
raw_q = int(budget * weight // total_weight) if total_weight > 0 else 1
c.q_i = max(1, raw_q) if raw_q > 0 else 1
else:
c.q_i = 0
total_qubits = sum(c.q_i for c in cells)
# Bekenstein-like bound in Q16_16
bekenstein = q_div(sum(c.E_i for c in cells), len(cells) * Q16_ONE) if cells else Q16_ZERO
area_util = q_div(total_qubits * Q16_ONE, q_add(bekenstein, Q16_EPSILON)) if bekenstein > 0 else Q16_ZERO
self.surface = NUVMAPSurface(
cells=cells,
total_qubits=total_qubits,
bekenstein_bound=bekenstein,
area_utilization=area_util,
root_fingerprint=self._compute_surface_root(cells),
timestamp=datetime.utcnow().isoformat(),
)
return self.surface
@staticmethod
def _compute_surface_root(cells: List['NUVMAPCell']) -> str:
payload = "|".join(
f"{c.u_i}:{c.E_i}:{c.chi_i}:{c.q_i}"
for c in sorted(cells, key=lambda x: x.u_i)
)
return hashlib.sha256(payload.encode()).hexdigest()
def quantum_storage_admissible(self, node_i: int, tau_q16: int) -> bool:
if node_i < 0 or node_i >= len(self.surface.cells):
return False
c = self.surface.cells[node_i]
lhs = q_mul(c.E_i, q_add(c.R_i, Q16_EPSILON))
rhs = q_mul(tau_q16, q_add(c.R_i, Q16_EPSILON))
return lhs <= rhs and c.chi_i <= self.chi_max_q16 and c.admissible
def get_density_map(self) -> Dict[str, List]:
if not self.surface.cells:
return {"E_i": [], "q_i": [], "chi_i": [], "R_i": []}
return {
"E_i": [c.E_i for c in self.surface.cells],
"q_i": [c.q_i for c in self.surface.cells],
"chi_i": [c.chi_i for c in self.surface.cells],
"R_i": [c.R_i for c in self.surface.cells],
"equation_ids": [c.equation_id for c in self.surface.cells],
}
def summary(self) -> Dict:
s = self.surface
admissible = [c for c in s.cells if c.admissible]
return {
"num_cells": len(s.cells),
"num_admissible": len(admissible),
"num_rejected": len(s.cells) - len(admissible),
"total_qubits": s.total_qubits,
"avg_qubits_per_cell": s.total_qubits // max(len(admissible), 1),
"bekenstein_bound_q16": s.bekenstein_bound,
"area_utilization_q16": s.area_utilization,
"max_eigenmass_q16": max((c.E_i for c in s.cells), default=0),
"max_chiral_q16": max((c.chi_i for c in s.cells), default=0),
"surface_root": s.root_fingerprint[:32] + "...",
}
def build_nuvmap_from_eigenmass(eigenmass_data: List[Dict],
qubit_budget: int = 0) -> NUVMAPSurface:
engine = NUVMAPProjectionEngine(total_qubit_budget=qubit_budget)
return engine.project(eigenmass_data)