use amari_holographic::BindingAlgebra;
use crate::encoding::HashMapCodebook;
use crate::error::MinuetResult;
use crate::store::SimpleStore;
use crate::traits::{Codebook, MemoryStore, RetrievalResult, StoreReceipt};
pub struct SimpleMemory<A: BindingAlgebra> {
store: SimpleStore<A>,
codebook: HashMapCodebook<A>,
}
impl<A: BindingAlgebra> Default for SimpleMemory<A> {
fn default() -> Self {
Self::new()
}
}
impl<A: BindingAlgebra> SimpleMemory<A> {
#[must_use]
pub fn new() -> Self {
Self {
store: SimpleStore::new(),
codebook: HashMapCodebook::new(),
}
}
pub fn symbol(&self, name: &str) -> A {
self.codebook.symbol(name)
}
pub fn store(&self, key: &A, value: &A) -> MinuetResult<StoreReceipt> {
self.store.store(key, value)
}
pub fn store_symbols(&self, key: &str, value: &str) -> MinuetResult<StoreReceipt> {
let k = self.symbol(key);
let v = self.symbol(value);
self.store(&k, &v)
}
pub fn retrieve(&self, key: &A) -> MinuetResult<RetrievalResult<A>> {
self.store.retrieve(key)
}
pub fn retrieve_symbol(&self, key: &str) -> MinuetResult<RetrievalResult<A>> {
let k = self.symbol(key);
self.retrieve(&k)
}
pub fn closest(&self, repr: &A) -> Option<(String, f64)> {
self.codebook.closest(repr)
}
pub fn recall(&self, key: &str) -> MinuetResult<Option<(String, f64)>> {
let result = self.retrieve_symbol(key)?;
Ok(self.closest(&result.value))
}
#[must_use]
pub fn codebook(&self) -> &HashMapCodebook<A> {
&self.codebook
}
#[must_use]
pub fn capacity_info(&self) -> crate::traits::CapacityInfo {
self.store.capacity_info()
}
pub fn clear(&self) -> MinuetResult<()> {
self.store.clear()
}
#[must_use]
pub fn symbol_count(&self) -> usize {
self.codebook.len()
}
#[must_use]
pub fn item_count(&self) -> usize {
self.store.total_items()
}
}
#[cfg(test)]
mod tests {
use super::*;
use amari_holographic::ProductCliffordAlgebra;
type TestAlgebra = ProductCliffordAlgebra<16>;
#[test]
fn store_and_recall() {
let memory = SimpleMemory::<TestAlgebra>::new();
memory.store_symbols("paris", "france").unwrap();
memory.store_symbols("berlin", "germany").unwrap();
let result = memory.recall("paris").unwrap();
assert!(result.is_some());
let (_name, sim) = result.unwrap();
assert!(sim > 0.3, "similarity was {}", sim);
}
#[test]
fn symbol_consistency() {
let memory = SimpleMemory::<TestAlgebra>::new();
let a1 = memory.symbol("test");
let a2 = memory.symbol("test");
assert!(a1.similarity(&a2) > 0.99);
}
#[test]
fn capacity_info() {
let memory = SimpleMemory::<TestAlgebra>::new();
assert_eq!(memory.item_count(), 0);
assert_eq!(memory.symbol_count(), 0);
memory.store_symbols("a", "b").unwrap();
assert_eq!(memory.item_count(), 1);
assert_eq!(memory.symbol_count(), 2); }
}