core/tests/test_rotor_power.py
Shay 07f49eb215 fix(drift): proper rotor-manifold scaling; restore respond contract
Three issues in the drift-fix landing (922bddc) addressed:

1. algebra/rotor.py: add rotor_power(R, alpha) — slerp on the rotor manifold
   via the rotor's exp/log decomposition. Handles both rotation planes
   (cos/sin) and boost planes (cosh/sinh); falls back to identity for
   non-simple bivectors or null cases.

2. generate/stream.py: the score-weighted vault recall previously did
   `weight*V + (1-weight)*np.eye(V.shape[0])`. Two bugs:
   - np.eye produced a 32x32 matrix for a 1D multivector, crashing
     versor_apply with a broadcasting error (2 cognition tests failing
     on main).
   - The linear blend produced multivectors with versor_condition up to
     2.2e-2, violating the non-negotiable 1e-6 invariant declared in
     CLAUDE.md. Now uses rotor_power(V, weight) which stays on the
     manifold by construction (versor_condition <= 1.1e-16).

3. session/context.py: respond() now re-binds result.final_state to
   self.state after finalize_turn's anchor pull, restoring the
   "respond returns the same object that was vaulted" contract
   (test_engine_loop_proof regression).

Verification:
- 41 new tests in tests/test_rotor_power.py covering closure preservation,
  alpha=0/1 boundaries, half-angle composition, and word-transition rotors.
- Empirical multi-turn versor_condition stays at machine epsilon with
  anchor pull, max 9.4e-7 without (under threshold either way after fix).
- Full suite: 609 passed, 4 skipped, 0 failed.
2026-05-16 11:44:45 -07:00

82 lines
2.9 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.

"""Tests for algebra.rotor.rotor_power — manifold-preserving rotor scaling.
The drift-fix #2 originally used linear interpolation between a rotor and
identity, which produced multivectors with versor_condition ≈ 10⁻², violating
the non-negotiable 1e-6 invariant. ``rotor_power`` replaces that with a proper
slerp on the rotor manifold: identity -> R^α stays on the manifold for any α.
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.rotor import make_rotor_from_angle, rotor_power, word_transition_rotor
from algebra.versor import versor_condition
_TOL = 1e-6
@pytest.mark.parametrize("angle", [0.05, 0.3, 0.7, 1.2, np.pi / 2])
@pytest.mark.parametrize("alpha", [0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0])
def test_rotor_power_preserves_versor_closure(angle: float, alpha: float) -> None:
"""For any rotation rotor and any fractional power, output is a closed unit rotor."""
R = make_rotor_from_angle(angle, bivector_idx=7)
R_alpha = rotor_power(R, alpha)
assert versor_condition(R_alpha) < _TOL, (
f"rotor_power(R(angle={angle}), {alpha}) violates closure: "
f"versor_condition = {versor_condition(R_alpha):.3e}"
)
def test_rotor_power_alpha_zero_returns_identity() -> None:
R = make_rotor_from_angle(0.7, bivector_idx=7)
R_zero = rotor_power(R, 0.0)
expected = np.zeros(32, dtype=R_zero.dtype)
expected[0] = 1.0
np.testing.assert_allclose(R_zero, expected, atol=1e-9)
def test_rotor_power_alpha_one_returns_input() -> None:
R = make_rotor_from_angle(0.4, bivector_idx=7)
R_one = rotor_power(R, 1.0)
np.testing.assert_allclose(R_one, R, atol=1e-9)
def test_rotor_power_half_angle_halves_rotation() -> None:
"""R^0.5 applied twice equals R."""
from algebra.cl41 import geometric_product
R = make_rotor_from_angle(0.8, bivector_idx=7)
R_half = rotor_power(R, 0.5)
R_half_squared = geometric_product(R_half, R_half)
np.testing.assert_allclose(R_half_squared, R, atol=1e-6)
def test_rotor_power_handles_identity_input() -> None:
"""Identity rotor under any power stays identity."""
identity = np.zeros(32, dtype=np.float64)
identity[0] = 1.0
for alpha in [0.0, 0.3, 1.0, 1.5]:
result = rotor_power(identity, alpha)
np.testing.assert_allclose(result, identity, atol=1e-9)
def test_rotor_power_on_word_transition_preserves_closure() -> None:
"""The real-world case: rotors produced by word_transition_rotor."""
A = np.zeros(32, dtype=np.float64)
A[0] = 1.0
B = np.zeros(32, dtype=np.float64)
B[0] = np.cos(0.4)
B[7] = np.sin(0.4)
R = word_transition_rotor(A, B)
for alpha in [0.05, 0.2, 0.5, 0.8, 0.95]:
R_alpha = rotor_power(R, alpha)
cond = versor_condition(R_alpha)
assert cond < _TOL, f"alpha={alpha}: versor_condition = {cond:.3e}"
def test_rotor_power_rejects_wrong_shape() -> None:
with pytest.raises(ValueError):
rotor_power(np.zeros(16, dtype=np.float64), 0.5)