core/tests/test_rust_backend.py
Shay 523c072818 feat: vault recall index, Rust versor parity, cognitive pack expansion
Phase 3 — vault exact recall index:
- Replace O(N) np.array_equal scan with hash-based exact-match index
- Add optional max_entries with deterministic FIFO eviction
- Index rebuilds on reproject for consistency

Phase 4 — Rust versor_apply parity:
- Fix CGA metric signature (+,+,+,+,-) and blade ordering to match Python
- Implement versor_apply_closed with null-vector preservation, f64 unitize,
  and construction seed fallback matching Python closure semantics
- Gate Rust dispatch behind CORE_BACKEND=rust; Python remains default
- Add f64 geometric product for closure-path precision

Phase 5 — cognitive quality pack expansion:
- Expand lexicon from 55 to 70 entries (evidence, inference, procedure,
  verification, distinction, relation, thought, understanding, judgment,
  principle, order, connectives)
- Improve semantic templates for cause, procedure, comparison, recall,
  verification intents
- Expand eval cases from 20 to 45 across all categories

Validation: 491 tests pass, 45 eval cases at 100% all metrics.
2026-05-15 15:34:39 -07:00

135 lines
3.9 KiB
Python

"""Rust versor_apply parity tests.
Verifies that the Rust closure-aware versor_apply produces identical results
to the Python algebra.versor.versor_apply for all critical cases:
identity, rotors, null vectors, versor condition, and backend dispatch.
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.versor import (
unitize_versor,
versor_apply as python_versor_apply,
versor_condition,
)
from algebra.cga import embed_point, is_null
try:
import core_rs
HAS_RUST = True
except ImportError:
HAS_RUST = False
skip_no_rust = pytest.mark.skipif(not HAS_RUST, reason="core_rs not available")
def _positive_unit_reflector(seed: int) -> np.ndarray:
rng = np.random.default_rng(seed)
vec4 = rng.standard_normal(4).astype(np.float32)
norm4 = float(np.linalg.norm(vec4))
if norm4 < 1e-6:
vec4[0] = 1.0
norm4 = 1.0
vec = np.zeros(5, dtype=np.float32)
vec[:4] = vec4
vec[4] = 0.25 * norm4 * np.tanh(float(rng.standard_normal()))
mv = np.zeros(32, dtype=np.float32)
mv[1:6] = vec
return unitize_versor(mv)
def _random_rotor(seed: int) -> np.ndarray:
from algebra.cl41 import geometric_product as gp
a = _positive_unit_reflector(seed)
b = _positive_unit_reflector(seed + 10000)
return unitize_versor(gp(a, b))
@skip_no_rust
def test_rust_versor_apply_matches_python_for_identity():
identity = np.zeros(32, dtype=np.float32)
identity[0] = 1.0
F = _positive_unit_reflector(42)
py_result = python_versor_apply(identity, F)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(identity, F), dtype=np.float32
)
assert np.allclose(py_result, rust_result, atol=1e-4), (
f"max diff: {np.max(np.abs(py_result - rust_result))}"
)
@skip_no_rust
def test_rust_versor_apply_matches_python_for_rotors():
for seed in range(20):
V = _random_rotor(seed)
F = _positive_unit_reflector(seed + 500)
py_result = python_versor_apply(V, F)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(V, F), dtype=np.float32
)
assert np.allclose(py_result, rust_result, atol=1e-3), (
f"seed={seed} max diff: {np.max(np.abs(py_result - rust_result))}"
)
@skip_no_rust
def test_rust_versor_apply_preserves_null_vectors():
point = embed_point(np.array([1.0, 2.0, 3.0], dtype=np.float32))
assert is_null(point)
V = _positive_unit_reflector(7)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(V, point), dtype=np.float32
)
py_result = python_versor_apply(V, point)
py_is_null = is_null(py_result)
rust_is_null = is_null(rust_result)
assert py_is_null == rust_is_null, (
f"null preservation mismatch: python={py_is_null}, rust={rust_is_null}"
)
@skip_no_rust
def test_rust_versor_apply_preserves_versor_condition():
for seed in range(20):
V = _positive_unit_reflector(seed)
F = _positive_unit_reflector(seed + 1000)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(V, F), dtype=np.float32
)
cond = versor_condition(rust_result)
assert cond < 1e-4, f"seed={seed} condition={cond:.2e}"
@skip_no_rust
def test_backend_dispatch_uses_rust_only_when_enabled():
"""Verify that algebra.backend.versor_apply only uses Rust when CORE_BACKEND=rust."""
import os
from importlib import reload
import algebra.backend as backend_mod
original = os.environ.get("CORE_BACKEND", "")
os.environ["CORE_BACKEND"] = "numpy"
reload(backend_mod)
assert not (backend_mod._REQUESTED_BACKEND == "rust")
os.environ["CORE_BACKEND"] = "rust"
reload(backend_mod)
assert backend_mod._REQUESTED_BACKEND == "rust"
if original:
os.environ["CORE_BACKEND"] = original
else:
os.environ.pop("CORE_BACKEND", None)
reload(backend_mod)