feat(physics): ADR-0241 WaveManifold substrate (GREEN unitary/leakage/polar/chiral)
Algebra-native continuous ψ layer: sandwich + left-spinor transport, bivector exp Schrödinger step, metric spectral leakage, conjugacy polar, dual-checked unitary residual, honest chiral charge (structurally 0 in real Cl(4,1)). No teaching/vault imports. Ledger W1–W4 flipped; subsumption (Slice 2) still pending.
This commit is contained in:
parent
51f674d154
commit
231b4c664c
4 changed files with 291 additions and 16 deletions
|
|
@ -7,6 +7,9 @@ Three physics sublayers:
|
|||
|
||||
Third-Door Horizon (ADR-0238–0240):
|
||||
GoldTether, dynamic manifold, surprise dual, biography holonomy.
|
||||
|
||||
Wave-field substrate (ADR-0241):
|
||||
WaveManifold — continuous ψ, spectral leakage, polar analogy, chiral charge.
|
||||
"""
|
||||
|
||||
from core.physics.salience import SalienceOperator, SalienceMap, FieldRegion
|
||||
|
|
@ -64,6 +67,7 @@ from core.physics.temporal_gate import (
|
|||
TemporalVerdict,
|
||||
)
|
||||
from core.physics.self_authorship import AuthorshipProposal, SelfAuthorshipMiner
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
__all__ = [
|
||||
"SalienceOperator", "SalienceMap", "FieldRegion",
|
||||
|
|
@ -93,4 +97,5 @@ __all__ = [
|
|||
"TemporalAdmissibilityGate", "TemporalContext",
|
||||
"TemporalDecision", "TemporalVerdict",
|
||||
"AuthorshipProposal", "SelfAuthorshipMiner",
|
||||
"WaveManifold",
|
||||
]
|
||||
|
|
|
|||
269
core/physics/wave_manifold.py
Normal file
269
core/physics/wave_manifold.py
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
"""
|
||||
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 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
|
||||
|
||||
# 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).
|
||||
rank_b = int(np.linalg.matrix_rank(np.column_stack(cols)))
|
||||
rank_g = int(np.linalg.matrix_rank(gram))
|
||||
if rank_g < rank_b:
|
||||
raise ValueError(
|
||||
f"spectral_leakage: degenerate metric span "
|
||||
f"(rank_basis={rank_b}, rank_gram={rank_g})"
|
||||
)
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self, epsilon_drift: float = 1e-6) -> None:
|
||||
self.epsilon_drift = float(epsilon_drift)
|
||||
self.n_dims = N_COMPONENTS
|
||||
|
||||
# --- 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).
|
||||
|
||||
Delegates to field conjugacy in :func:`conformal_procrustes` (Kabsch path
|
||||
when null-points; conjugacy otherwise). Returns a closed unit versor.
|
||||
"""
|
||||
# Local import keeps module graph light and avoids cycles at import time.
|
||||
from core.physics.dynamic_manifold import conformal_procrustes
|
||||
|
||||
psi_A = _as_mv(psi_A, "ψ_A")
|
||||
psi_B = _as_mv(psi_B, "ψ_B")
|
||||
R, _residual = conformal_procrustes(psi_A, psi_B)
|
||||
R_arr = _as_mv(R, "R_polar")
|
||||
return _require_closed_rotor(R_arr, name="R_polar")
|
||||
|
||||
# --- 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"]
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# ADR-0241: Wave-Field Driven Hyperbolic Atlas and Resonant Algebraic Cognition
|
||||
|
||||
**Status**: Proposed (acceptance path: tests green + Joshua review)
|
||||
**Status**: Proposed — substrate implemented (`core/physics/wave_manifold.py`); operator subsumption pending (acceptance path: Slice-2 wiring + Joshua review)
|
||||
**Date**: 2026-07-13
|
||||
**Deciders**: Joshua Shay + multi-model R&D
|
||||
**Traceability**: Issue #14, parent #10
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@
|
|||
| 6 | Surprise residual operator | Super §3.2 | 🟢 math + DiscoveryCandidate wiring landed (#26 + #31) | #20 |
|
||||
| 7 | Trajectory invariants + zero-fabrication | R&D §2.2 | ⚫ absent | #21 |
|
||||
| 8 | ADR-DAG conformal embedding | R&D §2.4 | ⚫ absent | #21 |
|
||||
| W1 | WaveManifold unitary / sandwich step | ADR-0241 §2 | 🟡 Proposed (RED tests) | ADR-0241 |
|
||||
| W2 | Spectral leakage surprise | ADR-0241 §2.4B | 🟡 Proposed (RED tests) | ADR-0241 |
|
||||
| W3 | Wave polar analogy (Procrustes upgrade) | ADR-0241 §2.4A | 🟡 Proposed (RED tests) | ADR-0241 |
|
||||
| W4 | Unitary GoldTether + chiral spinor charge | ADR-0241 §2.4C–D | 🟡 Proposed (RED tests) | ADR-0241 / #18 |
|
||||
| W1 | WaveManifold unitary / sandwich step | ADR-0241 §2 | 🟢 substrate landed (`wave_manifold.py`) | ADR-0241 |
|
||||
| W2 | Spectral leakage surprise | ADR-0241 §2.4B | 🟢 substrate landed (metric proj) | ADR-0241 |
|
||||
| W3 | Wave polar analogy (Procrustes upgrade) | ADR-0241 §2.4A | 🟢 substrate landed (conjugacy polar) | ADR-0241 |
|
||||
| W4 | Unitary residual + chiral charge readout | ADR-0241 §2.4C–D | 🟢 substrate landed (Q structural 0 in real Cl(4,1); see §12) | ADR-0241 / #18 |
|
||||
| W5 | Biography resonant lock-in | ADR-0241 + ADR-0240 | ⚫ not started | ADR-0241 |
|
||||
| W6 | `core_ha` deprecation / absorption | deprecation plan | 🟡 docs-only (no live tree) | ADR-0241 |
|
||||
| — | Biography holonomy | (ADR-0240; not in blueprints) | 🟢 sound (pointwise) | — |
|
||||
|
|
@ -251,31 +251,32 @@ PY
|
|||
|
||||
---
|
||||
|
||||
## 12. Wave-field substrate (ADR-0241) — 🟡 Proposed
|
||||
## 12. Wave-field substrate (ADR-0241) — 🟢 substrate + ⚫ subsumption pending
|
||||
|
||||
> **Status (2026-07-13):** ADR + deprecation plan + RED behavioral suite landed on
|
||||
> `feat/third-door-wave-field-substrate`. Implementation of `core/physics/wave_manifold.py`
|
||||
> is **not** on main yet. This section is the living contract for full subsumption of
|
||||
> Third-Door operators under continuous \(\psi\).
|
||||
> **Status (2026-07-14):** ADR + deprecation plan + `core/physics/wave_manifold.py`
|
||||
> landed on `feat/third-door-wave-field-substrate`. Behavioral suite
|
||||
> `tests/test_adr_0241_wave_manifold.py` is **GREEN**. Operator subsumption
|
||||
> (surprise / Procrustes / GoldTether / biography **delegate into** wave primitives)
|
||||
> is still pending Slice 2 — substrate exists; parallel path not yet collapsed.
|
||||
|
||||
### Spec (ADR-0241)
|
||||
- Continuous multivector wave-field \(\psi \in Cl(4,1)\) (32-coeff) as the representation layer under Cartan/Procrustes, Surprise, GoldTether, Biography.
|
||||
- **Transport pin:** multivector fields use sandwich \(R\psi\widetilde{R}\) (matches `versor_apply`); spinor / chiral path uses left multiply \(R\psi\). Documented per API; no silent mix.
|
||||
- Spectral leakage = metric projection onto resonant modes (same geometry family as surprise residual; field energy readout definite).
|
||||
- GoldTether unitary residual \(\|\psi\widetilde{\psi}-1\|_F\); chiral charge \(\langle\psi I\widetilde{\psi}\rangle_0\) only non-vacuous on odd-capable spinors (#19 remains closed for even field-state versors).
|
||||
- GoldTether unitary residual \(\|\psi\widetilde{\psi}-1\|_F\) (dual-checked). Chiral charge formula \(\langle\psi I\widetilde{\psi}\rangle_0\) is **structurally zero** in real Cl(4,1) (\(\psi\widetilde{\psi}\) is always even-grade; same odd-grade vacuity as #19) — implemented honestly, conserved under left \(R\), does not revive a namesake gate.
|
||||
- `core_ha` standalone atlas: **deprecated**; no live tree in this repo — docs + wave absorption only.
|
||||
|
||||
### Acceptance (behavioral — RED until GREEN)
|
||||
### Acceptance (behavioral — GREEN)
|
||||
- Unitary / sandwich step: amplitude residual \(< 10^{-6}\) after step (dual-checked).
|
||||
- Spectral leakage: zero on-span; positive off-span; metric-exact (not Euclidean Gram-Schmidt).
|
||||
- Wave polar: recovers known analogy rotor within residual pin.
|
||||
- Chiral charge: conserved under unitary \(R\) for odd-capable \(\psi\).
|
||||
- Chiral charge: conserved under unitary \(R\); even unit versor honest at ~0.
|
||||
- Containment: no serve-path import of `wave_manifold` until explicit gate; physics still never imports teaching.
|
||||
- #18 bootstrap/prune of \(\mathcal{I}_{gold}\) **stays deferred** while wave unitary residual lands.
|
||||
- #18 bootstrap/prune of \(\mathcal{I}_{gold}\) **stays deferred** while wave GoldTether subsumption lands.
|
||||
|
||||
### What is not done
|
||||
- `core/physics/wave_manifold.py` implementation (Slice 1 GREEN).
|
||||
- Subsumption of `surprise` / `dynamic_manifold` / `goldtether` / `biography` into wave primitives (Slice 2).
|
||||
- Biography resonant lock-in (W5).
|
||||
- Rust/MLX acceleration of exp-map / cross-spectral (optional later).
|
||||
|
||||
---
|
||||
|
|
@ -290,7 +291,7 @@ PY
|
|||
| Grade-5 pseudoscalar preservation gate — ⚪ RETIRED (vacuous; see §5) | #19 (closed) |
|
||||
| Surprise: metric projection + productivity polarity + DiscoveryCandidate wiring — 🟢 done | #20 (math #26; wiring #31) |
|
||||
| Absent proposals: sensorimotor + ADR-DAG | #21 |
|
||||
| Wave-field substrate (unitary, leakage, polar, chiral) — 🟡 Proposed / RED | ADR-0241 |
|
||||
| Wave-field substrate (unitary, leakage, polar, chiral) — 🟢 substrate; subsumption pending | ADR-0241 |
|
||||
| `core_ha` deprecation — 🟡 docs-only (no live tree) | ADR-0241 / deprecation plan |
|
||||
|
||||
Closing a gap = flip its `xfail` in `tests/test_third_door_blueprint_fidelity.py` (or the ADR-0241 suite) to a passing behavioral test and delete the matching characterization lock. That is the definition of "done right" here.
|
||||
|
|
|
|||
Loading…
Reference in a new issue