#![allow(clippy::too_many_arguments)]
#![allow(dead_code)]
use scirs2_core::numeric::Float;
use std::collections::{HashMap, VecDeque};
use std::time::{Duration, Instant};
#[derive(Debug)]
pub struct NeuromorphicMemory<F: Float> {
pub short_term_memory: ShortTermMemory<F>,
pub long_term_memory: LongTermMemory<F>,
pub consolidation_controller: ConsolidationController<F>,
pub recall_mechanisms: RecallMechanisms<F>,
}
#[derive(Debug)]
pub struct ShortTermMemory<F: Float> {
pub working_memory: VecDeque<MemoryTrace<F>>,
pub capacity: usize,
pub decay_rate: F,
pub refresh_controller: RefreshController<F>,
}
#[derive(Debug)]
pub struct LongTermMemory<F: Float> {
pub memory_traces: HashMap<String, MemoryTrace<F>>,
pub decay_rate: F,
pub consolidation_threshold: F,
}
#[derive(Debug, Clone)]
pub struct MemoryTrace<F: Float> {
pub id: String,
pub content: Vec<F>,
pub strength: F,
pub timestamp: Instant,
pub access_count: usize,
pub consolidation_level: F,
}
#[derive(Debug)]
pub struct ConsolidationController<F: Float> {
pub policies: Vec<ConsolidationPolicy>,
pub thresholds: HashMap<String, F>,
pub replay_controller: ReplayController<F>,
}
#[derive(Debug, Clone)]
pub enum ConsolidationPolicy {
TimeBased { interval: Duration },
StrengthBased { threshold: f64 },
AccessBased { min_access: usize },
Combined { policies: Vec<ConsolidationPolicy> },
}
#[derive(Debug)]
pub struct ReplayController<F: Float> {
pub replay_sequences: VecDeque<ReplaySequence<F>>,
pub replay_patterns: Vec<ReplayPattern>,
pub scheduling: ReplayScheduling,
}
#[derive(Debug, Clone)]
pub struct ReplaySequence<F: Float> {
pub memory_ids: Vec<String>,
pub replay_strength: F,
pub temporal_compression: F,
}
#[derive(Debug, Clone)]
pub enum ReplayPattern {
Forward,
Backward,
Random,
Priority,
}
#[derive(Debug, Clone)]
pub enum ReplayScheduling {
Continuous,
Sleep,
Idle,
Triggered,
}
#[derive(Debug)]
pub struct RecallMechanisms<F: Float> {
pub associative_recall: AssociativeRecall<F>,
pub content_recall: ContentAddressableRecall<F>,
pub context_recall: ContextDependentRecall<F>,
}
#[derive(Debug)]
pub struct AssociativeRecall<F: Float> {
pub association_matrix: HashMap<String, HashMap<String, F>>,
pub recall_threshold: F,
}
#[derive(Debug)]
pub struct ContentAddressableRecall<F: Float> {
pub content_index: HashMap<Vec<F>, String>,
pub similarity_threshold: F,
}
#[derive(Debug)]
pub struct ContextDependentRecall<F: Float> {
pub context_associations: HashMap<String, Vec<String>>,
pub context_weights: HashMap<String, F>,
}
#[derive(Debug)]
pub struct RefreshController<F: Float> {
pub refresh_rate: Duration,
pub last_refresh: Instant,
pub refresh_strength: F,
}
impl<F: Float> NeuromorphicMemory<F> {
pub fn new(capacity: usize) -> Self {
Self {
short_term_memory: ShortTermMemory::new(capacity),
long_term_memory: LongTermMemory::new(),
consolidation_controller: ConsolidationController::new(),
recall_mechanisms: RecallMechanisms::new(),
}
}
pub fn store(&mut self, content: Vec<F>, strength: F) -> crate::error::Result<String> {
let memory_id = format!("mem_{}", Instant::now().elapsed().as_nanos());
let trace = MemoryTrace {
id: memory_id.clone(),
content,
strength,
timestamp: Instant::now(),
access_count: 0,
consolidation_level: F::zero(),
};
self.short_term_memory.store(trace)?;
Ok(memory_id)
}
pub fn recall(&mut self, memory_id: &str) -> crate::error::Result<Option<MemoryTrace<F>>> {
if let Some(trace) = self.short_term_memory.recall(memory_id)? {
return Ok(Some(trace));
}
if let Some(trace) = self.long_term_memory.recall(memory_id)? {
return Ok(Some(trace));
}
Ok(None)
}
pub fn update(&mut self, dt: Duration) -> crate::error::Result<()> {
self.short_term_memory.update(dt)?;
self.long_term_memory.update(dt)?;
self.consolidation_controller
.update(&mut self.short_term_memory, &mut self.long_term_memory)?;
Ok(())
}
}
impl<F: Float> ShortTermMemory<F> {
pub fn new(capacity: usize) -> Self {
Self {
working_memory: VecDeque::with_capacity(capacity),
capacity,
decay_rate: F::from(0.95).expect("Failed to convert constant to float"),
refresh_controller: RefreshController::new(),
}
}
pub fn store(&mut self, trace: MemoryTrace<F>) -> crate::error::Result<()> {
if self.working_memory.len() >= self.capacity {
self.working_memory.pop_front();
}
self.working_memory.push_back(trace);
Ok(())
}
pub fn recall(&mut self, memory_id: &str) -> crate::error::Result<Option<MemoryTrace<F>>> {
for trace in &mut self.working_memory {
if trace.id == memory_id {
trace.access_count += 1;
return Ok(Some(trace.clone()));
}
}
Ok(None)
}
pub fn update(&mut self, dt: Duration) -> crate::error::Result<()> {
for trace in &mut self.working_memory {
trace.strength = trace.strength * self.decay_rate;
}
self.working_memory.retain(|trace| {
trace.strength > F::from(0.01).expect("Failed to convert constant to float")
});
self.refresh_controller.update(dt)?;
Ok(())
}
}
impl<F: Float> LongTermMemory<F> {
pub fn new() -> Self {
Self {
memory_traces: HashMap::new(),
decay_rate: F::from(0.999).expect("Failed to convert constant to float"),
consolidation_threshold: F::from(0.8).expect("Failed to convert constant to float"),
}
}
pub fn store(&mut self, trace: MemoryTrace<F>) -> crate::error::Result<()> {
self.memory_traces.insert(trace.id.clone(), trace);
Ok(())
}
pub fn recall(&mut self, memory_id: &str) -> crate::error::Result<Option<MemoryTrace<F>>> {
if let Some(trace) = self.memory_traces.get_mut(memory_id) {
trace.access_count += 1;
Ok(Some(trace.clone()))
} else {
Ok(None)
}
}
pub fn update(&mut self, dt: Duration) -> crate::error::Result<()> {
for trace in self.memory_traces.values_mut() {
trace.strength = trace.strength * self.decay_rate;
}
self.memory_traces.retain(|_, trace| {
trace.strength > F::from(0.001).expect("Failed to convert constant to float")
});
Ok(())
}
}
impl<F: Float> ConsolidationController<F> {
pub fn new() -> Self {
Self {
policies: vec![ConsolidationPolicy::StrengthBased { threshold: 0.5 }],
thresholds: HashMap::new(),
replay_controller: ReplayController::new(),
}
}
pub fn update(
&mut self,
short_term: &mut ShortTermMemory<F>,
long_term: &mut LongTermMemory<F>,
) -> crate::error::Result<()> {
let mut traces_to_consolidate = Vec::new();
for trace in &short_term.working_memory {
if self.should_consolidate(trace)? {
traces_to_consolidate.push(trace.clone());
}
}
for trace in traces_to_consolidate {
long_term.store(trace.clone())?;
short_term.working_memory.retain(|t| t.id != trace.id);
}
Ok(())
}
fn should_consolidate(&self, trace: &MemoryTrace<F>) -> crate::error::Result<bool> {
for policy in &self.policies {
match policy {
ConsolidationPolicy::StrengthBased { threshold } => {
if trace.strength > F::from(*threshold).expect("Failed to convert to float") {
return Ok(true);
}
}
ConsolidationPolicy::AccessBased { min_access } => {
if trace.access_count >= *min_access {
return Ok(true);
}
}
ConsolidationPolicy::TimeBased { interval } => {
if trace.timestamp.elapsed() > *interval {
return Ok(true);
}
}
_ => {}
}
}
Ok(false)
}
}
impl<F: Float> RefreshController<F> {
pub fn new() -> Self {
Self {
refresh_rate: Duration::from_millis(100),
last_refresh: Instant::now(),
refresh_strength: F::from(0.1).expect("Failed to convert constant to float"),
}
}
pub fn update(&mut self, dt: Duration) -> crate::error::Result<()> {
self.last_refresh += dt;
Ok(())
}
}
impl<F: Float> ReplayController<F> {
pub fn new() -> Self {
Self {
replay_sequences: VecDeque::new(),
replay_patterns: vec![ReplayPattern::Forward],
scheduling: ReplayScheduling::Idle,
}
}
}
impl<F: Float> RecallMechanisms<F> {
pub fn new() -> Self {
Self {
associative_recall: AssociativeRecall::new(),
content_recall: ContentAddressableRecall::new(),
context_recall: ContextDependentRecall::new(),
}
}
}
impl<F: Float> AssociativeRecall<F> {
pub fn new() -> Self {
Self {
association_matrix: HashMap::new(),
recall_threshold: F::from(0.7).expect("Failed to convert constant to float"),
}
}
}
impl<F: Float> ContentAddressableRecall<F> {
pub fn new() -> Self {
Self {
content_index: HashMap::new(),
similarity_threshold: F::from(0.8).expect("Failed to convert constant to float"),
}
}
}
impl<F: Float> ContextDependentRecall<F> {
pub fn new() -> Self {
Self {
context_associations: HashMap::new(),
context_weights: HashMap::new(),
}
}
}