exo_exotic/
morphogenesis.rs

1//! # Morphogenetic Cognition
2//!
3//! Self-organizing pattern formation inspired by biological development.
4//! Uses reaction-diffusion systems (Turing patterns) to generate
5//! emergent cognitive structures.
6//!
7//! ## Key Concepts
8//!
9//! - **Turing Patterns**: Emergent patterns from reaction-diffusion
10//! - **Morphogens**: Signaling molecules that create concentration gradients
11//! - **Self-Organization**: Structure emerges from local rules
12//! - **Cognitive Embryogenesis**: Growing cognitive structures
13//!
14//! ## Mathematical Foundation
15//!
16//! Based on Turing's 1952 paper "The Chemical Basis of Morphogenesis":
17//! ∂u/∂t = Du∇²u + f(u,v)
18//! ∂v/∂t = Dv∇²v + g(u,v)
19
20use std::collections::HashMap;
21use serde::{Serialize, Deserialize};
22use uuid::Uuid;
23
24/// A field where morphogenetic patterns emerge
25#[derive(Debug)]
26pub struct MorphogeneticField {
27    /// Width of the field
28    width: usize,
29    /// Height of the field
30    height: usize,
31    /// Activator concentration
32    activator: Vec<Vec<f64>>,
33    /// Inhibitor concentration
34    inhibitor: Vec<Vec<f64>>,
35    /// Diffusion rate for activator
36    da: f64,
37    /// Diffusion rate for inhibitor
38    db: f64,
39    /// Reaction parameters
40    params: ReactionParams,
41    /// Pattern history for analysis
42    pattern_history: Vec<PatternSnapshot>,
43    /// Time step
44    dt: f64,
45}
46
47/// Parameters for reaction kinetics
48#[derive(Debug, Clone)]
49pub struct ReactionParams {
50    /// Feed rate
51    pub f: f64,
52    /// Kill rate
53    pub k: f64,
54    /// Activator production rate
55    pub alpha: f64,
56    /// Inhibitor production rate
57    pub beta: f64,
58}
59
60/// A snapshot of the pattern state
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct PatternSnapshot {
63    pub timestamp: u64,
64    pub complexity: f64,
65    pub dominant_wavelength: f64,
66    pub symmetry_score: f64,
67}
68
69/// Turing pattern generator
70#[derive(Debug)]
71pub struct TuringPattern {
72    /// Pattern type
73    pub pattern_type: PatternType,
74    /// Characteristic wavelength
75    pub wavelength: f64,
76    /// Amplitude of pattern
77    pub amplitude: f64,
78    /// Pattern data
79    pub data: Vec<Vec<f64>>,
80}
81
82/// Types of Turing patterns
83#[derive(Debug, Clone, PartialEq)]
84pub enum PatternType {
85    /// Spots pattern
86    Spots,
87    /// Stripes pattern
88    Stripes,
89    /// Labyrinth pattern
90    Labyrinth,
91    /// Hexagonal pattern
92    Hexagonal,
93    /// Mixed/transitional
94    Mixed,
95}
96
97/// Cognitive embryogenesis - growing cognitive structures
98#[derive(Debug)]
99pub struct CognitiveEmbryogenesis {
100    /// Current developmental stage
101    stage: DevelopmentStage,
102    /// Growing cognitive structures
103    structures: Vec<CognitiveStructure>,
104    /// Morphogen gradients
105    gradients: HashMap<String, Vec<f64>>,
106    /// Development history
107    history: Vec<DevelopmentEvent>,
108}
109
110#[derive(Debug, Clone, PartialEq)]
111pub enum DevelopmentStage {
112    /// Initial undifferentiated state
113    Zygote,
114    /// Early division
115    Cleavage,
116    /// Pattern formation
117    Gastrulation,
118    /// Structure differentiation
119    Organogenesis,
120    /// Mature structure
121    Mature,
122}
123
124#[derive(Debug, Clone)]
125pub struct CognitiveStructure {
126    pub id: Uuid,
127    pub structure_type: StructureType,
128    pub position: (f64, f64, f64),
129    pub size: f64,
130    pub connectivity: Vec<Uuid>,
131    pub specialization: f64,
132}
133
134#[derive(Debug, Clone, PartialEq)]
135pub enum StructureType {
136    SensoryRegion,
137    ProcessingNode,
138    MemoryStore,
139    IntegrationHub,
140    OutputRegion,
141}
142
143#[derive(Debug, Clone)]
144pub struct DevelopmentEvent {
145    pub stage: DevelopmentStage,
146    pub event_type: String,
147    pub timestamp: u64,
148}
149
150impl MorphogeneticField {
151    /// Create a new morphogenetic field
152    pub fn new(width: usize, height: usize) -> Self {
153        let mut field = Self {
154            width,
155            height,
156            activator: vec![vec![1.0; width]; height],
157            inhibitor: vec![vec![0.0; width]; height],
158            da: 1.0,
159            db: 0.5,
160            params: ReactionParams {
161                f: 0.055,
162                k: 0.062,
163                alpha: 1.0,
164                beta: 1.0,
165            },
166            pattern_history: Vec::new(),
167            dt: 1.0,
168        };
169
170        // Add initial perturbation
171        field.add_random_perturbation(0.05);
172        field
173    }
174
175    /// Create with specific parameters
176    pub fn with_params(width: usize, height: usize, da: f64, db: f64, params: ReactionParams) -> Self {
177        let mut field = Self::new(width, height);
178        field.da = da;
179        field.db = db;
180        field.params = params;
181        field
182    }
183
184    /// Add random perturbation to break symmetry
185    pub fn add_random_perturbation(&mut self, magnitude: f64) {
186        use std::time::{SystemTime, UNIX_EPOCH};
187        let seed = SystemTime::now()
188            .duration_since(UNIX_EPOCH)
189            .map(|d| d.as_nanos())
190            .unwrap_or(12345) as u64;
191
192        let mut state = seed;
193
194        for y in 0..self.height {
195            for x in 0..self.width {
196                // Simple LCG random
197                state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
198                let r = (state as f64) / (u64::MAX as f64);
199                self.inhibitor[y][x] += (r - 0.5) * magnitude;
200            }
201        }
202    }
203
204    /// Measure pattern complexity
205    pub fn measure_complexity(&self) -> f64 {
206        // Complexity based on spatial entropy and gradient magnitude
207        let mut gradient_sum = 0.0;
208        let mut count = 0;
209
210        for y in 1..self.height-1 {
211            for x in 1..self.width-1 {
212                let dx = self.activator[y][x+1] - self.activator[y][x-1];
213                let dy = self.activator[y+1][x] - self.activator[y-1][x];
214                gradient_sum += (dx*dx + dy*dy).sqrt();
215                count += 1;
216            }
217        }
218
219        if count > 0 {
220            (gradient_sum / count as f64).min(1.0)
221        } else {
222            0.0
223        }
224    }
225
226    /// Run one simulation step using Gray-Scott model
227    pub fn step(&mut self) {
228        let mut new_a = self.activator.clone();
229        let mut new_b = self.inhibitor.clone();
230
231        for y in 1..self.height-1 {
232            for x in 1..self.width-1 {
233                let a = self.activator[y][x];
234                let b = self.inhibitor[y][x];
235
236                // Laplacian (diffusion)
237                let lap_a = self.activator[y-1][x] + self.activator[y+1][x]
238                          + self.activator[y][x-1] + self.activator[y][x+1]
239                          - 4.0 * a;
240
241                let lap_b = self.inhibitor[y-1][x] + self.inhibitor[y+1][x]
242                          + self.inhibitor[y][x-1] + self.inhibitor[y][x+1]
243                          - 4.0 * b;
244
245                // Gray-Scott reaction
246                let reaction = a * b * b;
247
248                new_a[y][x] = a + self.dt * (
249                    self.da * lap_a
250                    - reaction
251                    + self.params.f * (1.0 - a)
252                );
253
254                new_b[y][x] = b + self.dt * (
255                    self.db * lap_b
256                    + reaction
257                    - (self.params.f + self.params.k) * b
258                );
259
260                // Clamp values
261                new_a[y][x] = new_a[y][x].clamp(0.0, 1.0);
262                new_b[y][x] = new_b[y][x].clamp(0.0, 1.0);
263            }
264        }
265
266        self.activator = new_a;
267        self.inhibitor = new_b;
268    }
269
270    /// Run simulation for n steps
271    pub fn simulate(&mut self, steps: usize) {
272        for _ in 0..steps {
273            self.step();
274        }
275
276        // Record snapshot
277        self.pattern_history.push(PatternSnapshot {
278            timestamp: self.pattern_history.len() as u64,
279            complexity: self.measure_complexity(),
280            dominant_wavelength: self.estimate_wavelength(),
281            symmetry_score: self.measure_symmetry(),
282        });
283    }
284
285    /// Estimate dominant wavelength using autocorrelation
286    fn estimate_wavelength(&self) -> f64 {
287        let center_y = self.height / 2;
288        let slice: Vec<f64> = (0..self.width)
289            .map(|x| self.activator[center_y][x])
290            .collect();
291
292        // Find first minimum in autocorrelation
293        let mut best_lag = 1;
294        let mut min_corr = f64::MAX;
295
296        for lag in 1..self.width/4 {
297            let mut corr = 0.0;
298            let mut count = 0;
299
300            for i in 0..self.width-lag {
301                corr += slice[i] * slice[i + lag];
302                count += 1;
303            }
304
305            if count > 0 {
306                corr /= count as f64;
307                if corr < min_corr {
308                    min_corr = corr;
309                    best_lag = lag;
310                }
311            }
312        }
313
314        (best_lag * 2) as f64 // Wavelength is twice the first minimum lag
315    }
316
317    /// Measure pattern symmetry
318    fn measure_symmetry(&self) -> f64 {
319        let mut diff_sum = 0.0;
320        let mut count = 0;
321
322        // Check left-right symmetry
323        for y in 0..self.height {
324            for x in 0..self.width/2 {
325                let mirror_x = self.width - 1 - x;
326                let diff = (self.activator[y][x] - self.activator[y][mirror_x]).abs();
327                diff_sum += diff;
328                count += 1;
329            }
330        }
331
332        if count > 0 {
333            1.0 - (diff_sum / count as f64).min(1.0)
334        } else {
335            0.0
336        }
337    }
338
339    /// Detect pattern type
340    pub fn detect_pattern_type(&self) -> PatternType {
341        let complexity = self.measure_complexity();
342        let symmetry = self.measure_symmetry();
343        let wavelength = self.estimate_wavelength();
344
345        if complexity < 0.1 {
346            PatternType::Mixed // Uniform
347        } else if symmetry > 0.7 && wavelength > self.width as f64 / 4.0 {
348            PatternType::Stripes
349        } else if symmetry > 0.5 && wavelength < self.width as f64 / 8.0 {
350            PatternType::Spots
351        } else if complexity > 0.5 {
352            PatternType::Labyrinth
353        } else {
354            PatternType::Mixed
355        }
356    }
357
358    /// Get the activator field
359    pub fn activator_field(&self) -> &Vec<Vec<f64>> {
360        &self.activator
361    }
362
363    /// Get the inhibitor field
364    pub fn inhibitor_field(&self) -> &Vec<Vec<f64>> {
365        &self.inhibitor
366    }
367
368    /// Get pattern at specific location
369    pub fn sample(&self, x: usize, y: usize) -> Option<(f64, f64)> {
370        if x < self.width && y < self.height {
371            Some((self.activator[y][x], self.inhibitor[y][x]))
372        } else {
373            None
374        }
375    }
376}
377
378impl CognitiveEmbryogenesis {
379    /// Create a new embryogenesis process
380    pub fn new() -> Self {
381        Self {
382            stage: DevelopmentStage::Zygote,
383            structures: Vec::new(),
384            gradients: HashMap::new(),
385            history: Vec::new(),
386        }
387    }
388
389    /// Advance development by one stage
390    pub fn develop(&mut self) -> DevelopmentStage {
391        let new_stage = match self.stage {
392            DevelopmentStage::Zygote => {
393                self.initialize_gradients();
394                DevelopmentStage::Cleavage
395            }
396            DevelopmentStage::Cleavage => {
397                self.divide_structures();
398                DevelopmentStage::Gastrulation
399            }
400            DevelopmentStage::Gastrulation => {
401                self.form_patterns();
402                DevelopmentStage::Organogenesis
403            }
404            DevelopmentStage::Organogenesis => {
405                self.differentiate();
406                DevelopmentStage::Mature
407            }
408            DevelopmentStage::Mature => {
409                DevelopmentStage::Mature
410            }
411        };
412
413        self.history.push(DevelopmentEvent {
414            stage: new_stage.clone(),
415            event_type: format!("Transition to {:?}", new_stage),
416            timestamp: self.history.len() as u64,
417        });
418
419        self.stage = new_stage.clone();
420        new_stage
421    }
422
423    fn initialize_gradients(&mut self) {
424        // Create morphogen gradients
425        let gradient_length = 100;
426
427        // Anterior-posterior gradient
428        let ap_gradient: Vec<f64> = (0..gradient_length)
429            .map(|i| (i as f64 / gradient_length as f64))
430            .collect();
431        self.gradients.insert("anterior_posterior".to_string(), ap_gradient);
432
433        // Dorsal-ventral gradient
434        let dv_gradient: Vec<f64> = (0..gradient_length)
435            .map(|i| {
436                let x = i as f64 / gradient_length as f64;
437                (x * std::f64::consts::PI).sin()
438            })
439            .collect();
440        self.gradients.insert("dorsal_ventral".to_string(), dv_gradient);
441    }
442
443    fn divide_structures(&mut self) {
444        // Create initial structures through division
445        let initial = CognitiveStructure {
446            id: Uuid::new_v4(),
447            structure_type: StructureType::ProcessingNode,
448            position: (0.5, 0.5, 0.5),
449            size: 1.0,
450            connectivity: Vec::new(),
451            specialization: 0.0,
452        };
453
454        // Divide into multiple structures
455        for i in 0..4 {
456            let angle = i as f64 * std::f64::consts::PI / 2.0;
457            self.structures.push(CognitiveStructure {
458                id: Uuid::new_v4(),
459                structure_type: StructureType::ProcessingNode,
460                position: (
461                    0.5 + 0.3 * angle.cos(),
462                    0.5 + 0.3 * angle.sin(),
463                    0.5,
464                ),
465                size: initial.size / 4.0,
466                connectivity: Vec::new(),
467                specialization: 0.0,
468            });
469        }
470    }
471
472    fn form_patterns(&mut self) {
473        // Establish connectivity patterns based on gradients
474        let structure_ids: Vec<Uuid> = self.structures.iter().map(|s| s.id).collect();
475
476        for i in 0..self.structures.len() {
477            for j in i+1..self.structures.len() {
478                let dist = self.distance(i, j);
479                if dist < 0.5 {
480                    self.structures[i].connectivity.push(structure_ids[j]);
481                    self.structures[j].connectivity.push(structure_ids[i]);
482                }
483            }
484        }
485    }
486
487    fn distance(&self, i: usize, j: usize) -> f64 {
488        let (x1, y1, z1) = self.structures[i].position;
489        let (x2, y2, z2) = self.structures[j].position;
490        ((x2-x1).powi(2) + (y2-y1).powi(2) + (z2-z1).powi(2)).sqrt()
491    }
492
493    fn differentiate(&mut self) {
494        // Differentiate structures based on position in gradients
495        for structure in &mut self.structures {
496            let (x, y, _) = structure.position;
497
498            // Determine type based on position
499            structure.structure_type = if x < 0.3 {
500                StructureType::SensoryRegion
501            } else if x > 0.7 {
502                StructureType::OutputRegion
503            } else if y < 0.3 {
504                StructureType::MemoryStore
505            } else if y > 0.7 {
506                StructureType::IntegrationHub
507            } else {
508                StructureType::ProcessingNode
509            };
510
511            structure.specialization = 1.0;
512        }
513    }
514
515    /// Get current stage
516    pub fn current_stage(&self) -> &DevelopmentStage {
517        &self.stage
518    }
519
520    /// Get structures
521    pub fn structures(&self) -> &[CognitiveStructure] {
522        &self.structures
523    }
524
525    /// Check if development is complete
526    pub fn is_mature(&self) -> bool {
527        self.stage == DevelopmentStage::Mature
528    }
529
530    /// Run full development
531    pub fn full_development(&mut self) {
532        while self.stage != DevelopmentStage::Mature {
533            self.develop();
534        }
535    }
536}
537
538impl Default for CognitiveEmbryogenesis {
539    fn default() -> Self {
540        Self::new()
541    }
542}
543
544#[cfg(test)]
545mod tests {
546    use super::*;
547
548    #[test]
549    fn test_morphogenetic_field_creation() {
550        let field = MorphogeneticField::new(32, 32);
551        assert_eq!(field.width, 32);
552        assert_eq!(field.height, 32);
553    }
554
555    #[test]
556    fn test_simulation_step() {
557        let mut field = MorphogeneticField::new(32, 32);
558        field.step();
559
560        // Field should still be valid
561        assert!(field.activator[16][16] >= 0.0);
562        assert!(field.activator[16][16] <= 1.0);
563    }
564
565    #[test]
566    fn test_pattern_complexity() {
567        let mut field = MorphogeneticField::new(32, 32);
568
569        // Initial complexity should be low
570        let initial_complexity = field.measure_complexity();
571
572        // After simulation, patterns should form
573        field.simulate(100);
574        let final_complexity = field.measure_complexity();
575
576        // Complexity should generally increase (patterns form)
577        assert!(final_complexity >= 0.0);
578    }
579
580    #[test]
581    fn test_pattern_detection() {
582        let mut field = MorphogeneticField::new(32, 32);
583        field.simulate(50);
584
585        let pattern_type = field.detect_pattern_type();
586        // Should detect some pattern type
587        assert!(matches!(pattern_type, PatternType::Spots | PatternType::Stripes
588            | PatternType::Labyrinth | PatternType::Hexagonal | PatternType::Mixed));
589    }
590
591    #[test]
592    fn test_cognitive_embryogenesis() {
593        let mut embryo = CognitiveEmbryogenesis::new();
594        assert_eq!(*embryo.current_stage(), DevelopmentStage::Zygote);
595
596        embryo.full_development();
597
598        assert!(embryo.is_mature());
599        assert!(!embryo.structures().is_empty());
600    }
601
602    #[test]
603    fn test_structure_differentiation() {
604        let mut embryo = CognitiveEmbryogenesis::new();
605        embryo.full_development();
606
607        // Should have different structure types
608        let types: Vec<_> = embryo.structures().iter()
609            .map(|s| &s.structure_type)
610            .collect();
611
612        assert!(embryo.structures().iter()
613            .all(|s| s.specialization > 0.0));
614    }
615
616    #[test]
617    fn test_gradient_initialization() {
618        let mut embryo = CognitiveEmbryogenesis::new();
619        embryo.develop(); // Zygote -> Cleavage, initializes gradients
620
621        assert!(embryo.gradients.contains_key("anterior_posterior"));
622        assert!(embryo.gradients.contains_key("dorsal_ventral"));
623    }
624}