hdcstorage / tests /test_ring.py
AEUPH's picture
HDCSTORAGE: hyperdimensional computer, webOS and agentic MCP layer (stdlib-only Python)
ad474c9 verified
Raw History Blame Contribute Delete
5.49 kB
import unittest
from hdc.hypervec import hvc, sim
from hdc.ring import (
PHASES,
HistoricLedger,
LedgerEntry,
RingController,
drifting_world,
evolve,
periodic_world,
report,
rewind,
tick_key,
)
D = 2000
class TestAlgebraicRing(unittest.TestCase):
def test_evolution_is_invertible(self):
key = hvc("ring/test-key", D)
for i in range(4):
state = hvc("ring/state/%d" % i, D)
for k in (1, 2, 7):
self.assertEqual(rewind(evolve(state, key, k, D), key, k, D), state)
def test_evolution_actually_moves_the_state(self):
key = hvc("ring/test-key", D)
state = hvc("ring/state/0", D)
self.assertLess(abs(sim(evolve(state, key, 1, D), state, D)), 0.1)
def test_tick_keys_are_distinct(self):
self.assertNotEqual(tick_key(0, D), tick_key(1, D))
self.assertLess(abs(sim(tick_key(0, D), tick_key(1, D), D)), 0.1)
class TestLedger(unittest.TestCase):
def test_append_and_lookup(self):
ledger = HistoricLedger(d=D, capacity=4)
state = hvc("ledger/0", D)
ledger.append(LedgerEntry(0, "past", state, None, 0.5, 1.0))
self.assertIs(ledger.at(0).state, state)
self.assertEqual(ledger.recall_state(0)[0], state)
self.assertIsNone(ledger.at(9))
def test_eviction_recycles_into_the_phase_summary(self):
ledger = HistoricLedger(d=D, capacity=2)
for i in range(5):
ledger.append(LedgerEntry(i, PHASES[i % 3], hvc("ledger/%d" % i, D), None, 0.0, 1.0))
self.assertEqual(len(ledger), 2)
self.assertEqual(ledger.recycled, 3)
self.assertEqual(sum(1 for p in PHASES if ledger.summaries[p].keys), 3)
def test_entropy_of_uniform_surprise_is_zero(self):
ledger = HistoricLedger(d=D, capacity=8)
for i in range(4):
ledger.append(LedgerEntry(i, "past", hvc("l/%d" % i, D), None, 0.0, 1.0))
self.assertEqual(ledger.entropy(), 0.0)
def test_entropy_rises_when_surprise_spreads(self):
ledger = HistoricLedger(d=D, capacity=8)
for i, surprise in enumerate([0.0, 0.5, 1.0, 0.0]):
ledger.append(LedgerEntry(i, "past", hvc("l/%d" % i, D), None, surprise, 1.0))
self.assertGreater(ledger.entropy(), 1.0)
def test_timeline_is_a_superposition_of_the_history(self):
ledger = HistoricLedger(d=D, capacity=4)
states = [hvc("timeline/%d" % i, D) for i in range(4)]
for i, state in enumerate(states):
ledger.append(LedgerEntry(i, PHASES[i % 3], state, None, 0.0, 1.0))
record = ledger.timeline_record()
self.assertNotEqual(record, 0)
got, score = ledger.recall_timeline(2)
self.assertEqual(got, states[2])
self.assertGreater(score, 0.1)
def test_empty_ledger_is_well_behaved(self):
ledger = HistoricLedger(d=D, capacity=2)
self.assertEqual(ledger.entropy(), 0.0)
self.assertEqual(ledger.timeline_record(), 0)
self.assertEqual(ledger.recall_timeline(0), (None, 0.0))
def test_zero_capacity_rejected(self):
with self.assertRaises(ValueError):
HistoricLedger(d=D, capacity=0)
class TestRingController(unittest.TestCase):
def test_converges_on_a_periodic_world(self):
ring = RingController(d=D, capacity=8)
ring.run(periodic_world(4, 12, D))
tail = ring.ledger.entries[-4:]
self.assertTrue(all(e.surprise < 1e-6 for e in tail), msg=[e.surprise for e in tail])
self.assertEqual(ring.energy, 1.0)
self.assertEqual(ring.mode(), "stable")
self.assertEqual(ring.horizon(), 3)
def test_stays_surprised_on_a_drifting_world(self):
ring = RingController(d=D, capacity=8)
ring.run(drifting_world(4, 12, D))
self.assertGreater(ring.mean_surprise(), 0.9)
self.assertEqual(ring.energy, 0.0)
self.assertEqual(ring.mode(), "explore")
self.assertEqual(ring.horizon(), 1)
def test_energy_stays_in_range(self):
ring = RingController(d=D, capacity=8)
for entry in ring.run(periodic_world(4, 20, D)):
self.assertGreaterEqual(entry.energy, 0.0)
self.assertLessEqual(entry.energy, 1.0)
def test_first_tick_has_no_prediction(self):
ring = RingController(d=D, capacity=4)
entry = ring.step(hvc("ring/first", D))
self.assertEqual(entry.surprise, 0.5)
def test_phases_rotate(self):
ring = RingController(d=D, capacity=8)
phases = [e.phase for e in ring.run(periodic_world(4, 6, D))]
self.assertEqual(phases, [PHASES[i % 3] for i in range(6)])
def test_horizon_follows_energy(self):
ring = RingController(d=D, capacity=8)
ring.energy = 0.0
self.assertEqual(ring.horizon(), 1)
ring.energy = 1.0
self.assertEqual(ring.horizon(), 3)
def test_predictions_become_exact(self):
ring = RingController(d=D, capacity=8)
ring.run(periodic_world(4, 10, D))
predicted, _ = ring.model.predict(ring.observations[-1], "tick")
self.assertIsNotNone(predicted)
self.assertEqual(predicted, ring.observations[-4])
def test_report_mentions_the_mode(self):
ring = RingController(d=D, capacity=4)
ring.run(periodic_world(4, 5, D))
self.assertIn("mode", ring.report())
self.assertIn("ring controller", report(D))
if __name__ == "__main__":
unittest.main()