Skip to main content

midstreamer_strange_loop/
lib.rs

1//! # Strange-Loop
2//!
3//! Self-referential systems and meta-learning inspired by Douglas Hofstadter.
4//!
5//! ## Features
6//! - Multi-level meta-learning
7//! - Self-modification with safety constraints
8//! - Recursive cognition
9//! - Tangled hierarchies
10//! - Meta-knowledge extraction
11
12use dashmap::DashMap;
13use midstreamer_attractor::{AttractorAnalyzer, PhasePoint};
14use midstreamer_neural_solver::TemporalNeuralSolver;
15use midstreamer_temporal_compare::TemporalComparator;
16use serde::{Deserialize, Serialize};
17use std::collections::HashMap;
18use std::sync::Arc;
19use thiserror::Error;
20
21/// Strange loop errors
22#[derive(Debug, Error)]
23pub enum StrangeLoopError {
24    #[error("Max meta-depth exceeded: {0}")]
25    MaxDepthExceeded(usize),
26
27    #[error("Safety constraint violated: {0}")]
28    SafetyViolation(String),
29
30    #[error("Invalid modification: {0}")]
31    InvalidModification(String),
32
33    #[error("Meta-learning failed: {0}")]
34    MetaLearningFailed(String),
35}
36
37/// Meta-level in the learning hierarchy
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
39pub struct MetaLevel(pub usize);
40
41impl MetaLevel {
42    pub fn base() -> Self {
43        MetaLevel(0)
44    }
45
46    pub fn next(&self) -> Self {
47        MetaLevel(self.0 + 1)
48    }
49
50    pub fn level(&self) -> usize {
51        self.0
52    }
53}
54
55/// Meta-knowledge extracted from lower levels
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct MetaKnowledge {
58    pub level: MetaLevel,
59    pub pattern: String,
60    pub confidence: f64,
61    pub applications: Vec<String>,
62    pub learned_at: u64,
63}
64
65impl MetaKnowledge {
66    pub fn new(level: MetaLevel, pattern: String, confidence: f64) -> Self {
67        Self {
68            level,
69            pattern,
70            confidence,
71            applications: Vec::new(),
72            learned_at: std::time::SystemTime::now()
73                .duration_since(std::time::UNIX_EPOCH)
74                .unwrap()
75                .as_millis() as u64,
76        }
77    }
78}
79
80/// Safety constraint for self-modification
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct SafetyConstraint {
83    pub name: String,
84    pub formula: String, // Simplified temporal formula
85    pub enforced: bool,
86}
87
88impl SafetyConstraint {
89    pub fn new(name: impl Into<String>, formula: impl Into<String>) -> Self {
90        Self {
91            name: name.into(),
92            formula: formula.into(),
93            enforced: true,
94        }
95    }
96
97    pub fn always_safe() -> Self {
98        Self::new("always_safe", "G(safe)")
99    }
100
101    pub fn eventually_terminates() -> Self {
102        Self::new("eventually_terminates", "F(done)")
103    }
104}
105
106/// Modification rule for self-improvement
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct ModificationRule {
109    pub name: String,
110    pub trigger: String,
111    pub action: String,
112    pub safety_check: bool,
113}
114
115impl ModificationRule {
116    pub fn new(
117        name: impl Into<String>,
118        trigger: impl Into<String>,
119        action: impl Into<String>,
120    ) -> Self {
121        Self {
122            name: name.into(),
123            trigger: trigger.into(),
124            action: action.into(),
125            safety_check: true,
126        }
127    }
128}
129
130/// Statistics about meta-learning performance
131#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct MetaLearningSummary {
133    pub total_levels: usize,
134    pub total_knowledge: usize,
135    pub total_modifications: usize,
136    pub safety_violations: usize,
137    pub learning_iterations: u64,
138}
139
140/// Configuration for strange loop
141#[derive(Debug, Clone)]
142pub struct StrangeLoopConfig {
143    pub max_meta_depth: usize,
144    pub enable_self_modification: bool,
145    pub max_modifications_per_cycle: usize,
146    pub safety_check_enabled: bool,
147}
148
149impl Default for StrangeLoopConfig {
150    fn default() -> Self {
151        Self {
152            max_meta_depth: 3,
153            enable_self_modification: false, // Disabled by default for safety
154            max_modifications_per_cycle: 5,
155            safety_check_enabled: true,
156        }
157    }
158}
159
160/// The main strange loop structure
161pub struct StrangeLoop {
162    config: StrangeLoopConfig,
163    meta_knowledge: Arc<DashMap<MetaLevel, Vec<MetaKnowledge>>>,
164    safety_constraints: Vec<SafetyConstraint>,
165    modification_rules: Vec<ModificationRule>,
166    learning_iterations: Arc<DashMap<MetaLevel, u64>>,
167    modification_count: usize,
168    safety_violations: usize,
169
170    // Integrated components (reserved for future use)
171    #[allow(dead_code)]
172    temporal_comparator: TemporalComparator<String>,
173    attractor_analyzer: AttractorAnalyzer,
174    #[allow(dead_code)]
175    temporal_solver: TemporalNeuralSolver,
176}
177
178impl StrangeLoop {
179    /// Create a new strange loop
180    pub fn new(config: StrangeLoopConfig) -> Self {
181        Self {
182            config,
183            meta_knowledge: Arc::new(DashMap::new()),
184            safety_constraints: vec![
185                SafetyConstraint::always_safe(),
186                SafetyConstraint::eventually_terminates(),
187            ],
188            modification_rules: Vec::new(),
189            learning_iterations: Arc::new(DashMap::new()),
190            modification_count: 0,
191            safety_violations: 0,
192            temporal_comparator: TemporalComparator::new(1000, 10000),
193            attractor_analyzer: AttractorAnalyzer::new(3, 10000),
194            temporal_solver: TemporalNeuralSolver::default(),
195        }
196    }
197
198    /// Learn at a specific meta-level
199    pub fn learn_at_level(
200        &mut self,
201        level: MetaLevel,
202        data: &[String],
203    ) -> Result<Vec<MetaKnowledge>, StrangeLoopError> {
204        if level.level() > self.config.max_meta_depth {
205            return Err(StrangeLoopError::MaxDepthExceeded(level.level()));
206        }
207
208        // Increment learning iterations
209        self.learning_iterations
210            .entry(level)
211            .and_modify(|v| *v += 1)
212            .or_insert(1);
213
214        // Extract patterns from data
215        let patterns = self.extract_patterns(level, data)?;
216
217        // Store meta-knowledge
218        self.meta_knowledge
219            .entry(level)
220            .or_default()
221            .extend(patterns.clone());
222
223        // If not at max depth, meta-learn from this level
224        if level.level() < self.config.max_meta_depth {
225            self.meta_learn_from_level(level)?;
226        }
227
228        Ok(patterns)
229    }
230
231    /// Meta-learn from a lower level
232    fn meta_learn_from_level(&mut self, level: MetaLevel) -> Result<(), StrangeLoopError> {
233        // Get knowledge from this level
234        let knowledge = if let Some(k) = self.meta_knowledge.get(&level) {
235            k.clone()
236        } else {
237            return Ok(()); // No knowledge to learn from
238        };
239
240        // Extract meta-patterns
241        let meta_patterns: Vec<String> = knowledge.iter().map(|k| k.pattern.clone()).collect();
242
243        // Learn at next level
244        let next_level = level.next();
245        let _meta_knowledge = self.learn_at_level(next_level, &meta_patterns)?;
246
247        Ok(())
248    }
249
250    /// Extract patterns from data
251    fn extract_patterns(
252        &self,
253        level: MetaLevel,
254        data: &[String],
255    ) -> Result<Vec<MetaKnowledge>, StrangeLoopError> {
256        let mut patterns = Vec::new();
257
258        // Find recurring patterns using temporal comparison
259        for i in 0..data.len() {
260            for j in i + 1..data.len() {
261                if data[i] == data[j] {
262                    // Found a repeating pattern
263                    let pattern = MetaKnowledge::new(
264                        level,
265                        data[i].clone(),
266                        0.8, // Confidence
267                    );
268                    patterns.push(pattern);
269                }
270            }
271        }
272
273        // Limit number of patterns
274        patterns.truncate(100);
275
276        Ok(patterns)
277    }
278
279    /// Apply self-modification with safety checks
280    pub fn apply_modification(&mut self, rule: ModificationRule) -> Result<(), StrangeLoopError> {
281        if !self.config.enable_self_modification {
282            return Err(StrangeLoopError::InvalidModification(
283                "Self-modification is disabled".to_string(),
284            ));
285        }
286
287        if self.modification_count >= self.config.max_modifications_per_cycle {
288            return Err(StrangeLoopError::InvalidModification(
289                "Max modifications per cycle reached".to_string(),
290            ));
291        }
292
293        // Safety check
294        if rule.safety_check && self.config.safety_check_enabled {
295            self.check_safety_constraints()?;
296        }
297
298        // Apply modification
299        self.modification_rules.push(rule);
300        self.modification_count += 1;
301
302        Ok(())
303    }
304
305    /// Check all safety constraints
306    fn check_safety_constraints(&mut self) -> Result<(), StrangeLoopError> {
307        for constraint in &self.safety_constraints {
308            if constraint.enforced {
309                // Simplified safety check
310                // In production, this would use the temporal solver
311                if constraint.formula.contains("safe") {
312                    // Always pass for now
313                    continue;
314                }
315            }
316        }
317
318        Ok(())
319    }
320
321    /// Add a safety constraint
322    pub fn add_safety_constraint(&mut self, constraint: SafetyConstraint) {
323        self.safety_constraints.push(constraint);
324    }
325
326    /// Get knowledge at a specific level
327    pub fn get_knowledge_at_level(&self, level: MetaLevel) -> Vec<MetaKnowledge> {
328        self.meta_knowledge
329            .get(&level)
330            .map(|k| k.clone())
331            .unwrap_or_default()
332    }
333
334    /// Get all meta-knowledge
335    pub fn get_all_knowledge(&self) -> HashMap<MetaLevel, Vec<MetaKnowledge>> {
336        let mut result = HashMap::new();
337        for entry in self.meta_knowledge.iter() {
338            result.insert(*entry.key(), entry.value().clone());
339        }
340        result
341    }
342
343    /// Get summary statistics
344    pub fn get_summary(&self) -> MetaLearningSummary {
345        let total_knowledge: usize = self
346            .meta_knowledge
347            .iter()
348            .map(|entry| entry.value().len())
349            .sum();
350
351        MetaLearningSummary {
352            total_levels: self.meta_knowledge.len(),
353            total_knowledge,
354            total_modifications: self.modification_count,
355            safety_violations: self.safety_violations,
356            learning_iterations: self
357                .learning_iterations
358                .iter()
359                .map(|entry| *entry.value())
360                .sum(),
361        }
362    }
363
364    /// Reset the strange loop
365    pub fn reset(&mut self) {
366        self.meta_knowledge.clear();
367        self.learning_iterations.clear();
368        self.modification_rules.clear();
369        self.modification_count = 0;
370        self.safety_violations = 0;
371    }
372
373    /// Analyze behavioral dynamics using attractor analysis
374    pub fn analyze_behavior(
375        &mut self,
376        trajectory_data: Vec<Vec<f64>>,
377    ) -> Result<String, StrangeLoopError> {
378        for (i, point_data) in trajectory_data.iter().enumerate() {
379            let point = PhasePoint::new(point_data.clone(), i as u64);
380            self.attractor_analyzer
381                .add_point(point)
382                .map_err(|e| StrangeLoopError::MetaLearningFailed(e.to_string()))?;
383        }
384
385        let analysis = self
386            .attractor_analyzer
387            .analyze()
388            .map_err(|e| StrangeLoopError::MetaLearningFailed(e.to_string()))?;
389
390        Ok(format!("{:?}", analysis.attractor_type))
391    }
392}
393
394impl Default for StrangeLoop {
395    fn default() -> Self {
396        Self::new(StrangeLoopConfig::default())
397    }
398}
399
400/// Meta-learner trait for types that can engage in meta-learning
401pub trait MetaLearner {
402    fn learn(&mut self, data: &[String]) -> Result<Vec<MetaKnowledge>, StrangeLoopError>;
403    fn meta_level(&self) -> MetaLevel;
404}
405
406#[cfg(test)]
407mod tests {
408    use super::*;
409
410    #[test]
411    fn test_meta_level() {
412        let base = MetaLevel::base();
413        assert_eq!(base.level(), 0);
414
415        let next = base.next();
416        assert_eq!(next.level(), 1);
417    }
418
419    #[test]
420    fn test_strange_loop_creation() {
421        let config = StrangeLoopConfig::default();
422        let strange_loop = StrangeLoop::new(config);
423
424        assert_eq!(strange_loop.modification_count, 0);
425        assert_eq!(strange_loop.safety_violations, 0);
426    }
427
428    #[test]
429    fn test_learning_at_level() {
430        let mut strange_loop = StrangeLoop::default();
431
432        let data = vec![
433            "pattern1".to_string(),
434            "pattern2".to_string(),
435            "pattern1".to_string(),
436        ];
437
438        let result = strange_loop.learn_at_level(MetaLevel::base(), &data);
439        assert!(result.is_ok());
440
441        let knowledge = strange_loop.get_knowledge_at_level(MetaLevel::base());
442        assert!(!knowledge.is_empty());
443    }
444
445    #[test]
446    fn test_max_depth_exceeded() {
447        let mut strange_loop = StrangeLoop::default();
448
449        let data = vec!["test".to_string()];
450        let deep_level = MetaLevel(10); // Exceeds default max of 3
451
452        let result = strange_loop.learn_at_level(deep_level, &data);
453        assert!(result.is_err());
454    }
455
456    #[test]
457    fn test_safety_constraint() {
458        let constraint = SafetyConstraint::always_safe();
459        assert_eq!(constraint.name, "always_safe");
460        assert!(constraint.enforced);
461    }
462
463    #[test]
464    fn test_modification_disabled() {
465        let mut strange_loop = StrangeLoop::default();
466
467        let rule = ModificationRule::new("test_rule", "trigger", "action");
468        let result = strange_loop.apply_modification(rule);
469
470        assert!(result.is_err()); // Should fail because self-modification is disabled
471    }
472
473    #[test]
474    fn test_summary() {
475        let mut strange_loop = StrangeLoop::default();
476
477        let data = vec!["pattern1".to_string(), "pattern2".to_string()];
478        let _ = strange_loop.learn_at_level(MetaLevel::base(), &data);
479
480        let summary = strange_loop.get_summary();
481        assert!(summary.total_knowledge > 0);
482        assert_eq!(summary.safety_violations, 0);
483    }
484
485    #[test]
486    fn test_reset() {
487        let mut strange_loop = StrangeLoop::default();
488
489        let data = vec!["pattern1".to_string()];
490        let _ = strange_loop.learn_at_level(MetaLevel::base(), &data);
491
492        strange_loop.reset();
493
494        let summary = strange_loop.get_summary();
495        assert_eq!(summary.total_knowledge, 0);
496        assert_eq!(summary.total_modifications, 0);
497    }
498}