Skip to main content

microscope_memory/
impulse_control.rs

1//! Impulse control system for filtering incoming stimuli and suppressing irrelevant thoughts.
2//! Implements a gating mechanism based on attention priority and long-term goals.
3
4use std::collections::HashSet;
5use std::sync::{Arc, RwLock};
6use std::time::{SystemTime, UNIX_EPOCH};
7
8/// Represents an incoming stimulus that needs filtering
9#[derive(Debug, Clone)]
10pub struct Stimulus {
11    pub id: String,
12    pub content: String,
13    pub source: String,
14    pub urgency: f32,   // 0.0-1.0
15    pub relevance: f32, // 0.0-1.0
16    pub timestamp: u64,
17    pub suppressed: bool,
18}
19
20/// Impulse control filter based on attention gates
21pub struct ImpulseControl {
22    #[allow(dead_code)]
23    attention_gates: Arc<RwLock<Vec<String>>>,
24    suppression_patterns: Arc<RwLock<HashSet<String>>>,
25    long_term_goals: Vec<String>,
26    attention_budget: f32, // 0.0-1.0, current available attention
27    suppression_threshold: f32,
28}
29
30impl Default for ImpulseControl {
31    fn default() -> Self {
32        Self::new()
33    }
34}
35
36impl ImpulseControl {
37    /// Create a new impulse control system
38    pub fn new() -> Self {
39        Self {
40            attention_gates: Arc::new(RwLock::new(vec![
41                "urgent".to_string(),
42                "important".to_string(),
43                "goal_aligned".to_string(),
44            ])),
45            suppression_patterns: Arc::new(RwLock::new(HashSet::new())),
46            long_term_goals: Vec::new(),
47            attention_budget: 0.8, // start with 80% attention available
48            suppression_threshold: 0.3,
49        }
50    }
51
52    /// Add a long-term goal for relevance filtering
53    pub fn add_goal(&mut self, goal: &str) {
54        self.long_term_goals.push(goal.to_string());
55    }
56
57    /// Add a suppression pattern (keywords to automatically suppress)
58    pub fn add_suppression_pattern(&mut self, pattern: &str) {
59        crate::sync_guard::write_lock(&self.suppression_patterns).insert(pattern.to_lowercase());
60    }
61
62    /// Filter a stimulus based on attention gates and goals
63    pub fn filter_stimulus(&mut self, content: &str, source: &str, urgency: f32) -> Stimulus {
64        let id = format!("stimulus_{}", rand::random::<u32>());
65        let timestamp = SystemTime::now()
66            .duration_since(UNIX_EPOCH)
67            .unwrap()
68            .as_secs();
69
70        let mut suppressed = false;
71        let mut relevance = self.calculate_relevance(content);
72
73        // Check against suppression patterns
74        let content_lower = content.to_lowercase();
75        let patterns = crate::sync_guard::read_lock(&self.suppression_patterns);
76        for pattern in patterns.iter() {
77            if content_lower.contains(pattern) {
78                suppressed = true;
79                relevance = 0.0; // Completely irrelevant if suppressed
80                break;
81            }
82        }
83
84        // Apply attention budget constraint
85        if !suppressed && self.attention_budget < 0.2 {
86            // Low attention budget, suppress less relevant stimuli
87            if relevance < self.suppression_threshold * 2.0 {
88                suppressed = true;
89            }
90        }
91
92        let stimulus = Stimulus {
93            id,
94            content: content.to_string(),
95            source: source.to_string(),
96            urgency,
97            relevance,
98            timestamp,
99            suppressed,
100        };
101
102        // Update attention budget
103        if !stimulus.suppressed && stimulus.relevance > 0.5 {
104            self.attention_budget -= 0.1; // Consume attention
105            self.attention_budget = self.attention_budget.max(0.0);
106        }
107
108        stimulus
109    }
110
111    /// Calculate relevance to long-term goals
112    fn calculate_relevance(&self, content: &str) -> f32 {
113        if self.long_term_goals.is_empty() {
114            return 0.5; // neutral relevance
115        }
116
117        let content_lower = content.to_lowercase();
118        let mut score = 0.0;
119
120        for goal in &self.long_term_goals {
121            let goal_lower = goal.to_lowercase();
122            if content_lower.contains(&goal_lower) {
123                score += 1.0;
124            }
125        }
126
127        // Also check for goal-related keywords
128        let goal_keywords = ["achieve", "progress", "improve", "develop", "complete"];
129        for keyword in &goal_keywords {
130            if content_lower.contains(keyword) {
131                score += 0.5;
132            }
133        }
134
135        (score / (self.long_term_goals.len() as f32 + goal_keywords.len() as f32)).min(1.0)
136    }
137
138    /// Restore attention budget (call periodically)
139    pub fn restore_attention(&mut self, amount: f32) {
140        self.attention_budget += amount;
141        self.attention_budget = self.attention_budget.min(1.0);
142    }
143
144    /// Get statistics about filtering
145    pub fn get_stats(&self) -> (f32, usize) {
146        let patterns = crate::sync_guard::read_lock(&self.suppression_patterns);
147        (self.attention_budget, patterns.len())
148    }
149
150    /// Clear all suppression patterns
151    pub fn clear_patterns(&mut self) {
152        crate::sync_guard::write_lock(&self.suppression_patterns).clear();
153    }
154}
155
156/// Batch filter multiple stimuli
157pub fn batch_filter_stimuli(
158    control: &mut ImpulseControl,
159    stimuli: &[(&str, &str, f32)],
160) -> Vec<Stimulus> {
161    stimuli
162        .iter()
163        .map(|(content, source, urgency)| control.filter_stimulus(content, source, *urgency))
164        .collect()
165}