strange_loop/
types.rs

1//! Core types and traits for strange loop implementation
2
3use crate::error::{LoopError, Result};
4use nalgebra::{Matrix3, Vector3 as NalgebraVector3};
5#[cfg(feature = "quantum")]
6use num_complex::Complex64;
7use parking_lot::RwLock;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::sync::Arc;
11use std::time::Instant;
12
13/// Type alias for 3D vectors used in strange attractors (custom implementation)
14pub use crate::vector3d::Vector3D;
15
16/// Type alias for nalgebra 3D vectors used in specific computations
17pub type NalgebraVec3 = NalgebraVector3<f64>;
18
19/// Type alias for 3D matrices used in transformations
20pub type Matrix3D = Matrix3<f64>;
21
22/// Type alias for complex vectors used in quantum computations
23#[cfg(feature = "quantum")]
24pub type ComplexVector = Vec<Complex64>;
25
26/// Type alias for quantum amplitude
27#[cfg(feature = "quantum")]
28pub type QuantumAmplitude = Complex64;
29
30/// Context for strange loop execution - contains mutable state
31pub type Context = HashMap<String, f64>;
32
33/// Policy parameters that control loop behavior
34#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
35pub struct Policy {
36    /// Step size for gradient descent
37    pub step_size: f64,
38    /// Regularization parameter
39    pub regularization: f64,
40    /// Learning rate decay
41    pub decay_rate: f64,
42    /// Momentum parameter
43    pub momentum: f64,
44}
45
46impl Policy {
47    /// Create a new policy with default parameters
48    pub fn new(step_size: f64) -> Self {
49        Self {
50            step_size,
51            regularization: 0.0,
52            decay_rate: 0.99,
53            momentum: 0.9,
54        }
55    }
56
57    /// Validate policy parameters
58    pub fn validate(&self) -> Result<()> {
59        if self.step_size <= 0.0 || self.step_size > 1.0 {
60            return Err(LoopError::invalid_policy("step_size must be in (0, 1]"));
61        }
62        if self.regularization < 0.0 {
63            return Err(LoopError::invalid_policy("regularization must be non-negative"));
64        }
65        if self.decay_rate <= 0.0 || self.decay_rate > 1.0 {
66            return Err(LoopError::invalid_policy("decay_rate must be in (0, 1]"));
67        }
68        if self.momentum < 0.0 || self.momentum >= 1.0 {
69            return Err(LoopError::invalid_policy("momentum must be in [0, 1)"));
70        }
71        Ok(())
72    }
73
74    /// Apply exponential decay to step size
75    #[inline(always)]
76    pub fn decay_step_size(&mut self) {
77        self.step_size *= self.decay_rate;
78    }
79
80    /// Clamp all parameters to valid ranges
81    pub fn clamp(&mut self) {
82        self.step_size = self.step_size.clamp(1e-10, 1.0);
83        self.regularization = self.regularization.max(0.0);
84        self.decay_rate = self.decay_rate.clamp(0.01, 1.0);
85        self.momentum = self.momentum.clamp(0.0, 0.99);
86    }
87}
88
89/// Delta changes to policy parameters
90#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
91pub struct PolicyDelta {
92    /// Change in step size
93    pub delta_step_size: f64,
94    /// Change in regularization
95    pub delta_regularization: f64,
96    /// Change in decay rate
97    pub delta_decay_rate: f64,
98    /// Change in momentum
99    pub delta_momentum: f64,
100    /// Confidence in the proposed changes [0, 1]
101    pub confidence: f64,
102}
103
104impl PolicyDelta {
105    /// Create a new policy delta
106    pub fn new(
107        delta_step_size: f64,
108        delta_regularization: f64,
109        confidence: f64,
110    ) -> Self {
111        Self {
112            delta_step_size,
113            delta_regularization,
114            delta_decay_rate: 0.0,
115            delta_momentum: 0.0,
116            confidence: confidence.clamp(0.0, 1.0),
117        }
118    }
119
120    /// Create a zero delta (no changes)
121    pub fn zero() -> Self {
122        Self {
123            delta_step_size: 0.0,
124            delta_regularization: 0.0,
125            delta_decay_rate: 0.0,
126            delta_momentum: 0.0,
127            confidence: 0.0,
128        }
129    }
130
131    /// Scale all deltas by confidence
132    pub fn scale_by_confidence(&mut self) {
133        let scale = self.confidence;
134        self.delta_step_size *= scale;
135        self.delta_regularization *= scale;
136        self.delta_decay_rate *= scale;
137        self.delta_momentum *= scale;
138    }
139}
140
141/// Trace of a single loop iteration
142#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
143pub struct Trace {
144    /// State before the action
145    pub state_before: f64,
146    /// State after the action
147    pub state_after: f64,
148    /// Performance score (lower is better)
149    pub score: f64,
150    /// Gradient norm
151    pub gradient_norm: f64,
152    /// Timestamp in nanoseconds
153    pub timestamp_ns: u128,
154    /// Iteration number
155    pub iteration: usize,
156}
157
158impl Trace {
159    /// Create a new trace
160    pub fn new(
161        state_before: f64,
162        state_after: f64,
163        score: f64,
164        iteration: usize,
165    ) -> Self {
166        Self {
167            state_before,
168            state_after,
169            score,
170            gradient_norm: (state_after - state_before).abs(),
171            timestamp_ns: Instant::now().elapsed().as_nanos(),
172            iteration,
173        }
174    }
175
176    /// Calculate the improvement (positive = better)
177    #[inline(always)]
178    pub fn improvement(&self) -> f64 {
179        self.state_before.abs() - self.state_after.abs()
180    }
181
182    /// Check if this represents progress
183    #[inline(always)]
184    pub fn is_progress(&self) -> bool {
185        self.improvement() > 0.0
186    }
187
188    /// Calculate Lipschitz constant estimate
189    #[inline(always)]
190    pub fn lipschitz_estimate(&self, input_delta: f64) -> f64 {
191        if input_delta.abs() < f64::EPSILON {
192            return 0.0;
193        }
194        self.gradient_norm / input_delta.abs()
195    }
196}
197
198/// Configuration for strange loop execution
199#[derive(Clone, Debug, Serialize, Deserialize)]
200pub struct LoopConfig {
201    /// Maximum number of iterations
202    pub max_iterations: usize,
203    /// Maximum execution time in nanoseconds
204    pub max_duration_ns: u128,
205    /// Convergence threshold
206    pub convergence_threshold: f64,
207    /// Lipschitz constant limit
208    pub lipschitz_constant: f64,
209    /// Enable temporal consciousness features
210    pub enable_consciousness: bool,
211    /// Enable quantum computing features
212    pub enable_quantum: bool,
213    /// Enable SIMD optimizations
214    pub enable_simd: bool,
215}
216
217impl Default for LoopConfig {
218    fn default() -> Self {
219        Self {
220            max_iterations: 10_000,
221            max_duration_ns: 100_000_000, // 100ms
222            convergence_threshold: 1e-9,
223            lipschitz_constant: 0.9,
224            enable_consciousness: false,
225            enable_quantum: false,
226            enable_simd: true,
227        }
228    }
229}
230
231impl LoopConfig {
232    /// Create a high-performance configuration
233    pub fn high_performance() -> Self {
234        Self {
235            max_iterations: 1_000_000,
236            max_duration_ns: 10_000_000, // 10ms
237            convergence_threshold: 1e-12,
238            lipschitz_constant: 0.95,
239            enable_consciousness: true,
240            enable_quantum: true,
241            enable_simd: true,
242        }
243    }
244
245    /// Create a configuration for consciousness experiments
246    pub fn consciousness_mode() -> Self {
247        Self {
248            max_iterations: 100_000,
249            max_duration_ns: 1_000_000_000, // 1s
250            convergence_threshold: 1e-6,
251            lipschitz_constant: 0.8,
252            enable_consciousness: true,
253            enable_quantum: true,
254            enable_simd: true,
255        }
256    }
257
258    /// Validate configuration parameters
259    pub fn validate(&self) -> Result<()> {
260        if self.max_iterations == 0 {
261            return Err(LoopError::invalid_policy("max_iterations must be > 0"));
262        }
263        if self.max_duration_ns == 0 {
264            return Err(LoopError::invalid_policy("max_duration_ns must be > 0"));
265        }
266        if self.convergence_threshold <= 0.0 {
267            return Err(LoopError::invalid_policy("convergence_threshold must be > 0"));
268        }
269        if self.lipschitz_constant <= 0.0 || self.lipschitz_constant >= 1.0 {
270            return Err(LoopError::invalid_policy("lipschitz_constant must be in (0, 1)"));
271        }
272        Ok(())
273    }
274}
275
276/// Trait for objects that can reason about state and take actions
277pub trait Reasoner: Send + Sync {
278    /// Perform one reasoning step
279    fn act(&mut self, context: &mut Context) -> Result<Trace>;
280
281    /// Get current policy
282    fn policy(&self) -> &Policy;
283
284    /// Update policy
285    fn update_policy(&mut self, policy: Policy) -> Result<()>;
286
287    /// Get reasoner type name
288    fn name(&self) -> &'static str;
289}
290
291/// Trait for critics that evaluate reasoning traces
292pub trait Critic: Send + Sync {
293    /// Evaluate a trace and return a loss value (lower is better)
294    fn evaluate(&self, trace: &Trace) -> f64;
295
296    /// Propose policy changes based on trace
297    fn propose_delta(&self, trace: &Trace) -> PolicyDelta;
298
299    /// Get critic name
300    fn name(&self) -> &'static str;
301}
302
303/// Trait for reflectors that apply policy changes
304pub trait Reflector: Send + Sync {
305    /// Apply policy delta with safety checks
306    fn apply(&self, policy: &mut Policy, delta: &PolicyDelta) -> Result<()>;
307
308    /// Get reflector name
309    fn name(&self) -> &'static str;
310}
311
312/// Main strange loop execution engine
313pub struct StrangeLoop<R: Reasoner, C: Critic, F: Reflector> {
314    reasoner: Arc<RwLock<R>>,
315    critic: C,
316    reflector: F,
317    config: LoopConfig,
318    iteration_count: usize,
319    start_time: Option<Instant>,
320}
321
322impl<R: Reasoner, C: Critic, F: Reflector> StrangeLoop<R, C, F> {
323    /// Create a new strange loop
324    pub fn new(reasoner: R, critic: C, reflector: F, config: LoopConfig) -> Self {
325        config.validate().expect("Invalid configuration");
326        Self {
327            reasoner: Arc::new(RwLock::new(reasoner)),
328            critic,
329            reflector,
330            config,
331            iteration_count: 0,
332            start_time: None,
333        }
334    }
335
336    /// Run the strange loop until convergence or timeout
337    pub fn run(&mut self, context: &mut Context) -> Result<LoopResult> {
338        self.start_time = Some(Instant::now());
339        let start_time = self.start_time.unwrap();
340        let mut last_score = f64::INFINITY;
341        let mut traces = Vec::with_capacity(1000);
342
343        for i in 0..self.config.max_iterations {
344            self.iteration_count = i;
345
346            // Check timeout
347            if start_time.elapsed().as_nanos() > self.config.max_duration_ns {
348                return Err(LoopError::timeout(start_time.elapsed().as_nanos()));
349            }
350
351            // Execute reasoning step
352            let trace = {
353                let mut reasoner = self.reasoner.write();
354                reasoner.act(context)?
355            };
356
357            // Evaluate trace
358            let loss = self.critic.evaluate(&trace);
359            traces.push(trace.clone());
360
361            // Check convergence
362            let delta_score = (last_score - loss).abs();
363            if delta_score < self.config.convergence_threshold {
364                return Ok(LoopResult {
365                    iterations: i + 1,
366                    final_score: loss,
367                    duration_ns: start_time.elapsed().as_nanos(),
368                    converged: true,
369                    traces,
370                });
371            }
372
373            // Check Lipschitz continuity
374            if i > 0 {
375                let input_delta = 1.0; // Simplified for scalar case
376                let lipschitz = trace.lipschitz_estimate(input_delta);
377                if lipschitz > self.config.lipschitz_constant {
378                    return Err(LoopError::lipschitz_violation(
379                        lipschitz,
380                        self.config.lipschitz_constant,
381                    ));
382                }
383            }
384
385            // Apply meta-learning
386            let delta = self.critic.propose_delta(&trace);
387            {
388                let mut reasoner = self.reasoner.write();
389                let mut policy = reasoner.policy().clone();
390                self.reflector.apply(&mut policy, &delta)?;
391                reasoner.update_policy(policy)?;
392            }
393
394            last_score = loss;
395
396            // Yield control periodically for better concurrency
397            if i % 1000 == 0 {
398                std::hint::spin_loop();
399            }
400        }
401
402        // Reached max iterations without convergence
403        Err(LoopError::convergence_failure(self.config.max_iterations))
404    }
405
406    /// Get current iteration count
407    pub fn iteration_count(&self) -> usize {
408        self.iteration_count
409    }
410
411    /// Get configuration
412    pub fn config(&self) -> &LoopConfig {
413        &self.config
414    }
415
416    /// Get reasoner reference
417    pub fn reasoner(&self) -> Arc<RwLock<R>> {
418        Arc::clone(&self.reasoner)
419    }
420}
421
422/// Result of strange loop execution
423#[derive(Clone, Debug, Serialize, Deserialize)]
424pub struct LoopResult {
425    /// Number of iterations completed
426    pub iterations: usize,
427    /// Final score achieved
428    pub final_score: f64,
429    /// Total execution time in nanoseconds
430    pub duration_ns: u128,
431    /// Whether the loop converged
432    pub converged: bool,
433    /// Trace of all iterations
434    pub traces: Vec<Trace>,
435}
436
437impl LoopResult {
438    /// Get average iterations per second
439    pub fn iterations_per_second(&self) -> f64 {
440        if self.duration_ns == 0 {
441            return 0.0;
442        }
443        (self.iterations as f64) / (self.duration_ns as f64 / 1_000_000_000.0)
444    }
445
446    /// Get convergence rate
447    pub fn convergence_rate(&self) -> f64 {
448        if self.traces.len() < 2 {
449            return 0.0;
450        }
451        let initial_score = self.traces[0].score;
452        let improvement = initial_score - self.final_score;
453        improvement / (self.iterations as f64)
454    }
455}
456
457/// Simple scalar reasoner implementation
458#[derive(Clone, Debug)]
459pub struct ScalarReasoner {
460    target: f64,
461    policy: Policy,
462    momentum: f64,
463}
464
465impl ScalarReasoner {
466    /// Create a new scalar reasoner
467    pub fn new(target: f64, step_size: f64) -> Self {
468        Self {
469            target,
470            policy: Policy::new(step_size),
471            momentum: 0.0,
472        }
473    }
474}
475
476impl Reasoner for ScalarReasoner {
477    fn act(&mut self, context: &mut Context) -> Result<Trace> {
478        let x = *context.get("x").unwrap_or(&0.0);
479        let gradient = (x - self.target) + self.policy.regularization * x;
480
481        // Apply momentum
482        self.momentum = self.policy.momentum * self.momentum + (1.0 - self.policy.momentum) * gradient;
483
484        let x_new = x - self.policy.step_size * self.momentum;
485        context.insert("x".to_string(), x_new);
486
487        let score = (x_new - self.target).abs();
488
489        Ok(Trace::new(x, x_new, score, 0))
490    }
491
492    fn policy(&self) -> &Policy {
493        &self.policy
494    }
495
496    fn update_policy(&mut self, policy: Policy) -> Result<()> {
497        policy.validate()?;
498        self.policy = policy;
499        Ok(())
500    }
501
502    fn name(&self) -> &'static str {
503        "ScalarReasoner"
504    }
505}
506
507/// Simple critic implementation
508#[derive(Clone, Debug)]
509pub struct SimpleCritic {
510    adaptation_rate: f64,
511}
512
513impl SimpleCritic {
514    /// Create a new simple critic
515    pub fn new() -> Self {
516        Self {
517            adaptation_rate: 0.1,
518        }
519    }
520
521    /// Create with custom adaptation rate
522    pub fn with_adaptation_rate(rate: f64) -> Self {
523        Self {
524            adaptation_rate: rate.clamp(0.01, 1.0),
525        }
526    }
527}
528
529impl Default for SimpleCritic {
530    fn default() -> Self {
531        Self::new()
532    }
533}
534
535impl Critic for SimpleCritic {
536    fn evaluate(&self, trace: &Trace) -> f64 {
537        // Combine multiple factors: score, gradient stability, and progress
538        trace.score + 0.1 * trace.gradient_norm + if trace.is_progress() { 0.0 } else { 0.5 }
539    }
540
541    fn propose_delta(&self, trace: &Trace) -> PolicyDelta {
542        let improvement = trace.improvement();
543        let gradient_stability = 1.0 / (1.0 + trace.gradient_norm);
544
545        // Adaptive step size adjustment
546        let delta_step = if improvement > 0.0 {
547            self.adaptation_rate * gradient_stability
548        } else {
549            -self.adaptation_rate * 0.5
550        };
551
552        // Regularization adjustment based on stability
553        let delta_reg = if trace.gradient_norm > 1.0 {
554            self.adaptation_rate * 0.1
555        } else {
556            -self.adaptation_rate * 0.05
557        };
558
559        let confidence = gradient_stability * if improvement > 0.0 { 0.9 } else { 0.3 };
560
561        PolicyDelta::new(delta_step, delta_reg, confidence)
562    }
563
564    fn name(&self) -> &'static str {
565        "SimpleCritic"
566    }
567}
568
569/// Safe reflector with bounded updates
570#[derive(Clone, Debug)]
571pub struct SafeReflector {
572    max_change_rate: f64,
573}
574
575impl SafeReflector {
576    /// Create a new safe reflector
577    pub fn new() -> Self {
578        Self {
579            max_change_rate: 0.2, // Maximum 20% change per step
580        }
581    }
582
583    /// Create with custom maximum change rate
584    pub fn with_max_change_rate(rate: f64) -> Self {
585        Self {
586            max_change_rate: rate.clamp(0.01, 1.0),
587        }
588    }
589}
590
591impl Default for SafeReflector {
592    fn default() -> Self {
593        Self::new()
594    }
595}
596
597impl Reflector for SafeReflector {
598    fn apply(&self, policy: &mut Policy, delta: &PolicyDelta) -> Result<()> {
599        let alpha = delta.confidence.clamp(0.0, 1.0);
600
601        // Apply bounded changes
602        let max_step_change = policy.step_size * self.max_change_rate;
603        let step_change = (alpha * delta.delta_step_size).clamp(-max_step_change, max_step_change);
604        policy.step_size = (policy.step_size + step_change).clamp(1e-10, 1.0);
605
606        let max_reg_change = self.max_change_rate;
607        let reg_change = (alpha * delta.delta_regularization).clamp(-max_reg_change, max_reg_change);
608        policy.regularization = (policy.regularization + reg_change).max(0.0);
609
610        // Apply decay
611        policy.decay_step_size();
612        policy.clamp();
613        policy.validate()?;
614
615        Ok(())
616    }
617
618    fn name(&self) -> &'static str {
619        "SafeReflector"
620    }
621}
622
623#[cfg(test)]
624mod tests {
625    use super::*;
626
627    #[test]
628    fn test_policy_validation() {
629        let mut policy = Policy::new(0.1);
630        assert!(policy.validate().is_ok());
631
632        policy.step_size = -0.1;
633        assert!(policy.validate().is_err());
634
635        policy.step_size = 0.1;
636        policy.regularization = -0.1;
637        assert!(policy.validate().is_err());
638    }
639
640    #[test]
641    fn test_policy_delta() {
642        let mut delta = PolicyDelta::new(0.1, 0.05, 0.8);
643        delta.scale_by_confidence();
644        assert!((delta.delta_step_size - 0.08).abs() < 1e-10);
645        assert!((delta.delta_regularization - 0.04).abs() < 1e-10);
646    }
647
648    #[test]
649    fn test_trace_methods() {
650        let trace = Trace::new(10.0, 5.0, 5.0, 0);
651        assert_eq!(trace.improvement(), 5.0);
652        assert!(trace.is_progress());
653
654        let lipschitz = trace.lipschitz_estimate(1.0);
655        assert_eq!(lipschitz, 5.0);
656    }
657
658    #[test]
659    fn test_scalar_reasoner() {
660        let mut reasoner = ScalarReasoner::new(0.0, 0.1);
661        let mut context = HashMap::from([("x".to_string(), 10.0)]);
662
663        let trace = reasoner.act(&mut context).unwrap();
664        let new_x = context.get("x").unwrap();
665
666        assert!(*new_x < 10.0); // Should move toward target
667        assert!(trace.is_progress());
668    }
669
670    #[test]
671    fn test_simple_critic() {
672        let critic = SimpleCritic::new();
673        let trace = Trace::new(10.0, 5.0, 5.0, 0);
674
675        let loss = critic.evaluate(&trace);
676        assert!(loss > 0.0);
677
678        let delta = critic.propose_delta(&trace);
679        assert!(delta.confidence > 0.0);
680    }
681
682    #[test]
683    fn test_safe_reflector() {
684        let reflector = SafeReflector::new();
685        let mut policy = Policy::new(0.1);
686        let delta = PolicyDelta::new(0.5, 0.1, 0.8); // Large change
687
688        let old_step_size = policy.step_size;
689        reflector.apply(&mut policy, &delta).unwrap();
690
691        // Change should be bounded
692        let change = (policy.step_size - old_step_size).abs();
693        assert!(change <= old_step_size * 0.2); // Max 20% change
694    }
695
696    #[test]
697    fn test_loop_config_validation() {
698        let config = LoopConfig::default();
699        assert!(config.validate().is_ok());
700
701        let mut bad_config = config.clone();
702        bad_config.max_iterations = 0;
703        assert!(bad_config.validate().is_err());
704    }
705}