"""Storage-size regression tests for holographic HRR vectors.""" from __future__ import annotations import pytest np = pytest.importorskip("numpy") from plugins.memory.holographic import holographic as hrr from plugins.memory.holographic.retrieval import FactRetriever from plugins.memory.holographic.store import MemoryStore pytestmark = pytest.mark.skipif( not hrr._HAS_NUMPY, reason="holographic vector storage requires numpy", ) def _float32_blob_size(dim: int) -> int: return len(hrr._FLOAT32_BLOB_PREFIX) + dim * np.dtype(np.float32).itemsize def test_phases_to_bytes_stores_float32_and_round_trips_with_dim() -> None: dim = 1024 phases = hrr.encode_atom("storage-size-regression", dim=dim) blob = hrr.phases_to_bytes(phases) assert len(blob) == _float32_blob_size(dim) restored = hrr.bytes_to_phases(blob, dim=dim) assert restored.shape == (dim,) np.testing.assert_allclose(restored, phases, rtol=0, atol=1e-6) def test_phases_to_bytes_round_trips_without_dim() -> None: dim = 1024 phases = hrr.encode_atom("dimensionless-round-trip", dim=dim) restored = hrr.bytes_to_phases(hrr.phases_to_bytes(phases)) assert restored.shape == (dim,) np.testing.assert_allclose(restored, phases, rtol=0, atol=1e-6) def test_phases_to_bytes_round_trips_ambiguous_small_dims_without_dim() -> None: dim = 2 phases = hrr.encode_atom("ambiguous-small-dimension", dim=dim) restored = hrr.bytes_to_phases(hrr.phases_to_bytes(phases)) assert restored.shape == (dim,) np.testing.assert_allclose(restored, phases, rtol=0, atol=1e-6) def test_bytes_to_phases_rejects_malformed_float32_blobs() -> None: phases = hrr.encode_atom("malformed-float32-blob", dim=2) blob = hrr.phases_to_bytes(phases) with pytest.raises(ValueError, match="expected .* for dim=3"): hrr.bytes_to_phases(blob, dim=3) with pytest.raises(ValueError, match="invalid payload byte length"): hrr.bytes_to_phases(hrr._FLOAT32_BLOB_PREFIX + b"x") def test_bytes_to_phases_reads_legacy_float64_blobs_with_and_without_dim() -> None: dim = 1024 phases = hrr.encode_atom("legacy-float64-regression", dim=dim) legacy_blob = phases.astype(np.float64, copy=False).tobytes() assert len(legacy_blob) == dim * np.dtype(np.float64).itemsize restored_with_dim = hrr.bytes_to_phases(legacy_blob, dim=dim) restored_without_dim = hrr.bytes_to_phases(legacy_blob) assert restored_with_dim.shape == (dim,) assert restored_without_dim.shape == (dim,) np.testing.assert_allclose(restored_with_dim, phases, rtol=0, atol=0) np.testing.assert_allclose(restored_without_dim, phases, rtol=0, atol=0) def test_bytes_to_phases_prefers_dim_matched_legacy_float64_on_prefix_collision() -> None: dim = 4 legacy_blob = hrr._FLOAT32_BLOB_PREFIX + b"\0" * ( dim * np.dtype(np.float64).itemsize - len(hrr._FLOAT32_BLOB_PREFIX) ) restored = hrr.bytes_to_phases(legacy_blob, dim=dim) assert restored.shape == (dim,) np.testing.assert_array_equal( restored, np.frombuffer(legacy_blob, dtype=np.float64).copy(), ) def test_dim1_phases_to_bytes_writes_legacy_float64() -> None: """At dim=1 the float32 prefixed blob (8 B) collides with raw float64 (8 B), so phases_to_bytes must fall back to raw float64.""" dim = 1 phases = hrr.encode_atom("dim-one-ambiguity", dim=dim) blob = hrr.phases_to_bytes(phases, dim=dim) assert len(blob) == dim * np.dtype(np.float64).itemsize # 8 bytes, no prefix assert not blob.startswith(hrr._FLOAT32_BLOB_PREFIX) def test_dim1_round_trip_with_dim() -> None: """Round-trip at dim=1 must work via the legacy float64 path.""" dim = 1 phases = hrr.encode_atom("dim-one-round-trip", dim=dim) restored = hrr.bytes_to_phases(hrr.phases_to_bytes(phases, dim=dim), dim=dim) assert restored.shape == (dim,) np.testing.assert_allclose(restored, phases, rtol=0, atol=0) def test_dim1_legacy_blob_starting_with_prefix_decodes_as_float64() -> None: """A legacy float64 blob at dim=1 that happens to start with HRR1 must decode as float64, not be misread as a prefixed float32 blob.""" dim = 1 phases = hrr.encode_atom("prefix-collision-dim-one", dim=dim) legacy_blob = phases.astype(np.float64).tobytes() # Force the blob to start with HRR1 prefix bytes collision_blob = hrr._FLOAT32_BLOB_PREFIX + legacy_blob[len(hrr._FLOAT32_BLOB_PREFIX):] assert len(collision_blob) == dim * np.dtype(np.float64).itemsize restored = hrr.bytes_to_phases(collision_blob, dim=dim) assert restored.shape == (dim,) np.testing.assert_allclose(restored, np.frombuffer(collision_blob, dtype=np.float64).copy(), rtol=0, atol=0) def test_memory_store_reads_legacy_float64_vectors(tmp_path) -> None: dim = 64 db_path = tmp_path / "legacy_memory_store.db" with MemoryStore(db_path=db_path, hrr_dim=dim) as store: fact_id = store.add_fact( 'Bob Stone keeps "legacy HRR vectors" searchable.', category="compat", tags="legacy storage", ) fact_blob = store._conn.execute( "SELECT hrr_vector FROM facts WHERE fact_id = ?", (fact_id,), ).fetchone()["hrr_vector"] bank_blob = store._conn.execute( "SELECT vector FROM memory_banks WHERE bank_name = ?", ("cat:compat",), ).fetchone()["vector"] legacy_fact_blob = hrr.bytes_to_phases(fact_blob, dim=dim).astype(np.float64).tobytes() legacy_bank_blob = hrr.bytes_to_phases(bank_blob, dim=dim).astype(np.float64).tobytes() store._conn.execute( "UPDATE facts SET hrr_vector = ? WHERE fact_id = ?", (legacy_fact_blob, fact_id), ) store._conn.execute( "UPDATE memory_banks SET vector = ? WHERE bank_name = ?", (legacy_bank_blob, "cat:compat"), ) store._conn.commit() assert len(legacy_fact_blob) == dim * np.dtype(np.float64).itemsize assert len(legacy_bank_blob) == dim * np.dtype(np.float64).itemsize retriever = FactRetriever(store, hrr_dim=dim) results = retriever.search("legacy HRR vectors", category="compat", limit=1) assert results assert results[0]["fact_id"] == fact_id def test_memory_store_persists_fact_and_bank_vectors_as_float32(tmp_path) -> None: dim = 64 db_path = tmp_path / "memory_store.db" with MemoryStore(db_path=db_path, hrr_dim=dim) as store: fact_id = store.add_fact( 'Alice Smith stores "compact HRR vectors" for Python tests.', category="perf", tags="hrr storage", ) fact_blob = store._conn.execute( "SELECT hrr_vector FROM facts WHERE fact_id = ?", (fact_id,), ).fetchone()["hrr_vector"] bank_blob = store._conn.execute( "SELECT vector FROM memory_banks WHERE bank_name = ?", ("cat:perf",), ).fetchone()["vector"] assert len(fact_blob) == _float32_blob_size(dim) assert len(bank_blob) == _float32_blob_size(dim) retriever = FactRetriever(store, hrr_dim=dim) results = retriever.search("compact HRR vectors", category="perf", limit=1) assert results assert results[0]["fact_id"] == fact_id