use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ElasticMemoryGuard {
activation_counts: HashMap<u64, usize>,
content_map: HashMap<u64, String>,
pub pin_threshold: usize,
pub lambda: f64,
pub total_activations: usize,
}
impl ElasticMemoryGuard {
pub fn new(pin_threshold: usize, lambda: f64) -> Self {
Self {
activation_counts: HashMap::new(),
content_map: HashMap::new(),
pin_threshold: pin_threshold.max(1),
lambda: lambda.max(0.0),
total_activations: 0,
}
}
pub fn observe_activation(&mut self, content: &str) {
let fp = fnv1a(content);
*self.activation_counts.entry(fp).or_insert(0) += 1;
self.content_map
.entry(fp)
.or_insert_with(|| content.to_string());
self.total_activations += 1;
}
pub fn activation_count(&self, content: &str) -> usize {
*self.activation_counts.get(&fnv1a(content)).unwrap_or(&0)
}
pub fn is_pinned(&self, content: &str) -> bool {
self.activation_count(content) >= self.pin_threshold
}
pub fn importance(&self, content: &str) -> f64 {
let count = self.activation_count(content);
if count == 0 {
return 0.0;
}
let max = self.activation_counts.values().copied().max().unwrap_or(1) as f64;
count as f64 / max
}
pub fn pinned_contents(&self) -> Vec<&str> {
self.activation_counts
.iter()
.filter(|&(_, count)| *count >= self.pin_threshold)
.filter_map(|(fp, _)| self.content_map.get(fp).map(|s| s.as_str()))
.collect()
}
pub fn unique_entry_count(&self) -> usize {
self.activation_counts.len()
}
}
fn fnv1a(s: &str) -> u64 {
const BASIS: u64 = 0xcbf29ce484222325;
const PRIME: u64 = 0x100000001b3;
s.bytes()
.fold(BASIS, |h, b| (h ^ b as u64).wrapping_mul(PRIME))
}