genesis_protocol/
evolution.rs

1//! 🧬 Evolution Engine - Biological Evolution for Digital Organisms
2//!
3//! This module implements the evolution engine that drives biological evolution
4//! of TRON organisms through mutations, selection pressure, and fitness evaluation.
5
6use crate::dna::{DigitalDNA, Mutation, DNAError};
7use crate::tron::TRON;
8use serde::{Deserialize, Serialize};
9use std::time::{SystemTime, UNIX_EPOCH};
10
11/// Evolution engine for managing organism evolution
12#[derive(Debug, Clone)]
13pub struct EvolutionEngine {
14    /// Current evolution cycle
15    pub current_cycle: u64,
16    /// Selection pressure (0.0-1.0)
17    pub selection_pressure: f64,
18    /// Mutation rate (0.0-1.0)
19    pub mutation_rate: f64,
20    /// Evolution history
21    pub evolution_history: Vec<EvolutionEvent>,
22    /// Fitness statistics
23    pub fitness_stats: FitnessStats,
24    /// Evolution parameters
25    pub parameters: EvolutionParameters,
26}
27
28/// Types of evolution mutations
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub enum MutationType {
31    /// Beneficial mutation
32    Beneficial,
33    /// Neutral mutation
34    Neutral,
35    /// Harmful mutation
36    Harmful,
37    /// Adaptive mutation in response to environment
38    Adaptive,
39}
40
41/// Selection pressure types
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub enum SelectionPressure {
44    /// Natural selection based on fitness
45    Natural,
46    /// Sexual selection for reproduction
47    Sexual,
48    /// Environmental pressure
49    Environmental,
50    /// Competitive pressure from other organisms
51    Competitive,
52    /// Artificial selection by external forces
53    Artificial,
54}
55
56/// Evolution event record
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct EvolutionEvent {
59    /// Event ID
60    pub event_id: String,
61    /// Organism that evolved
62    pub organism_id: String,
63    /// Evolution cycle when event occurred
64    pub cycle: u64,
65    /// Mutation applied
66    pub mutation: Mutation,
67    /// Fitness before evolution
68    pub fitness_before: f64,
69    /// Fitness after evolution
70    pub fitness_after: f64,
71    /// Selection pressure applied
72    pub selection_pressure: f64,
73    /// Timestamp
74    pub timestamp: u64,
75    /// Evolution outcome
76    pub outcome: EvolutionOutcome,
77}
78
79/// Evolution outcome types
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub enum EvolutionOutcome {
82    /// Successful evolution
83    Success,
84    /// Evolution failed
85    Failed,
86    /// Organism became extinct
87    Extinct,
88    /// Organism created new species
89    Speciation,
90}
91
92/// Evolution parameters
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct EvolutionParameters {
95    /// Base mutation rate
96    pub base_mutation_rate: f64,
97    /// Maximum mutations per cycle
98    pub max_mutations_per_cycle: usize,
99    /// Fitness threshold for survival
100    pub survival_threshold: f64,
101    /// Fitness threshold for reproduction
102    pub reproduction_threshold: f64,
103    /// Environmental adaptation factor
104    pub adaptation_factor: f64,
105    /// Sexual selection strength
106    pub sexual_selection_strength: f64,
107}
108
109/// Fitness statistics
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct FitnessStats {
112    /// Average fitness in population
113    pub average_fitness: f64,
114    /// Maximum fitness recorded
115    pub max_fitness: f64,
116    /// Minimum fitness recorded
117    pub min_fitness: f64,
118    /// Fitness variance
119    pub fitness_variance: f64,
120    /// Number of organisms tracked
121    pub organism_count: usize,
122}
123
124impl EvolutionEngine {
125    /// Create new evolution engine
126    pub fn new() -> Result<Self, EvolutionError> {
127        Ok(EvolutionEngine {
128            current_cycle: 0,
129            selection_pressure: 0.5,
130            mutation_rate: 0.01,
131            evolution_history: Vec::new(),
132            fitness_stats: FitnessStats::new(),
133            parameters: EvolutionParameters::default(),
134        })
135    }
136
137    /// Evolve a single organism
138    pub fn evolve_organism(&mut self, organism: &mut TRON) -> Result<EvolutionEvent, EvolutionError> {
139        let fitness_before = organism.dna.fitness;
140        
141        // Apply selection pressure
142        if fitness_before < self.parameters.survival_threshold {
143            return Err(EvolutionError::InsufficientFitness(fitness_before));
144        }
145        
146        // Generate mutation
147        let mutation = self.generate_mutation(&organism.dna)?;
148        
149        // Apply mutation
150        organism.dna.mutate(mutation.clone())
151            .map_err(|e| EvolutionError::MutationFailed(e.to_string()))?;
152        
153        let fitness_after = organism.dna.fitness;
154        
155        // Record evolution event
156        let event = EvolutionEvent {
157            event_id: uuid::Uuid::new_v4().to_string(),
158            organism_id: organism.id.clone(),
159            cycle: self.current_cycle,
160            mutation,
161            fitness_before,
162            fitness_after,
163            selection_pressure: self.selection_pressure,
164            timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(),
165            outcome: if fitness_after > fitness_before {
166                EvolutionOutcome::Success
167            } else {
168                EvolutionOutcome::Failed
169            },
170        };
171        
172        self.evolution_history.push(event.clone());
173        self.fitness_stats.update_fitness(fitness_after);
174        
175        Ok(event)
176    }
177
178    /// Generate appropriate mutation based on organism state
179    fn generate_mutation(&self, dna: &DigitalDNA) -> Result<Mutation, EvolutionError> {
180        // Determine mutation type based on fitness and environment
181        let mutation_type = if dna.fitness > 0.8 {
182            MutationType::Beneficial
183        } else if dna.fitness < 0.3 {
184            MutationType::Adaptive
185        } else {
186            MutationType::Neutral
187        };
188        
189        // Generate mutation based on type
190        match mutation_type {
191            MutationType::Beneficial => {
192                // Beneficial mutations are rare but powerful
193                if rand::random::<f64>() < 0.1 {
194                    Ok(Mutation::KeyEvolution {
195                        old_generation: dna.keypair.key_generation,
196                        new_generation: dna.keypair.key_generation + 1,
197                        timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(),
198                    })
199                } else {
200                    Ok(dna.generate_random_mutation())
201                }
202            },
203            MutationType::Adaptive => {
204                // Adaptive mutations respond to environmental pressure
205                Ok(Mutation::Duplication {
206                    start: rand::random::<usize>() % dna.sequence.len(),
207                    end: rand::random::<usize>() % dna.sequence.len(),
208                    insert_at: rand::random::<usize>() % dna.sequence.len(),
209                    timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(),
210                })
211            },
212            _ => Ok(dna.generate_random_mutation()),
213        }
214    }
215
216    /// Apply selection pressure to population
217    pub fn apply_selection_pressure(&mut self, organisms: &mut Vec<TRON>) -> Result<Vec<String>, EvolutionError> {
218        let mut eliminated = Vec::new();
219        
220        // Sort by fitness
221        organisms.sort_by(|a, b| b.dna.fitness.partial_cmp(&a.dna.fitness).unwrap());
222        
223        // Apply selection pressure
224        let elimination_threshold = self.selection_pressure;
225        let mut to_eliminate = Vec::new();
226        
227        for organism in organisms.iter() {
228            if organism.dna.fitness < elimination_threshold {
229                to_eliminate.push(organism.id.clone());
230            }
231        }
232        
233        // Remove eliminated organisms
234        organisms.retain(|o| !to_eliminate.contains(&o.id));
235        eliminated.extend(to_eliminate);
236        
237        // Update fitness statistics
238        self.update_population_stats(organisms);
239        
240        Ok(eliminated)
241    }
242
243    /// Update population fitness statistics
244    fn update_population_stats(&mut self, organisms: &[TRON]) {
245        if organisms.is_empty() {
246            return;
247        }
248        
249        let fitnesses: Vec<f64> = organisms.iter().map(|o| o.dna.fitness).collect();
250        
251        self.fitness_stats.organism_count = organisms.len();
252        self.fitness_stats.average_fitness = fitnesses.iter().sum::<f64>() / organisms.len() as f64;
253        self.fitness_stats.max_fitness = fitnesses.iter().cloned().fold(0.0, f64::max);
254        self.fitness_stats.min_fitness = fitnesses.iter().cloned().fold(f64::INFINITY, f64::min);
255        
256        // Calculate variance
257        let mean = self.fitness_stats.average_fitness;
258        let variance = fitnesses.iter()
259            .map(|f| (f - mean).powi(2))
260            .sum::<f64>() / organisms.len() as f64;
261        self.fitness_stats.fitness_variance = variance;
262    }
263
264    /// Get evolution statistics
265    pub fn get_stats(&self) -> EvolutionStats {
266        EvolutionStats {
267            current_cycle: self.current_cycle,
268            total_events: self.evolution_history.len(),
269            successful_evolutions: self.evolution_history.iter()
270                .filter(|e| matches!(e.outcome, EvolutionOutcome::Success))
271                .count(),
272            failed_evolutions: self.evolution_history.iter()
273                .filter(|e| matches!(e.outcome, EvolutionOutcome::Failed))
274                .count(),
275            average_fitness: self.fitness_stats.average_fitness,
276            max_fitness: self.fitness_stats.max_fitness,
277            min_fitness: self.fitness_stats.min_fitness,
278            selection_pressure: self.selection_pressure,
279            mutation_rate: self.mutation_rate,
280        }
281    }
282
283    /// Advance evolution cycle
284    pub fn advance_cycle(&mut self) {
285        self.current_cycle += 1;
286        
287        // Adjust mutation rate based on population health
288        if self.fitness_stats.average_fitness > 0.8 {
289            self.mutation_rate *= 0.9; // Reduce mutation rate in healthy populations
290        } else if self.fitness_stats.average_fitness < 0.3 {
291            self.mutation_rate *= 1.1; // Increase mutation rate in struggling populations
292        }
293        
294        // Cap mutation rate
295        self.mutation_rate = self.mutation_rate.max(0.001).min(0.1);
296    }
297}
298
299/// Evolution statistics
300#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct EvolutionStats {
302    pub current_cycle: u64,
303    pub total_events: usize,
304    pub successful_evolutions: usize,
305    pub failed_evolutions: usize,
306    pub average_fitness: f64,
307    pub max_fitness: f64,
308    pub min_fitness: f64,
309    pub selection_pressure: f64,
310    pub mutation_rate: f64,
311}
312
313impl FitnessStats {
314    pub fn new() -> Self {
315        FitnessStats {
316            average_fitness: 0.0,
317            max_fitness: 0.0,
318            min_fitness: f64::INFINITY,
319            fitness_variance: 0.0,
320            organism_count: 0,
321        }
322    }
323    
324    pub fn update_fitness(&mut self, fitness: f64) {
325        self.organism_count += 1;
326        
327        if fitness > self.max_fitness {
328            self.max_fitness = fitness;
329        }
330        
331        if fitness < self.min_fitness {
332            self.min_fitness = fitness;
333        }
334        
335        // Update running average
336        self.average_fitness = ((self.average_fitness * (self.organism_count - 1) as f64) + fitness) / self.organism_count as f64;
337    }
338}
339
340impl Default for EvolutionParameters {
341    fn default() -> Self {
342        EvolutionParameters {
343            base_mutation_rate: 0.01,
344            max_mutations_per_cycle: 3,
345            survival_threshold: 0.1,
346            reproduction_threshold: 0.6,
347            adaptation_factor: 0.8,
348            sexual_selection_strength: 0.5,
349        }
350    }
351}
352
353/// Evolution-related errors
354#[derive(Debug, thiserror::Error)]
355pub enum EvolutionError {
356    #[error("Insufficient fitness for evolution: {0}")]
357    InsufficientFitness(f64),
358    #[error("Mutation failed: {0}")]
359    MutationFailed(String),
360    #[error("Selection pressure too high: {0}")]
361    SelectionPressureTooHigh(f64),
362    #[error("Population extinct")]
363    PopulationExtinct,
364    #[error("Evolution cycle limit reached")]
365    CycleLimitReached,
366    #[error("DNA error: {0}")]
367    DNA(#[from] DNAError),
368}
369
370#[cfg(test)]
371mod tests {
372    use super::*;
373    use crate::dna::DigitalDNA;
374
375    #[test]
376    fn test_evolution_engine_creation() {
377        let engine = EvolutionEngine::new().unwrap();
378        assert_eq!(engine.current_cycle, 0);
379        assert_eq!(engine.selection_pressure, 0.5);
380        assert_eq!(engine.mutation_rate, 0.01);
381    }
382
383    #[test]
384    fn test_organism_evolution() {
385        let mut engine = EvolutionEngine::new().unwrap();
386        let mut organism = TRON::create_new().unwrap();
387        
388        let initial_fitness = organism.dna.fitness;
389        let initial_generation = organism.dna.generation;
390        
391        let event = engine.evolve_organism(&mut organism).unwrap();
392        
393        assert_eq!(event.organism_id, organism.id);
394        assert_eq!(event.fitness_before, initial_fitness);
395        assert_eq!(organism.dna.generation, initial_generation + 1);
396        assert_eq!(engine.evolution_history.len(), 1);
397    }
398
399    #[test]
400    fn test_selection_pressure() {
401        let mut engine = EvolutionEngine::new().unwrap();
402        let mut organisms = Vec::new();
403        
404        // Create organisms with different fitness levels
405        for i in 0..10 {
406            let mut organism = TRON::create_new().unwrap();
407            organism.dna.fitness = i as f64 / 10.0;
408            organisms.push(organism);
409        }
410        
411        engine.selection_pressure = 0.5;
412        let eliminated = engine.apply_selection_pressure(&mut organisms).unwrap();
413        
414        // Low fitness organisms should be eliminated
415        assert!(eliminated.len() > 0);
416        assert!(organisms.len() < 10);
417        
418        // Remaining organisms should have higher fitness
419        for organism in &organisms {
420            assert!(organism.dna.fitness >= 0.5);
421        }
422    }
423
424    #[test]
425    fn test_fitness_stats() {
426        let mut stats = FitnessStats::new();
427        
428        stats.update_fitness(0.8);
429        stats.update_fitness(0.6);
430        stats.update_fitness(0.9);
431        
432        assert_eq!(stats.organism_count, 3);
433        assert_eq!(stats.max_fitness, 0.9);
434        assert_eq!(stats.min_fitness, 0.6);
435        assert!((stats.average_fitness - 0.7667).abs() < 0.01);
436    }
437
438    #[test]
439    fn test_evolution_cycle_advance() {
440        let mut engine = EvolutionEngine::new().unwrap();
441        let initial_cycle = engine.current_cycle;
442        
443        engine.advance_cycle();
444        
445        assert_eq!(engine.current_cycle, initial_cycle + 1);
446    }
447
448    #[test]
449    fn test_mutation_rate_adjustment() {
450        let mut engine = EvolutionEngine::new().unwrap();
451        
452        // High fitness should reduce mutation rate
453        engine.fitness_stats.average_fitness = 0.9;
454        let initial_rate = engine.mutation_rate;
455        
456        engine.advance_cycle();
457        
458        assert!(engine.mutation_rate < initial_rate);
459        
460        // Low fitness should increase mutation rate
461        engine.fitness_stats.average_fitness = 0.2;
462        let current_rate = engine.mutation_rate;
463        
464        engine.advance_cycle();
465        
466        assert!(engine.mutation_rate > current_rate);
467    }
468}