hdcstorage / tests /test_memory_modes.py
AEUPH's picture
HDCSTORAGE: hyperdimensional computer, webOS and agentic MCP layer (stdlib-only Python)
ad474c9 verified
Raw History Blame Contribute Delete
5.77 kB
import unittest
from hdc.hypervec import hvc, sim
from hdc.memory_modes import (
HolographicMemory,
HybridMemory,
PhotographicMemory,
capacity_report,
compare_modes,
)
D = 2000
SYMBOLS = [hvc("test/symbol/%d" % i, D) for i in range(8)]
class TestPhotographic(unittest.TestCase):
def test_recall_is_bit_exact(self):
mem = PhotographicMemory(d=D)
value = hvc("pixel/42", D)
mem.capture("frame/42", value)
got, score = mem.recall("frame/42")
self.assertEqual(got, value & ((1 << D) - 1))
self.assertEqual(score, 1.0)
def test_miss_is_none(self):
mem = PhotographicMemory(d=D)
self.assertEqual(mem.recall("absent"), (None, 0.0))
def test_capacity_evicts_oldest(self):
mem = PhotographicMemory(d=D, capacity=2)
for i in range(3):
mem.capture("k/%d" % i, SYMBOLS[i])
self.assertEqual(len(mem), 2)
self.assertNotIn("k/0", mem)
self.assertIn("k/2", mem)
self.assertEqual(mem.stats()["evicted"], 1)
def test_overwrite_does_not_evict(self):
mem = PhotographicMemory(d=D, capacity=1)
mem.capture("k", SYMBOLS[0])
mem.capture("k", SYMBOLS[1])
self.assertEqual(mem.recall("k")[0], SYMBOLS[1])
self.assertEqual(mem.stats()["evicted"], 0)
class TestHolographic(unittest.TestCase):
def test_majority_superposition_recalls_exactly_at_small_k(self):
mem = HolographicMemory(d=D, alphabet=SYMBOLS)
for i in range(4):
mem.record("slot/%d" % i, SYMBOLS[i])
for i in range(4):
got, _ = mem.recall("slot/%d" % i)
self.assertEqual(got, SYMBOLS[i], msg="slot %d" % i)
def test_xor_accumulation_is_the_wrong_rule(self):
# Regression: XOR crosstalk is itself random at every bit, so unbinding
# is chance at any k. Majority is what makes recall work at all.
# Measured: XOR recalls 0/2, 0/4, 2/8 (chance); majority 8/8.
from hdc.hypervec import bind
for k in (2, 4, 8):
trace = 0
for i in range(k):
trace ^= bind(hvc("xor/%d" % i, D), SYMBOLS[i], D)
xor_hits = 0
for i in range(k):
probe = bind(trace, hvc("xor/%d" % i, D), D)
best = max(SYMBOLS, key=lambda s: sim(probe, s, D))
xor_hits += best == SYMBOLS[i]
self.assertLessEqual(xor_hits, k // 2, msg="k=%d" % k)
majority = HolographicMemory(d=D, alphabet=SYMBOLS)
for i in range(k):
majority.record("xor/%d" % i, SYMBOLS[i])
self.assertEqual(
sum(1 for i in range(k) if majority.recall("xor/%d" % i)[0] == SYMBOLS[i]),
k,
msg="k=%d" % k,
)
def test_confidence_falls_as_the_trace_fills(self):
mem = HolographicMemory(d=D, alphabet=SYMBOLS)
mem.record("slot/0", SYMBOLS[0])
alone = mem.confidence("slot/0")
for i in range(1, 6):
mem.record("slot/%d" % i, SYMBOLS[i])
crowded = mem.confidence("slot/0")
self.assertLess(crowded, alone)
self.assertGreater(alone, 0.9)
def test_empty_memory_returns_nothing(self):
mem = HolographicMemory(d=D, alphabet=SYMBOLS)
self.assertEqual(mem.recall("anything"), (None, 0.0))
self.assertEqual(mem.confidence("anything"), 0.0)
def test_trace_is_bounded_by_dimension(self):
mem = HolographicMemory(d=D, alphabet=SYMBOLS)
for i in range(8):
mem.record("slot/%d" % i, SYMBOLS[i])
self.assertLess(mem.trace.bit_length(), D + 1)
self.assertEqual(mem.stats()["items"], 8)
def test_capacity_report_is_monotone_in_similarity(self):
rows = capacity_report(D, sizes=(2, 8, 16), symbols=8)
self.assertEqual([r["items"] for r in rows], [2, 8, 16])
for earlier, later in zip(rows, rows[1:]):
self.assertLessEqual(later["mean_similarity"], earlier["mean_similarity"])
class TestHybrid(unittest.TestCase):
def test_exact_path_wins_when_present(self):
mem = HybridMemory(d=D, buckets=4, alphabet=SYMBOLS)
mem.capture("key/1", SYMBOLS[1])
value, score, path = mem.recall("key/1")
self.assertEqual((value, score, path), (SYMBOLS[1], 1.0, "exact"))
def test_trace_path_answers_after_eviction(self):
mem = HybridMemory(d=D, buckets=1, per_bucket=1, alphabet=SYMBOLS)
mem.capture("first", SYMBOLS[0])
mem.capture("second", SYMBOLS[1]) # evicts "first" from the exact index
self.assertNotIn("first", mem.exact[0])
value, score, path = mem.recall("first")
self.assertEqual(path, "trace")
self.assertIsNotNone(value)
def test_buckets_are_disjoint(self):
mem = HybridMemory(d=D, buckets=8, alphabet=SYMBOLS)
mem.capture("key/1", SYMBOLS[1])
filled = [i for i, cell in enumerate(mem.exact) if cell]
self.assertEqual(len(filled), 1)
def test_consolidate_matches_a_fresh_trace(self):
mem = HybridMemory(d=D, buckets=2, alphabet=SYMBOLS)
for i in range(4):
mem.capture("k/%d" % i, SYMBOLS[i])
self.assertEqual(mem.consolidate(), 0)
for i in range(4):
self.assertEqual(mem.recall("k/%d" % i)[0], SYMBOLS[i])
def test_compare_modes_photographic_is_perfect(self):
result = compare_modes(D, k=8, symbols=8)
self.assertEqual(result["photographic"], 1.0)
self.assertEqual(result["items"], 8)
def test_zero_buckets_rejected(self):
with self.assertRaises(ValueError):
HybridMemory(d=D, buckets=0)
if __name__ == "__main__":
unittest.main()