1use crate::{
18 GenomeMetadata, GenomeSignatures, GenomeStats, MorphologyRegistry, PhysiologyConfig,
19 RuntimeGenome,
20};
21use feagi_structures::genomic::cortical_area::CoreCorticalType;
22use feagi_structures::genomic::cortical_area::{CorticalArea, CorticalAreaDimensions};
23use feagi_structures::genomic::descriptors::GenomeCoordinate3D;
24use serde_json::Value;
25use std::collections::HashMap;
26
27pub const ESSENTIAL_GENOME_JSON: &str = include_str!("../genomes/essential_genome.json");
29
30pub const BAREBONES_GENOME_JSON: &str = include_str!("../genomes/barebones_genome.json");
32
33pub const TEST_GENOME_JSON: &str = include_str!("../genomes/test_genome.json");
35
36pub const VISION_GENOME_JSON: &str = include_str!("../genomes/vision_genome.json");
38
39pub fn get_default_neural_properties() -> HashMap<String, Value> {
41 let mut props = HashMap::new();
42 props.insert("per_voxel_neuron_cnt".to_string(), Value::from(1));
43 props.insert("synapse_attractivity".to_string(), Value::from(100.0));
44 props.insert("degeneration".to_string(), Value::from(0.0));
45 props.insert("psp_uniform_distribution".to_string(), Value::from(true));
46 props.insert("postsynaptic_current_max".to_string(), Value::from(10000.0));
47 props.insert("postsynaptic_current".to_string(), Value::from(500.0));
48 props.insert("firing_threshold".to_string(), Value::from(0.1));
49 props.insert("refractory_period".to_string(), Value::from(0));
50 props.insert("leak_coefficient".to_string(), Value::from(0.0));
51 props.insert("leak_variability".to_string(), Value::from(0.0));
52 props.insert("consecutive_fire_cnt_max".to_string(), Value::from(0));
53 props.insert("snooze_length".to_string(), Value::from(0));
54 props.insert("mp_charge_accumulation".to_string(), Value::from(false));
55 props.insert("mp_driven_psp".to_string(), Value::from(false));
56 props.insert("neuron_excitability".to_string(), Value::from(1.0));
57 props.insert("visualization".to_string(), Value::from(true));
58 props.insert("memory_twin_of".to_string(), Value::Null);
59 props.insert(
60 "cortical_mapping_dst".to_string(),
61 Value::Object(serde_json::Map::new()),
62 );
63 props
64}
65
66pub fn create_death_area() -> CorticalArea {
68 let cortical_id = CoreCorticalType::Death.to_cortical_id();
69 let cortical_type = cortical_id
70 .as_cortical_type()
71 .expect("Death cortical ID should map to Core type");
72
73 let mut area = CorticalArea::new(
74 cortical_id,
75 0, "Death".to_string(),
77 CorticalAreaDimensions::new(1, 1, 1).expect("Failed to create dimensions"),
78 GenomeCoordinate3D::new(0, 0, -20),
79 cortical_type,
80 )
81 .expect("Failed to create _death area");
82
83 let mut props = get_default_neural_properties();
84 props.insert("cortical_group".to_string(), Value::from("CORE"));
85 props.insert("2d_coordinate".to_string(), Value::from(vec![-10, -20]));
86 area.properties = props;
87 area
88}
89
90pub fn create_power_area() -> CorticalArea {
92 let cortical_id = CoreCorticalType::Power.to_cortical_id();
93 let cortical_type = cortical_id
94 .as_cortical_type()
95 .expect("Power cortical ID should map to Core type");
96
97 let mut area = CorticalArea::new(
98 cortical_id,
99 1, "Brain_Power".to_string(),
101 CorticalAreaDimensions::new(1, 1, 1).expect("Failed to create dimensions"),
102 GenomeCoordinate3D::new(0, 0, -20),
103 cortical_type,
104 )
105 .expect("Failed to create _power area");
106
107 let mut props = get_default_neural_properties();
108 props.insert("cortical_group".to_string(), Value::from("CORE"));
109 props.insert("2d_coordinate".to_string(), Value::from(vec![-10, -10]));
110 props.insert("firing_threshold".to_string(), Value::from(0.1));
111 props.insert("postsynaptic_current".to_string(), Value::from(500.0));
112 props.insert("neuron_excitability".to_string(), Value::from(100.0));
113 props.insert("degeneration".to_string(), Value::from(0.0));
114 props.insert("psp_uniform_distribution".to_string(), Value::from(true));
115 area.properties = props;
116 area
117}
118
119pub fn create_fatigue_area() -> CorticalArea {
121 let cortical_id = CoreCorticalType::Fatigue.to_cortical_id();
122 let cortical_type = cortical_id
123 .as_cortical_type()
124 .expect("Fatigue cortical ID should map to Core type");
125
126 let mut area = CorticalArea::new(
127 cortical_id,
128 2, "Fatigue".to_string(),
130 CorticalAreaDimensions::new(1, 1, 1).expect("Failed to create dimensions"),
131 GenomeCoordinate3D::new(0, 0, -30),
132 cortical_type,
133 )
134 .expect("Failed to create _fatigue area");
135
136 let mut props = get_default_neural_properties();
137 props.insert("cortical_group".to_string(), Value::from("CORE"));
138 props.insert("2d_coordinate".to_string(), Value::from(vec![-10, 0]));
139 area.properties = props;
140 area
141}
142
143pub fn create_pain_area() -> CorticalArea {
145 let cortical_id = CoreCorticalType::Pain.to_cortical_id();
146 let cortical_type = cortical_id
147 .as_cortical_type()
148 .expect("Pain cortical ID should map to Core type");
149
150 let mut area = CorticalArea::new(
151 cortical_id,
152 3, "Pain".to_string(),
154 CorticalAreaDimensions::new(1, 1, 1).expect("Failed to create dimensions"),
155 GenomeCoordinate3D::new(0, 0, -40),
156 cortical_type,
157 )
158 .expect("Failed to create _pain area");
159
160 let mut props = get_default_neural_properties();
161 props.insert("cortical_group".to_string(), Value::from("CORE"));
162 props.insert("2d_coordinate".to_string(), Value::from(vec![-10, 10]));
163 area.properties = props;
164 area
165}
166
167pub fn create_pleasure_area() -> CorticalArea {
169 let cortical_id = CoreCorticalType::Pleasure.to_cortical_id();
170 let cortical_type = cortical_id
171 .as_cortical_type()
172 .expect("Pleasure cortical ID should map to Core type");
173
174 let mut area = CorticalArea::new(
175 cortical_id,
176 4, "Pleasure".to_string(),
178 CorticalAreaDimensions::new(1, 1, 1).expect("Failed to create dimensions"),
179 GenomeCoordinate3D::new(0, 0, -50),
180 cortical_type,
181 )
182 .expect("Failed to create _pleasure area");
183
184 let mut props = get_default_neural_properties();
185 props.insert("cortical_group".to_string(), Value::from("CORE"));
186 props.insert("2d_coordinate".to_string(), Value::from(vec![-10, 20]));
187 area.properties = props;
188 area
189}
190
191pub fn create_fear_area() -> CorticalArea {
193 let cortical_id = CoreCorticalType::Fear.to_cortical_id();
194 let cortical_type = cortical_id
195 .as_cortical_type()
196 .expect("Fear cortical ID should map to Core type");
197
198 let mut area = CorticalArea::new(
199 cortical_id,
200 5, "Fear".to_string(),
202 CorticalAreaDimensions::new(1, 1, 1).expect("Failed to create dimensions"),
203 GenomeCoordinate3D::new(0, 0, -60),
204 cortical_type,
205 )
206 .expect("Failed to create _fear area");
207
208 let mut props = get_default_neural_properties();
209 props.insert("cortical_group".to_string(), Value::from("CORE"));
210 props.insert("2d_coordinate".to_string(), Value::from(vec![-10, 30]));
211 area.properties = props;
212 area
213}
214
215pub fn create_hope_area() -> CorticalArea {
217 let cortical_id = CoreCorticalType::Hope.to_cortical_id();
218 let cortical_type = cortical_id
219 .as_cortical_type()
220 .expect("Hope cortical ID should map to Core type");
221
222 let mut area = CorticalArea::new(
223 cortical_id,
224 6, "Hope".to_string(),
226 CorticalAreaDimensions::new(1, 1, 1).expect("Failed to create dimensions"),
227 GenomeCoordinate3D::new(0, 0, -70),
228 cortical_type,
229 )
230 .expect("Failed to create _hope area");
231
232 let mut props = get_default_neural_properties();
233 props.insert("cortical_group".to_string(), Value::from("CORE"));
234 props.insert("2d_coordinate".to_string(), Value::from(vec![-10, 40]));
235 area.properties = props;
236 area
237}
238
239pub fn create_minimal_genome(genome_id: String, genome_title: String) -> RuntimeGenome {
241 RuntimeGenome {
242 metadata: GenomeMetadata {
243 genome_id,
244 genome_title,
245 genome_description: "Minimal genome template".to_string(),
246 version: "2.0".to_string(),
247 timestamp: std::time::SystemTime::now()
248 .duration_since(std::time::UNIX_EPOCH)
249 .unwrap()
250 .as_secs_f64(),
251 brain_regions_root: None, },
253 cortical_areas: HashMap::new(),
254 brain_regions: HashMap::new(),
255 classifiers: HashMap::new(),
256 morphologies: MorphologyRegistry::new(),
257 physiology: PhysiologyConfig::default(),
258 signatures: GenomeSignatures {
259 genome: String::new(),
260 blueprint: String::new(),
261 physiology: String::new(),
262 morphologies: None,
263 },
264 stats: GenomeStats::default(),
265 change_history: Vec::new(),
266 }
267}
268
269pub fn create_genome_with_core_areas(genome_id: String, genome_title: String) -> RuntimeGenome {
271 let mut genome = create_minimal_genome(genome_id, genome_title);
272
273 let death_id =
275 crate::genome::parser::string_to_cortical_id("_death").expect("Valid cortical ID");
276 let power_id =
277 crate::genome::parser::string_to_cortical_id("_power").expect("Valid cortical ID");
278 let fatigue_id =
279 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid cortical ID");
280 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid cortical ID");
281 let pleasure_id =
282 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid cortical ID");
283 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid cortical ID");
284 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid cortical ID");
285
286 genome.cortical_areas.insert(death_id, create_death_area());
287 genome.cortical_areas.insert(power_id, create_power_area());
288 genome
289 .cortical_areas
290 .insert(fatigue_id, create_fatigue_area());
291 genome.cortical_areas.insert(pain_id, create_pain_area());
292 genome
293 .cortical_areas
294 .insert(pleasure_id, create_pleasure_area());
295 genome.cortical_areas.insert(fear_id, create_fear_area());
296 genome.cortical_areas.insert(hope_id, create_hope_area());
297
298 genome
299}
300
301pub fn create_genome_with_core_morphologies(
303 genome_id: String,
304 genome_title: String,
305) -> RuntimeGenome {
306 let mut genome = create_minimal_genome(genome_id, genome_title);
307
308 add_core_morphologies(&mut genome.morphologies);
310
311 genome
312}
313
314pub fn ensure_core_components(genome: &mut RuntimeGenome) -> (usize, usize) {
329 let mut areas_added = 0;
330 let mut morphologies_added = 0;
331
332 let death_id =
334 crate::genome::parser::string_to_cortical_id("_death").expect("Valid cortical ID");
335 let power_id =
336 crate::genome::parser::string_to_cortical_id("_power").expect("Valid cortical ID");
337 let fatigue_id =
338 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid cortical ID");
339 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid cortical ID");
340 let pleasure_id =
341 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid cortical ID");
342 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid cortical ID");
343 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid cortical ID");
344
345 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(death_id) {
347 let death_area = create_death_area();
348 e.insert(death_area);
349 areas_added += 1;
350 tracing::info!("Added missing core area: _death (cortical_idx=0)");
351 }
352
353 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(power_id) {
354 let power_area = create_power_area();
355 e.insert(power_area);
356 areas_added += 1;
357 tracing::info!("Added missing core area: _power (cortical_idx=1)");
358 }
359
360 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(fatigue_id) {
361 let fatigue_area = create_fatigue_area();
362 e.insert(fatigue_area);
363 areas_added += 1;
364 tracing::info!("Added missing core area: _fatigue (cortical_idx=2)");
365 }
366
367 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(pain_id) {
368 let pain_area = create_pain_area();
369 e.insert(pain_area);
370 areas_added += 1;
371 tracing::info!("Added missing core area: _pain (cortical_idx=3)");
372 }
373
374 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(pleasure_id) {
375 let pleasure_area = create_pleasure_area();
376 e.insert(pleasure_area);
377 areas_added += 1;
378 tracing::info!("Added missing core area: _pleasure (cortical_idx=4)");
379 }
380
381 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(fear_id) {
382 let fear_area = create_fear_area();
383 e.insert(fear_area);
384 areas_added += 1;
385 tracing::info!("Added missing core area: _fear (cortical_idx=5)");
386 }
387
388 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(hope_id) {
389 let hope_area = create_hope_area();
390 e.insert(hope_area);
391 areas_added += 1;
392 tracing::info!("Added missing core area: _hope (cortical_idx=6)");
393 }
394
395 let required_morphologies = vec![
397 "block_to_block",
398 "projector",
399 "centered_projector",
400 "transpose_xy",
401 "transpose_yz",
402 "transpose_xz",
403 "sweeper",
404 "last_to_first",
405 "first_to_last",
406 "bitmask_encoder_x",
407 "bitmask_encoder_y",
408 "bitmask_encoder_z",
409 "bitmask_decoder_x",
410 "bitmask_decoder_y",
411 "bitmask_decoder_z",
412 "episodic_memory",
413 "episodic_scan",
414 "memory_replay",
415 "associative_memory",
416 "rotator_z",
417 "all_to_0-0-0",
418 "0-0-0_to_all",
419 "tile",
420 "lateral_+x",
421 "lateral_-x",
422 "lateral_+y",
423 "lateral_-y",
424 "lateral_+z",
425 "lateral_-z",
426 ];
427
428 for morph_name in required_morphologies {
429 if !genome.morphologies.contains(morph_name) {
430 morphologies_added += 1;
431 }
432 }
433
434 if morphologies_added > 0 {
436 add_core_morphologies(&mut genome.morphologies);
437 tracing::info!("Added {} missing core morphologies", morphologies_added);
438 }
439
440 (areas_added, morphologies_added)
441}
442
443pub fn add_core_morphologies(registry: &mut MorphologyRegistry) {
445 use crate::{Morphology, MorphologyParameters, MorphologyType};
446
447 registry.add_morphology(
449 "block_to_block".to_string(),
450 Morphology {
451 morphology_type: MorphologyType::Vectors,
452 parameters: MorphologyParameters::Vectors {
453 vectors: vec![[0, 0, 0]],
454 },
455 class: "core".to_string(),
456 },
457 );
458
459 registry.add_morphology(
461 "projector".to_string(),
462 Morphology {
463 morphology_type: MorphologyType::Functions,
464 parameters: MorphologyParameters::Functions {},
465 class: "core".to_string(),
466 },
467 );
468
469 registry.add_morphology(
471 "centered_projector".to_string(),
472 Morphology {
473 morphology_type: MorphologyType::Functions,
474 parameters: MorphologyParameters::Functions {},
475 class: "core".to_string(),
476 },
477 );
478
479 registry.add_morphology(
481 "transpose_xy".to_string(),
482 Morphology {
483 morphology_type: MorphologyType::Functions,
484 parameters: MorphologyParameters::Functions {},
485 class: "core".to_string(),
486 },
487 );
488
489 registry.add_morphology(
491 "transpose_yz".to_string(),
492 Morphology {
493 morphology_type: MorphologyType::Functions,
494 parameters: MorphologyParameters::Functions {},
495 class: "core".to_string(),
496 },
497 );
498
499 registry.add_morphology(
501 "transpose_xz".to_string(),
502 Morphology {
503 morphology_type: MorphologyType::Functions,
504 parameters: MorphologyParameters::Functions {},
505 class: "core".to_string(),
506 },
507 );
508
509 registry.add_morphology(
511 "sweeper".to_string(),
512 Morphology {
513 morphology_type: MorphologyType::Functions,
514 parameters: MorphologyParameters::Functions {},
515 class: "core".to_string(),
516 },
517 );
518
519 registry.add_morphology(
521 "last_to_first".to_string(),
522 Morphology {
523 morphology_type: MorphologyType::Functions,
524 parameters: MorphologyParameters::Functions {},
525 class: "core".to_string(),
526 },
527 );
528
529 registry.add_morphology(
531 "first_to_last".to_string(),
532 Morphology {
533 morphology_type: MorphologyType::Functions,
534 parameters: MorphologyParameters::Functions {},
535 class: "core".to_string(),
536 },
537 );
538
539 registry.add_morphology(
541 "episodic_memory".to_string(),
542 Morphology {
543 morphology_type: MorphologyType::Functions,
544 parameters: MorphologyParameters::Functions {},
545 class: "core".to_string(),
546 },
547 );
548
549 registry.add_morphology(
551 "episodic_scan".to_string(),
552 Morphology {
553 morphology_type: MorphologyType::Functions,
554 parameters: MorphologyParameters::Functions {},
555 class: "core".to_string(),
556 },
557 );
558
559 registry.add_morphology(
561 "memory_replay".to_string(),
562 Morphology {
563 morphology_type: MorphologyType::Functions,
564 parameters: MorphologyParameters::Functions {},
565 class: "core".to_string(),
566 },
567 );
568
569 registry.add_morphology(
571 "associative_memory".to_string(),
572 Morphology {
573 morphology_type: MorphologyType::Functions,
574 parameters: MorphologyParameters::Functions {},
575 class: "core".to_string(),
576 },
577 );
578
579 registry.add_morphology(
581 "rotator_z".to_string(),
582 Morphology {
583 morphology_type: MorphologyType::Functions,
584 parameters: MorphologyParameters::Functions {},
585 class: "core".to_string(),
586 },
587 );
588
589 registry.add_morphology(
591 "bitmask_encoder_x".to_string(),
592 Morphology {
593 morphology_type: MorphologyType::Functions,
594 parameters: MorphologyParameters::Functions {},
595 class: "core".to_string(),
596 },
597 );
598
599 registry.add_morphology(
601 "bitmask_encoder_y".to_string(),
602 Morphology {
603 morphology_type: MorphologyType::Functions,
604 parameters: MorphologyParameters::Functions {},
605 class: "core".to_string(),
606 },
607 );
608
609 registry.add_morphology(
611 "bitmask_encoder_z".to_string(),
612 Morphology {
613 morphology_type: MorphologyType::Functions,
614 parameters: MorphologyParameters::Functions {},
615 class: "core".to_string(),
616 },
617 );
618
619 registry.add_morphology(
621 "bitmask_decoder_x".to_string(),
622 Morphology {
623 morphology_type: MorphologyType::Functions,
624 parameters: MorphologyParameters::Functions {},
625 class: "core".to_string(),
626 },
627 );
628
629 registry.add_morphology(
631 "bitmask_decoder_y".to_string(),
632 Morphology {
633 morphology_type: MorphologyType::Functions,
634 parameters: MorphologyParameters::Functions {},
635 class: "core".to_string(),
636 },
637 );
638
639 registry.add_morphology(
641 "bitmask_decoder_z".to_string(),
642 Morphology {
643 morphology_type: MorphologyType::Functions,
644 parameters: MorphologyParameters::Functions {},
645 class: "core".to_string(),
646 },
647 );
648
649 registry.add_morphology(
651 "all_to_0-0-0".to_string(),
652 Morphology {
653 morphology_type: MorphologyType::Patterns,
654 parameters: MorphologyParameters::Patterns {
655 patterns: vec![[
656 vec![
657 crate::PatternElement::Wildcard,
658 crate::PatternElement::Wildcard,
659 crate::PatternElement::Wildcard,
660 ],
661 vec![
662 crate::PatternElement::Value(0),
663 crate::PatternElement::Value(0),
664 crate::PatternElement::Value(0),
665 ],
666 ]],
667 },
668 class: "core".to_string(),
669 },
670 );
671
672 registry.add_morphology(
674 "0-0-0_to_all".to_string(),
675 Morphology {
676 morphology_type: MorphologyType::Patterns,
677 parameters: MorphologyParameters::Patterns {
678 patterns: vec![[
679 vec![
680 crate::PatternElement::Value(0),
681 crate::PatternElement::Value(0),
682 crate::PatternElement::Value(0),
683 ],
684 vec![
685 crate::PatternElement::Wildcard,
686 crate::PatternElement::Wildcard,
687 crate::PatternElement::Wildcard,
688 ],
689 ]],
690 },
691 class: "core".to_string(),
692 },
693 );
694
695 registry.add_morphology(
697 "tile".to_string(),
698 Morphology {
699 morphology_type: MorphologyType::Composite,
700 parameters: MorphologyParameters::Composite {
701 src_seed: [16, 16, 1],
702 src_pattern: vec![[1, 0], [1, 0], [1, 0]],
703 mapper_morphology: "projector".to_string(),
704 },
705 class: "core".to_string(),
706 },
707 );
708
709 registry.add_morphology(
711 "lateral_+x".to_string(),
712 Morphology {
713 morphology_type: MorphologyType::Vectors,
714 parameters: MorphologyParameters::Vectors {
715 vectors: vec![[1, 0, 0]],
716 },
717 class: "core".to_string(),
718 },
719 );
720
721 registry.add_morphology(
723 "lateral_-x".to_string(),
724 Morphology {
725 morphology_type: MorphologyType::Vectors,
726 parameters: MorphologyParameters::Vectors {
727 vectors: vec![[-1, 0, 0]],
728 },
729 class: "core".to_string(),
730 },
731 );
732
733 registry.add_morphology(
735 "lateral_+y".to_string(),
736 Morphology {
737 morphology_type: MorphologyType::Vectors,
738 parameters: MorphologyParameters::Vectors {
739 vectors: vec![[0, 1, 0]],
740 },
741 class: "core".to_string(),
742 },
743 );
744
745 registry.add_morphology(
747 "lateral_-y".to_string(),
748 Morphology {
749 morphology_type: MorphologyType::Vectors,
750 parameters: MorphologyParameters::Vectors {
751 vectors: vec![[0, -1, 0]],
752 },
753 class: "core".to_string(),
754 },
755 );
756
757 registry.add_morphology(
759 "lateral_+z".to_string(),
760 Morphology {
761 morphology_type: MorphologyType::Vectors,
762 parameters: MorphologyParameters::Vectors {
763 vectors: vec![[0, 0, 1]],
764 },
765 class: "core".to_string(),
766 },
767 );
768
769 registry.add_morphology(
771 "lateral_-z".to_string(),
772 Morphology {
773 morphology_type: MorphologyType::Vectors,
774 parameters: MorphologyParameters::Vectors {
775 vectors: vec![[0, 0, -1]],
776 },
777 class: "core".to_string(),
778 },
779 );
780}
781
782pub fn load_essential_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
786 use crate::genome::loader::load_genome_from_json;
787 let mut genome = load_genome_from_json(ESSENTIAL_GENOME_JSON)?;
788 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
789 if areas_added > 0 || morphs_added > 0 {
790 tracing::info!(
791 "Essential genome: added {} core areas, {} core morphologies",
792 areas_added,
793 morphs_added
794 );
795 }
796 Ok(genome)
797}
798
799pub fn load_barebones_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
803 use crate::genome::loader::load_genome_from_json;
804 let mut genome = load_genome_from_json(BAREBONES_GENOME_JSON)?;
805 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
806 if areas_added > 0 || morphs_added > 0 {
807 tracing::info!(
808 "Barebones genome: added {} core areas, {} core morphologies",
809 areas_added,
810 morphs_added
811 );
812 }
813 Ok(genome)
814}
815
816pub fn load_test_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
820 use crate::genome::loader::load_genome_from_json;
821 let mut genome = load_genome_from_json(TEST_GENOME_JSON)?;
822 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
823 if areas_added > 0 || morphs_added > 0 {
824 tracing::info!(
825 "Test genome: added {} core areas, {} core morphologies",
826 areas_added,
827 morphs_added
828 );
829 }
830 Ok(genome)
831}
832
833pub fn load_vision_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
837 use crate::genome::loader::load_genome_from_json;
838 let mut genome = load_genome_from_json(VISION_GENOME_JSON)?;
839 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
840 if areas_added > 0 || morphs_added > 0 {
841 tracing::info!(
842 "Vision genome: added {} core areas, {} core morphologies",
843 areas_added,
844 morphs_added
845 );
846 }
847 Ok(genome)
848}
849
850#[cfg(test)]
851mod tests {
852 use super::*;
853
854 #[test]
855 fn test_create_minimal_genome() {
856 let genome = create_minimal_genome("test_genome".to_string(), "Test Genome".to_string());
857
858 assert_eq!(genome.metadata.genome_id, "test_genome");
859 assert_eq!(genome.metadata.version, "2.0");
860 assert_eq!(genome.cortical_areas.len(), 0);
861 assert_eq!(genome.morphologies.count(), 0);
862 }
863
864 #[test]
865 fn test_create_genome_with_core_areas() {
866 let genome =
867 create_genome_with_core_areas("test_genome".to_string(), "Test Genome".to_string());
868
869 assert_eq!(genome.metadata.genome_id, "test_genome");
870 assert_eq!(genome.cortical_areas.len(), 7);
871
872 let death_id = crate::genome::parser::string_to_cortical_id("_death").expect("Valid ID");
873 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
874 let fatigue_id =
875 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid ID");
876 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid ID");
877 let pleasure_id =
878 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid ID");
879 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid ID");
880 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid ID");
881 assert!(genome.cortical_areas.contains_key(&death_id));
882 assert!(genome.cortical_areas.contains_key(&power_id));
883 assert!(genome.cortical_areas.contains_key(&fatigue_id));
884 assert!(genome.cortical_areas.contains_key(&pain_id));
885 assert!(genome.cortical_areas.contains_key(&pleasure_id));
886 assert!(genome.cortical_areas.contains_key(&fear_id));
887 assert!(genome.cortical_areas.contains_key(&hope_id));
888
889 let power = genome.cortical_areas.get(&power_id).unwrap();
891 assert_eq!(power.cortical_id.as_base_64(), power_id.as_base_64());
892 assert_eq!(power.cortical_idx, 1);
893 assert_eq!(power.dimensions.width, 1);
894 assert_eq!(power.dimensions.height, 1);
895 assert_eq!(power.dimensions.depth, 1);
896 assert_eq!(
897 power
898 .properties
899 .get("degeneration")
900 .and_then(|v| v.as_f64()),
901 Some(0.0)
902 );
903 assert_eq!(
904 power
905 .properties
906 .get("psp_uniform_distribution")
907 .and_then(|v| v.as_bool()),
908 Some(true)
909 );
910 }
911
912 #[test]
913 fn test_create_genome_with_core_morphologies() {
914 let genome = create_genome_with_core_morphologies(
915 "test_genome".to_string(),
916 "Test Genome".to_string(),
917 );
918
919 assert_eq!(genome.metadata.genome_id, "test_genome");
920 assert!(genome.morphologies.count() > 0);
921 assert!(genome.morphologies.contains("block_to_block"));
922 assert!(genome.morphologies.contains("projector"));
923 assert!(genome.morphologies.contains("centered_projector"));
924 assert!(genome.morphologies.contains("transpose_xy"));
925 assert!(genome.morphologies.contains("transpose_yz"));
926 assert!(genome.morphologies.contains("transpose_xz"));
927 assert!(genome.morphologies.contains("first_to_last"));
928 assert!(genome.morphologies.contains("lateral_+x"));
929 }
930
931 #[test]
932 fn test_add_core_morphologies() {
933 let mut registry = MorphologyRegistry::new();
934 add_core_morphologies(&mut registry);
935
936 assert!(registry.count() >= 11);
938 assert!(registry.contains("block_to_block"));
939 assert!(registry.contains("projector"));
940 assert!(registry.contains("centered_projector"));
941 assert!(registry.contains("transpose_xy"));
942 assert!(registry.contains("transpose_yz"));
943 assert!(registry.contains("transpose_xz"));
944 assert!(registry.contains("first_to_last"));
945 assert!(registry.contains("all_to_0-0-0"));
946 assert!(registry.contains("lateral_+x"));
947 assert!(registry.contains("lateral_-z"));
948 assert!(registry.contains("episodic_memory"));
949 assert!(registry.contains("episodic_scan"));
950 assert!(registry.contains("associative_memory"));
951 }
952
953 #[test]
954 fn test_embedded_genomes_exist() {
955 #[allow(clippy::const_is_empty)]
959 {
960 assert!(!ESSENTIAL_GENOME_JSON.is_empty());
961 assert!(!BAREBONES_GENOME_JSON.is_empty());
962 assert!(!TEST_GENOME_JSON.is_empty());
963 assert!(!VISION_GENOME_JSON.is_empty());
964 }
965 }
966
967 fn assert_power_has_zero_degeneration_and_psp_uniform(genome: &RuntimeGenome) {
968 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
969 let power = genome
970 .cortical_areas
971 .get(&power_id)
972 .expect("default genomes must include Power");
973 assert_eq!(
974 power
975 .properties
976 .get("degeneration")
977 .and_then(|v| v.as_f64()),
978 Some(0.0),
979 "default-genome Power degeneration must be 0"
980 );
981 assert_eq!(
982 power
983 .properties
984 .get("psp_uniform_distribution")
985 .and_then(|v| v.as_bool()),
986 Some(true),
987 "default-genome Power must have PSP uniformity on"
988 );
989 }
990
991 #[test]
992 fn test_load_essential_genome() {
993 let genome = load_essential_genome().expect("Failed to load essential genome");
994 assert!(!genome.cortical_areas.is_empty());
995 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
997 assert!(genome.cortical_areas.contains_key(&power_id));
998 assert_power_has_zero_degeneration_and_psp_uniform(&genome);
999 }
1000
1001 #[test]
1002 fn test_load_barebones_genome_power_defaults() {
1003 let genome = load_barebones_genome().expect("Failed to load barebones genome");
1004 assert_power_has_zero_degeneration_and_psp_uniform(&genome);
1005 }
1006
1007 #[test]
1008 fn test_ensure_core_components_adds_missing_areas() {
1009 let mut genome = create_minimal_genome("test".to_string(), "Test".to_string());
1011
1012 assert_eq!(genome.cortical_areas.len(), 0);
1013
1014 let (areas_added, _) = ensure_core_components(&mut genome);
1016
1017 assert_eq!(areas_added, 7);
1019
1020 let death_id = crate::genome::parser::string_to_cortical_id("_death").expect("Valid ID");
1021 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
1022 let fatigue_id =
1023 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid ID");
1024 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid ID");
1025 let pleasure_id =
1026 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid ID");
1027 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid ID");
1028 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid ID");
1029 assert!(genome.cortical_areas.contains_key(&death_id));
1030 assert!(genome.cortical_areas.contains_key(&power_id));
1031 assert!(genome.cortical_areas.contains_key(&fatigue_id));
1032 assert!(genome.cortical_areas.contains_key(&pain_id));
1033 assert!(genome.cortical_areas.contains_key(&pleasure_id));
1034 assert!(genome.cortical_areas.contains_key(&fear_id));
1035 assert!(genome.cortical_areas.contains_key(&hope_id));
1036
1037 assert_eq!(
1039 genome.cortical_areas.get(&death_id).unwrap().cortical_idx,
1040 0
1041 );
1042 assert_eq!(
1043 genome.cortical_areas.get(&power_id).unwrap().cortical_idx,
1044 1
1045 );
1046 assert_eq!(
1047 genome.cortical_areas.get(&fatigue_id).unwrap().cortical_idx,
1048 2
1049 );
1050 assert_eq!(genome.cortical_areas.get(&pain_id).unwrap().cortical_idx, 3);
1051 assert_eq!(
1052 genome
1053 .cortical_areas
1054 .get(&pleasure_id)
1055 .unwrap()
1056 .cortical_idx,
1057 4
1058 );
1059 assert_eq!(genome.cortical_areas.get(&fear_id).unwrap().cortical_idx, 5);
1060 assert_eq!(genome.cortical_areas.get(&hope_id).unwrap().cortical_idx, 6);
1061 }
1062
1063 #[test]
1064 fn test_ensure_core_components_adds_missing_morphologies() {
1065 let mut genome = create_genome_with_core_areas("test".to_string(), "Test".to_string());
1067
1068 assert_eq!(genome.morphologies.count(), 0);
1069
1070 let (_, morphs_added) = ensure_core_components(&mut genome);
1072
1073 assert!(morphs_added > 0);
1075 assert!(genome.morphologies.contains("block_to_block"));
1076 assert!(genome.morphologies.contains("projector"));
1077 assert!(genome.morphologies.contains("centered_projector"));
1078 assert!(genome.morphologies.contains("transpose_xy"));
1079 assert!(genome.morphologies.contains("transpose_yz"));
1080 assert!(genome.morphologies.contains("transpose_xz"));
1081 assert!(genome.morphologies.contains("first_to_last"));
1082 assert!(genome.morphologies.contains("episodic_memory"));
1083 assert!(genome.morphologies.contains("lateral_+x"));
1084 }
1085
1086 #[test]
1087 fn test_ensure_core_components_idempotent() {
1088 let mut genome = create_genome_with_core_areas("test".to_string(), "Test".to_string());
1090 add_core_morphologies(&mut genome.morphologies);
1091
1092 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
1094
1095 assert_eq!(areas_added, 0);
1097 assert_eq!(morphs_added, 0);
1098 }
1099}