core/core/physics/wave_manifold.py
Shay 0489b6a98a
Some checks failed
lane-shas / verify pinned lane SHAs (pull_request) Has been cancelled
smoke / smoke (-m "not quarantine") (pull_request) Successful in 14m5s
feat(adr-0241): cohesion substrate — vault ABI, reconstruct, I-01…I-05 suite
Land entity-cohesion foundation for ADR-0241 mastery: public VaultStore
get_versor/get_entry ABI (drop private _versors in holographic vault),
resonant_reconstruct + phase_correlation on WaveManifold, cohesion master
plan + Phase 0/serve quarantine suite, fidelity honesty pass, and Gemini
handoff brief for ADR-0242 atlas packing + Fibonacci search.
2026-07-14 14:09:00 -07:00

423 lines
16 KiB
Python
Raw 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.

"""
core/physics/wave_manifold.py
Wave-field substrate for Cl(4,1) (ADR-0241).
Continuous multivector wave fields ψ ∈ ℝ³² under:
* sandwich transport ψ' = R ψ ~R (multivector field path; matches versor_apply)
* left spinor transport ψ' = R ψ (odd-capable / chiral path)
* spectral leakage (metric proj onto resonant modes)
* wave polar analogy (sandwich conjugator)
* unitary amplitude residual + chiral spinor charge readout
Algebra-native only (algebra/*). No scipy-as-truth. No teaching/vault imports.
Off-serving until explicit gates; dual-checked unitary residual.
"""
from __future__ import annotations
from typing import Any, Sequence, Tuple
import numpy as np
from algebra.cga import cga_inner
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse, scalar_part
from algebra.versor import versor_apply, versor_condition, versor_unit_residual
_CLOSURE_TOL = 1e-6
_NEAR_ZERO = 1e-12
_NONSIMPLE_TOL = 1e-6
class WaveSpectralLeakageError(ValueError):
"""Fail-closed spectral leakage (metric-degenerate resonant span).
Mapped to :class:`core.physics.surprise.SurpriseResidualError` at the
surprise boundary so discovery / dual contracts keep a stable error type.
"""
def __init__(self, reason: str, **disclosure: Any) -> None:
self.reason = reason
self.disclosure = dict(disclosure)
super().__init__(f"spectral_leakage refused [{reason}]: {self.disclosure}")
# Unit pseudoscalar I₅ = e1 e2 e3 e4 e5 (central; I² = 1 in Cl(4,1)).
_I5 = np.zeros(N_COMPONENTS, dtype=np.float64)
_I5[31] = 1.0
_I5.setflags(write=False)
def _as_mv(x: np.ndarray, name: str = "ψ") -> np.ndarray:
arr = np.asarray(x, dtype=np.float64)
if arr.shape != (N_COMPONENTS,):
raise ValueError(f"{name} must have shape ({N_COMPONENTS},); got {arr.shape}")
return arr
def _identity() -> np.ndarray:
out = np.zeros(N_COMPONENTS, dtype=np.float64)
out[0] = 1.0
return out
def _strict_close_rotor(V: np.ndarray, *, name: str) -> np.ndarray:
"""Rescale a true versor to unit weight; never seed-fabricate."""
arr = _as_mv(V, name)
product = geometric_product(arr, reverse(arr)).astype(np.float64)
scalar_sq = float(product[0])
residue = product.copy()
residue[0] = 0.0
residue_norm = float(np.linalg.norm(residue))
if residue_norm >= 1e-2 or scalar_sq <= 0.0:
raise ValueError(
f"{name}: input not a versor "
f"(residue_norm={residue_norm:.3e}, scalar_sq={scalar_sq:.3e})"
)
closed = (arr * (1.0 / np.sqrt(scalar_sq))).astype(np.float64)
cond = versor_condition(closed)
if cond >= _CLOSURE_TOL:
raise ValueError(f"{name}: versor_condition={cond:.3e} after close")
return closed
def _require_closed_rotor(R: np.ndarray, *, name: str = "R") -> np.ndarray:
arr = _as_mv(R, name)
cond = versor_condition(arr)
if cond >= _CLOSURE_TOL:
# Attempt strict close only if already a versor (scalar reverse product).
return _strict_close_rotor(arr, name=name)
return arr.astype(np.float64, copy=True)
def _exp_bivector_generator(B: np.ndarray, dt: float) -> np.ndarray:
"""R = exp(B·dt) for a pure (or nearly pure) bivector generator.
Closed form when B² is scalar (simple plane); series fallback otherwise.
Result is construction-closed (versor_condition < 1e-6).
"""
G = _as_mv(B, "B") * float(dt)
G = G.copy()
G[0] = 0.0 # generator is grade ≥ 1; scalar part does not enter exp path
if float(np.linalg.norm(G)) < _NEAR_ZERO:
return _identity()
Gsq = geometric_product(G, G).astype(np.float64)
s = float(Gsq[0])
higher = Gsq.copy()
higher[0] = 0.0
if float(np.linalg.norm(higher)) < _NONSIMPLE_TOL:
out = np.zeros(N_COMPONENTS, dtype=np.float64)
if abs(s) < _NEAR_ZERO:
out[0] = 1.0
out = out + G
elif s < 0.0:
mag = float(np.sqrt(-s))
out[0] = float(np.cos(mag))
out = out + (float(np.sin(mag)) / mag) * G
else:
mag = float(np.sqrt(s))
out[0] = float(np.cosh(mag))
out = out + (float(np.sinh(mag)) / mag) * G
return _strict_close_rotor(out, name="exp_bivector")
# Non-simple: truncated geometric series (construction boundary only).
term = _identity()
out = term.copy()
for k in range(1, 48):
term = geometric_product(term, G) / float(k)
out = out + term
if float(np.linalg.norm(term)) < 1e-18:
break
return _strict_close_rotor(out, name="exp_bivector_series")
def _metric_project(
x: np.ndarray,
modes: Sequence[np.ndarray],
) -> Tuple[np.ndarray, np.ndarray]:
"""Metric-orthogonal projection onto span(modes) under cga_inner.
Solves G c = r with G_ij = ⟨b_i, b_j⟩, r_i = ⟨b_i, x⟩. Returns
(projection, residual) with residual = x projection.
"""
x_arr = _as_mv(x, "ψ_incoming")
cols = [_as_mv(m, f"mode[{i}]") for i, m in enumerate(modes)]
k = len(cols)
if k == 0:
return np.zeros(N_COMPONENTS, dtype=np.float64), x_arr.copy()
gram = np.array(
[[cga_inner(cols[i], cols[j]) for j in range(k)] for i in range(k)],
dtype=np.float64,
)
rhs = np.array([cga_inner(cols[i], x_arr) for i in range(k)], dtype=np.float64)
# Fail-closed on metric-degenerate span (null direction with no reciprocal).
Bmat = np.column_stack(cols)
rank_b = int(np.linalg.matrix_rank(Bmat))
rank_g = int(np.linalg.matrix_rank(gram))
if rank_g < rank_b:
_u, _sv, vh = np.linalg.svd(gram)
degenerate_combo = [round(float(v), 6) for v in vh[-1]]
null_columns = [
i for i in range(k) if abs(float(gram[i, i])) < _NEAR_ZERO
]
raise WaveSpectralLeakageError(
"degenerate_metric_span",
rank_basis=rank_b,
rank_gram=rank_g,
null_columns=null_columns,
degenerate_combo=degenerate_combo,
)
coeffs, *_ = np.linalg.lstsq(gram, rhs, rcond=None)
projection = np.zeros(N_COMPONENTS, dtype=np.float64)
for c, col in zip(coeffs, cols):
projection = projection + float(c) * col
residual = x_arr - projection
return projection, residual
class WaveManifold:
"""Continuous wave propagation + resonant measures over Cl(4,1) fields.
Construction-closed rotors; dual-checked unitary residual; deterministic.
Optional standing-wave mode registry for resonant recall (ADR-0241 §2.2);
not a vault/store — reconstruction-over-storage, off-serving.
"""
def __init__(self, epsilon_drift: float = 1e-6) -> None:
self.epsilon_drift = float(epsilon_drift)
self.n_dims = N_COMPONENTS
# Standing-wave eigenmode registry (session-local; not durable memory).
self._resonant_modes: list[np.ndarray] = []
# --- Transport -----------------------------------------------------------
def sandwich_step(self, psi: np.ndarray, R: np.ndarray) -> np.ndarray:
"""Multivector field path: ψ' = R ψ ~R (matches :func:`versor_apply`)."""
psi_arr = _as_mv(psi, "ψ")
R_arr = _require_closed_rotor(R, name="R")
return versor_apply(R_arr, psi_arr).astype(np.float64)
def left_spinor_step(self, psi: np.ndarray, R: np.ndarray) -> np.ndarray:
"""Spinor / chiral path: ψ' = R ψ (left geometric product)."""
psi_arr = _as_mv(psi, "ψ")
R_arr = _require_closed_rotor(R, name="R")
return geometric_product(R_arr, psi_arr).astype(np.float64)
def algebraic_schrodinger_step(
self,
psi: np.ndarray,
H_operator: np.ndarray,
dt: float,
) -> np.ndarray:
"""Unitary step via R = exp(B·dt), sandwich on multivector fields.
``H_operator`` is the bivector generator B (32-vector). Default field
law is sandwich so even field-state versors stay closed under the step.
"""
psi_arr = _as_mv(psi, "ψ")
R = _exp_bivector_generator(H_operator, dt)
return self.sandwich_step(psi_arr, R)
# --- Unitary residual (GoldTether wave form) -----------------------------
def measure_unitary_residual(self, psi: np.ndarray) -> float:
"""Dual-checked amplitude drift: max(‖ψ ψ̃ 1‖, ‖~ψ ψ 1‖ proxy).
Uses :func:`versor_unit_residual` on ψ and reverse(ψ).
"""
psi_arr = _as_mv(psi, "ψ")
r = float(versor_unit_residual(psi_arr))
r_rev = float(versor_unit_residual(reverse(psi_arr)))
return max(r, r_rev)
# --- Spectral leakage (surprise) -----------------------------------------
def compute_spectral_leakage(
self,
psi_incoming: np.ndarray,
resonant_modes: Sequence[np.ndarray],
) -> Tuple[np.ndarray, float]:
"""Non-resonant spectral leakage: residual after metric proj onto modes.
Returns ``(surprise_vector, energy)`` with energy = Euclidean ‖residual‖
(definite readout after metric-exact projection; same doctrine as
surprise_residual magnitude).
"""
_proj, residual = _metric_project(psi_incoming, list(resonant_modes))
energy = float(np.linalg.norm(residual))
return residual.astype(np.float64), energy
# --- Wave polar analogy (Procrustes upgrade) -----------------------------
def wave_analogical_polar(
self,
psi_A: np.ndarray,
psi_B: np.ndarray,
) -> np.ndarray:
"""Recover sandwich conjugator R with ψ_B ≈ R ψ_A ~R (polar / conjugacy).
Canonical single-field analogy rotor. Uses the field-conjugacy engine in
``dynamic_manifold`` (lazy import — avoids import cycle; Procrustes
multi-pair path calls this for single non-null pairs).
"""
R, _residual = self.wave_field_conjugacy([psi_A], [psi_B])
return R
def wave_field_conjugacy(
self,
sources: Sequence[np.ndarray],
targets: Sequence[np.ndarray],
) -> Tuple[np.ndarray, float]:
"""Multi-pair sandwich conjugacy (thin wrap over stacked field engine).
Canonical multi-field path for Procrustes (ADR-0241 Slice 3). Returns
``(R, residual)`` where residual is the mean raw-sandwich residual from
the conjugacy engine (callers may recompute pair residuals).
"""
# Lazy import: dynamic_manifold may call WaveManifold at runtime.
from core.physics.dynamic_manifold import _field_conjugacy_versor
src = [_as_mv(s, f"source[{i}]") for i, s in enumerate(sources)]
tgt = [_as_mv(t, f"target[{i}]") for i, t in enumerate(targets)]
if len(src) != len(tgt) or not src:
raise ValueError("wave_field_conjugacy: non-empty equal-length pairs required")
R, residual = _field_conjugacy_versor(src, tgt)
return _require_closed_rotor(R, name="R_conjugacy"), float(residual)
# --- Standing-wave registry / resonant recall (ADR-0241 §2.2) ------------
def register_resonant_mode(self, psi_k: np.ndarray) -> int:
"""Register a standing-wave mode. Returns mode index. Session-local only."""
mode = _as_mv(psi_k, "ψ_k").copy()
self._resonant_modes.append(mode)
return len(self._resonant_modes) - 1
def clear_resonant_modes(self) -> None:
"""Drop all registered modes (tests / session reset)."""
self._resonant_modes.clear()
@property
def resonant_modes(self) -> tuple[np.ndarray, ...]:
return tuple(m.copy() for m in self._resonant_modes)
def resonant_recall(
self,
psi_query: np.ndarray,
*,
modes: Sequence[np.ndarray] | None = None,
) -> Tuple[np.ndarray, float, int]:
"""Holographic resonant lock-in: max constructive overlap with modes.
Overlap uses the scalar part of ``ψ_q · ~ψ_k`` (algebraic inner structure
via reverse product — not cosine/ANN). Returns
``(best_mode, resonance_energy, index)``.
Empty mode set raises ``ValueError`` (no confabulated recall).
"""
query = _as_mv(psi_query, "ψ_query")
mode_list = self._resolve_modes(modes)
if not mode_list:
raise ValueError("resonant_recall: empty mode set (no confabulated recall)")
best_i = 0
best_E = -1.0
for i, mode in enumerate(mode_list):
# Resonance energy: |⟨ψ_q ~ψ_k⟩_0| — constructive phase lock magnitude.
prod = geometric_product(query, reverse(mode))
energy = abs(float(scalar_part(prod)))
if energy > best_E:
best_E = energy
best_i = i
return mode_list[best_i].copy(), float(best_E), int(best_i)
def resonant_reconstruct(
self,
psi_query: np.ndarray,
*,
modes: Sequence[np.ndarray] | None = None,
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Superposition reconstruction ψ̂ = Σ_k c_k ψ_k.
Coefficients c_k are reverse-product scalar overlaps
⟨ψ_q ~ψ_k⟩_0, L1-normalized when the total absolute mass is nonzero.
Reconstruction-over-storage via interference weights — not cosine
similarity and not argmax-only lock-in (use :meth:`resonant_recall`
for hard mode selection).
Returns ``(psi_hat, coeffs, energies)``. Empty mode set raises
``ValueError`` (no confabulation).
"""
query = _as_mv(psi_query, "ψ_query")
mode_list = self._resolve_modes(modes)
if not mode_list:
raise ValueError(
"resonant_reconstruct: empty mode set (no confabulated recall)"
)
energies = np.array(
[
float(scalar_part(geometric_product(query, reverse(m))))
for m in mode_list
],
dtype=np.float64,
)
mass = float(np.sum(np.abs(energies)))
if mass < _NEAR_ZERO:
coeffs = np.zeros(len(mode_list), dtype=np.float64)
# Uniform refuse-to-invent: zero reconstruction when no overlap.
psi_hat = np.zeros(N_COMPONENTS, dtype=np.float64)
return psi_hat, coeffs, energies
coeffs = energies / mass
psi_hat = np.zeros(N_COMPONENTS, dtype=np.float64)
for c, mode in zip(coeffs, mode_list):
psi_hat = psi_hat + float(c) * mode
return psi_hat.astype(np.float64), coeffs, energies
def phase_correlation(
self,
psi_A: np.ndarray,
psi_B: np.ndarray,
) -> float:
"""Algebraic multimodal resonance (cohesion I-04).
rho(A,B) = ⟨ψ_A ~ψ_B + ψ_B ~ψ_A⟩_0
Symmetric, deterministic, reverse-product structure. Not cosine/ANN.
"""
a = _as_mv(psi_A, "ψ_A")
b = _as_mv(psi_B, "ψ_B")
ab = geometric_product(a, reverse(b))
ba = geometric_product(b, reverse(a))
return float(scalar_part(ab + ba))
def _resolve_modes(
self,
modes: Sequence[np.ndarray] | None,
) -> list[np.ndarray]:
if modes is None:
return list(self._resonant_modes)
return [_as_mv(m, f"mode[{i}]") for i, m in enumerate(modes)]
# --- Chiral spinor charge ------------------------------------------------
def chiral_charge(self, psi: np.ndarray) -> float:
"""Topological spinor charge Q = ⟨ψ I₅ ~ψ⟩_0 (ADR-0241 §2.4C).
In real Cl(4,1), ψ~ψ is always even-grade, so ⟨I₅ (ψ~ψ)⟩_0 is structurally
zero — the same odd-grade vacuity that retired Super §3.3 on even field
states (#19). The formula is implemented honestly (returns ~0) and is
conserved under left unitary multiply; a non-vacuous complex/pair-spinor
extension remains future work. Even unit versors stay honest at ~0.
"""
psi_arr = _as_mv(psi, "ψ")
# ⟨ψ I ~ψ⟩_0 = ⟨I (ψ ~ψ)⟩_0 (I central)
return float(
scalar_part(
geometric_product(
geometric_product(psi_arr, _I5),
reverse(psi_arr),
)
)
)
__all__ = ["WaveManifold", "WaveSpectralLeakageError"]