1use 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
13pub use crate::vector3d::Vector3D;
15
16pub type NalgebraVec3 = NalgebraVector3<f64>;
18
19pub type Matrix3D = Matrix3<f64>;
21
22#[cfg(feature = "quantum")]
24pub type ComplexVector = Vec<Complex64>;
25
26#[cfg(feature = "quantum")]
28pub type QuantumAmplitude = Complex64;
29
30pub type Context = HashMap<String, f64>;
32
33#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
35pub struct Policy {
36 pub step_size: f64,
38 pub regularization: f64,
40 pub decay_rate: f64,
42 pub momentum: f64,
44}
45
46impl Policy {
47 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 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 #[inline(always)]
76 pub fn decay_step_size(&mut self) {
77 self.step_size *= self.decay_rate;
78 }
79
80 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#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
91pub struct PolicyDelta {
92 pub delta_step_size: f64,
94 pub delta_regularization: f64,
96 pub delta_decay_rate: f64,
98 pub delta_momentum: f64,
100 pub confidence: f64,
102}
103
104impl PolicyDelta {
105 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 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 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#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
143pub struct Trace {
144 pub state_before: f64,
146 pub state_after: f64,
148 pub score: f64,
150 pub gradient_norm: f64,
152 pub timestamp_ns: u128,
154 pub iteration: usize,
156}
157
158impl Trace {
159 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 #[inline(always)]
178 pub fn improvement(&self) -> f64 {
179 self.state_before.abs() - self.state_after.abs()
180 }
181
182 #[inline(always)]
184 pub fn is_progress(&self) -> bool {
185 self.improvement() > 0.0
186 }
187
188 #[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#[derive(Clone, Debug, Serialize, Deserialize)]
200pub struct LoopConfig {
201 pub max_iterations: usize,
203 pub max_duration_ns: u128,
205 pub convergence_threshold: f64,
207 pub lipschitz_constant: f64,
209 pub enable_consciousness: bool,
211 pub enable_quantum: bool,
213 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, 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 pub fn high_performance() -> Self {
234 Self {
235 max_iterations: 1_000_000,
236 max_duration_ns: 10_000_000, 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 pub fn consciousness_mode() -> Self {
247 Self {
248 max_iterations: 100_000,
249 max_duration_ns: 1_000_000_000, 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 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
276pub trait Reasoner: Send + Sync {
278 fn act(&mut self, context: &mut Context) -> Result<Trace>;
280
281 fn policy(&self) -> &Policy;
283
284 fn update_policy(&mut self, policy: Policy) -> Result<()>;
286
287 fn name(&self) -> &'static str;
289}
290
291pub trait Critic: Send + Sync {
293 fn evaluate(&self, trace: &Trace) -> f64;
295
296 fn propose_delta(&self, trace: &Trace) -> PolicyDelta;
298
299 fn name(&self) -> &'static str;
301}
302
303pub trait Reflector: Send + Sync {
305 fn apply(&self, policy: &mut Policy, delta: &PolicyDelta) -> Result<()>;
307
308 fn name(&self) -> &'static str;
310}
311
312pub 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 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 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 if start_time.elapsed().as_nanos() > self.config.max_duration_ns {
348 return Err(LoopError::timeout(start_time.elapsed().as_nanos()));
349 }
350
351 let trace = {
353 let mut reasoner = self.reasoner.write();
354 reasoner.act(context)?
355 };
356
357 let loss = self.critic.evaluate(&trace);
359 traces.push(trace.clone());
360
361 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 if i > 0 {
375 let input_delta = 1.0; 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 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 if i % 1000 == 0 {
398 std::hint::spin_loop();
399 }
400 }
401
402 Err(LoopError::convergence_failure(self.config.max_iterations))
404 }
405
406 pub fn iteration_count(&self) -> usize {
408 self.iteration_count
409 }
410
411 pub fn config(&self) -> &LoopConfig {
413 &self.config
414 }
415
416 pub fn reasoner(&self) -> Arc<RwLock<R>> {
418 Arc::clone(&self.reasoner)
419 }
420}
421
422#[derive(Clone, Debug, Serialize, Deserialize)]
424pub struct LoopResult {
425 pub iterations: usize,
427 pub final_score: f64,
429 pub duration_ns: u128,
431 pub converged: bool,
433 pub traces: Vec<Trace>,
435}
436
437impl LoopResult {
438 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 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#[derive(Clone, Debug)]
459pub struct ScalarReasoner {
460 target: f64,
461 policy: Policy,
462 momentum: f64,
463}
464
465impl ScalarReasoner {
466 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 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#[derive(Clone, Debug)]
509pub struct SimpleCritic {
510 adaptation_rate: f64,
511}
512
513impl SimpleCritic {
514 pub fn new() -> Self {
516 Self {
517 adaptation_rate: 0.1,
518 }
519 }
520
521 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 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 let delta_step = if improvement > 0.0 {
547 self.adaptation_rate * gradient_stability
548 } else {
549 -self.adaptation_rate * 0.5
550 };
551
552 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#[derive(Clone, Debug)]
571pub struct SafeReflector {
572 max_change_rate: f64,
573}
574
575impl SafeReflector {
576 pub fn new() -> Self {
578 Self {
579 max_change_rate: 0.2, }
581 }
582
583 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 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 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); 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); let old_step_size = policy.step_size;
689 reflector.apply(&mut policy, &delta).unwrap();
690
691 let change = (policy.step_size - old_step_size).abs();
693 assert!(change <= old_step_size * 0.2); }
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}