fix(algebra): make versor_apply close runtime field results
Remove the implicit null-vector bypass from the runtime-facing versor_apply closure boundary. FieldState.F is treated throughout the runtime and cognitive pipeline as a unit versor field. Returning null-like raw sandwich results from versor_apply created a contract mismatch and allowed multi-turn closure drift to escape into session state. - make _close_applied_versor always close runtime field results - keep unitize-first semantics and construction-seed fallback - add regression proving null-like sandwich output is closed for the runtime contract Null-vector preservation should return later behind an explicit geometry API, not the generic runtime field propagation path. No GitHub CI/status checks were exposed for this PR.
This commit is contained in:
parent
9b7310c07c
commit
7aa8626ec4
2 changed files with 17 additions and 13 deletions
|
|
@ -14,7 +14,6 @@ _CONSTRUCTION_RESIDUE_TOLERANCE = 1e-2
|
|||
_NEAR_ZERO_TOLERANCE = 1e-12
|
||||
_DENSE_SEED_MIN_COMPONENTS = 8
|
||||
_SEED_BIVECTORS = (6, 7, 8, 10, 11, 13)
|
||||
_NULL_SCALAR_TOLERANCE = 1e-9
|
||||
|
||||
|
||||
def _array_dtype(v: np.ndarray) -> np.dtype:
|
||||
|
|
@ -95,22 +94,15 @@ def construction_seed_versor(v: np.ndarray) -> np.ndarray:
|
|||
return _seed_to_rotor(v, _array_dtype(v))
|
||||
|
||||
|
||||
|
||||
def _is_null_vector(v: np.ndarray) -> bool:
|
||||
product = geometric_product(v, v).astype(np.float64)
|
||||
return float(np.linalg.norm(product)) < _NULL_SCALAR_TOLERANCE
|
||||
|
||||
|
||||
def _close_applied_versor(v: np.ndarray, dtype: np.dtype) -> np.ndarray:
|
||||
"""Close algebra-produced sandwich results without breaking null vectors.
|
||||
"""Close algebra-produced sandwich results for runtime field states.
|
||||
|
||||
CGA sandwiching must preserve null vectors as null vectors. Unit-versor
|
||||
closure only applies when the result is meant to remain a versor field;
|
||||
null vectors are geometric points and must pass through unchanged.
|
||||
``versor_apply`` is the field-propagation API: callers expect the returned
|
||||
multivector to satisfy ``versor_condition(result)``. CGA point/null-vector
|
||||
preservation belongs behind an explicit geometry API, not this runtime
|
||||
manifold boundary.
|
||||
"""
|
||||
arr = np.asarray(v, dtype=dtype)
|
||||
if _is_null_vector(arr):
|
||||
return arr.astype(dtype)
|
||||
try:
|
||||
return unitize_versor(arr).astype(dtype)
|
||||
except ValueError:
|
||||
|
|
|
|||
|
|
@ -103,6 +103,18 @@ def test_composition_closed():
|
|||
assert versor_condition(F3) < 1e-4
|
||||
|
||||
|
||||
def test_versor_apply_closes_null_like_field_results_for_runtime_contract():
|
||||
identity = np.zeros(32, dtype=np.float32)
|
||||
identity[0] = 1.0
|
||||
null_like = np.zeros(32, dtype=np.float32)
|
||||
null_like[1] = 1.0
|
||||
null_like[5] = 1.0
|
||||
|
||||
result = versor_apply(identity, null_like)
|
||||
|
||||
assert versor_condition(result) < 1e-6
|
||||
|
||||
|
||||
def test_identity_versor():
|
||||
identity = np.zeros(32, dtype=np.float32)
|
||||
identity[0] = 1.0
|
||||
|
|
|
|||
Loading…
Reference in a new issue