strange_loop/
self_modifying.rs1use std::sync::{Arc, RwLock};
4
5pub struct SelfModifyingLoop {
7 loop_fn: Arc<RwLock<Box<dyn Fn(f64) -> f64 + Send + Sync>>>,
9 mutation_rate: f64,
11 fitness_history: Vec<f64>,
13 generation: usize,
15 best_params: Vec<f64>,
17}
18
19impl SelfModifyingLoop {
20 pub fn new(mutation_rate: f64) -> Self {
21 let initial_fn = Box::new(|x: f64| x.sin() * x.cos()) as Box<dyn Fn(f64) -> f64 + Send + Sync>;
22
23 Self {
24 loop_fn: Arc::new(RwLock::new(initial_fn)),
25 mutation_rate,
26 fitness_history: Vec::new(),
27 generation: 0,
28 best_params: vec![1.0, 0.0, 0.0],
29 }
30 }
31
32 pub fn evolve(&mut self, fitness: f64) {
34 self.fitness_history.push(fitness);
35 self.generation += 1;
36
37 if self.fitness_history.len() < 10 {
39 return;
40 }
41
42 let recent_avg = self.fitness_history.iter().rev().take(5).sum::<f64>() / 5.0;
44 let past_avg = self.fitness_history.iter().rev().skip(5).take(5).sum::<f64>() / 5.0;
45
46 let mutation_factor = if recent_avg < past_avg {
48 self.mutation_rate * 2.0
49 } else {
50 self.mutation_rate
51 };
52
53 self.mutate_parameters(mutation_factor);
55
56 self.update_loop_function();
58 }
59
60 fn mutate_parameters(&mut self, factor: f64) {
61 use rand::Rng;
62 let mut rng = rand::thread_rng();
63
64 for param in &mut self.best_params {
65 if rng.gen::<f64>() < factor {
66 let noise = rng.gen_range(-0.1..0.1);
68 *param += noise;
69 *param = param.clamp(-10.0, 10.0);
70 }
71 }
72 }
73
74 fn update_loop_function(&mut self) {
75 let a = self.best_params[0];
76 let b = self.best_params[1];
77 let c = self.best_params[2];
78
79 let new_fn = Box::new(move |x: f64| {
80 a * x.sin() + b * x.cos() + c * x.tan().tanh()
81 }) as Box<dyn Fn(f64) -> f64 + Send + Sync>;
82
83 if let Ok(mut fn_lock) = self.loop_fn.write() {
84 *fn_lock = new_fn;
85 }
86 }
87
88 pub fn execute(&self, input: f64) -> f64 {
90 if let Ok(fn_lock) = self.loop_fn.read() {
91 fn_lock(input)
92 } else {
93 input
94 }
95 }
96
97 pub fn replicate(&self) -> Self {
99 let mut child = Self::new(self.mutation_rate);
100 child.best_params = self.best_params.clone();
101 child.mutate_parameters(self.mutation_rate * 0.5);
102 child.update_loop_function();
103 child
104 }
105
106 pub fn get_metrics(&self) -> EvolutionMetrics {
108 EvolutionMetrics {
109 generation: self.generation,
110 current_fitness: self.fitness_history.last().copied().unwrap_or(0.0),
111 best_fitness: self.fitness_history.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).copied().unwrap_or(0.0),
112 mutation_rate: self.mutation_rate,
113 parameters: self.best_params.clone(),
114 }
115 }
116}
117
118#[derive(Debug, Clone)]
119pub struct EvolutionMetrics {
120 pub generation: usize,
121 pub current_fitness: f64,
122 pub best_fitness: f64,
123 pub mutation_rate: f64,
124 pub parameters: Vec<f64>,
125}