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 morphologies: MorphologyRegistry::new(),
256 physiology: PhysiologyConfig::default(),
257 signatures: GenomeSignatures {
258 genome: String::new(),
259 blueprint: String::new(),
260 physiology: String::new(),
261 morphologies: None,
262 },
263 stats: GenomeStats::default(),
264 }
265}
266
267pub fn create_genome_with_core_areas(genome_id: String, genome_title: String) -> RuntimeGenome {
269 let mut genome = create_minimal_genome(genome_id, genome_title);
270
271 let death_id =
273 crate::genome::parser::string_to_cortical_id("_death").expect("Valid cortical ID");
274 let power_id =
275 crate::genome::parser::string_to_cortical_id("_power").expect("Valid cortical ID");
276 let fatigue_id =
277 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid cortical ID");
278 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid cortical ID");
279 let pleasure_id =
280 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid cortical ID");
281 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid cortical ID");
282 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid cortical ID");
283
284 genome.cortical_areas.insert(death_id, create_death_area());
285 genome.cortical_areas.insert(power_id, create_power_area());
286 genome
287 .cortical_areas
288 .insert(fatigue_id, create_fatigue_area());
289 genome.cortical_areas.insert(pain_id, create_pain_area());
290 genome
291 .cortical_areas
292 .insert(pleasure_id, create_pleasure_area());
293 genome.cortical_areas.insert(fear_id, create_fear_area());
294 genome.cortical_areas.insert(hope_id, create_hope_area());
295
296 genome
297}
298
299pub fn create_genome_with_core_morphologies(
301 genome_id: String,
302 genome_title: String,
303) -> RuntimeGenome {
304 let mut genome = create_minimal_genome(genome_id, genome_title);
305
306 add_core_morphologies(&mut genome.morphologies);
308
309 genome
310}
311
312pub fn ensure_core_components(genome: &mut RuntimeGenome) -> (usize, usize) {
327 let mut areas_added = 0;
328 let mut morphologies_added = 0;
329
330 let death_id =
332 crate::genome::parser::string_to_cortical_id("_death").expect("Valid cortical ID");
333 let power_id =
334 crate::genome::parser::string_to_cortical_id("_power").expect("Valid cortical ID");
335 let fatigue_id =
336 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid cortical ID");
337 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid cortical ID");
338 let pleasure_id =
339 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid cortical ID");
340 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid cortical ID");
341 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid cortical ID");
342
343 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(death_id) {
345 let death_area = create_death_area();
346 e.insert(death_area);
347 areas_added += 1;
348 tracing::info!("Added missing core area: _death (cortical_idx=0)");
349 }
350
351 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(power_id) {
352 let power_area = create_power_area();
353 e.insert(power_area);
354 areas_added += 1;
355 tracing::info!("Added missing core area: _power (cortical_idx=1)");
356 }
357
358 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(fatigue_id) {
359 let fatigue_area = create_fatigue_area();
360 e.insert(fatigue_area);
361 areas_added += 1;
362 tracing::info!("Added missing core area: _fatigue (cortical_idx=2)");
363 }
364
365 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(pain_id) {
366 let pain_area = create_pain_area();
367 e.insert(pain_area);
368 areas_added += 1;
369 tracing::info!("Added missing core area: _pain (cortical_idx=3)");
370 }
371
372 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(pleasure_id) {
373 let pleasure_area = create_pleasure_area();
374 e.insert(pleasure_area);
375 areas_added += 1;
376 tracing::info!("Added missing core area: _pleasure (cortical_idx=4)");
377 }
378
379 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(fear_id) {
380 let fear_area = create_fear_area();
381 e.insert(fear_area);
382 areas_added += 1;
383 tracing::info!("Added missing core area: _fear (cortical_idx=5)");
384 }
385
386 if let std::collections::hash_map::Entry::Vacant(e) = genome.cortical_areas.entry(hope_id) {
387 let hope_area = create_hope_area();
388 e.insert(hope_area);
389 areas_added += 1;
390 tracing::info!("Added missing core area: _hope (cortical_idx=6)");
391 }
392
393 let required_morphologies = vec![
395 "block_to_block",
396 "projector",
397 "centered_projector",
398 "transpose_xy",
399 "transpose_yz",
400 "transpose_xz",
401 "sweeper",
402 "last_to_first",
403 "first_to_last",
404 "bitmask_encoder_x",
405 "bitmask_encoder_y",
406 "bitmask_encoder_z",
407 "bitmask_decoder_x",
408 "bitmask_decoder_y",
409 "bitmask_decoder_z",
410 "episodic_memory",
411 "memory_replay",
412 "associative_memory",
413 "rotator_z",
414 "all_to_0-0-0",
415 "0-0-0_to_all",
416 "tile",
417 "lateral_+x",
418 "lateral_-x",
419 "lateral_+y",
420 "lateral_-y",
421 "lateral_+z",
422 "lateral_-z",
423 ];
424
425 for morph_name in required_morphologies {
426 if !genome.morphologies.contains(morph_name) {
427 morphologies_added += 1;
428 }
429 }
430
431 if morphologies_added > 0 {
433 add_core_morphologies(&mut genome.morphologies);
434 tracing::info!("Added {} missing core morphologies", morphologies_added);
435 }
436
437 (areas_added, morphologies_added)
438}
439
440pub fn add_core_morphologies(registry: &mut MorphologyRegistry) {
442 use crate::{Morphology, MorphologyParameters, MorphologyType};
443
444 registry.add_morphology(
446 "block_to_block".to_string(),
447 Morphology {
448 morphology_type: MorphologyType::Vectors,
449 parameters: MorphologyParameters::Vectors {
450 vectors: vec![[0, 0, 0]],
451 },
452 class: "core".to_string(),
453 },
454 );
455
456 registry.add_morphology(
458 "projector".to_string(),
459 Morphology {
460 morphology_type: MorphologyType::Functions,
461 parameters: MorphologyParameters::Functions {},
462 class: "core".to_string(),
463 },
464 );
465
466 registry.add_morphology(
468 "centered_projector".to_string(),
469 Morphology {
470 morphology_type: MorphologyType::Functions,
471 parameters: MorphologyParameters::Functions {},
472 class: "core".to_string(),
473 },
474 );
475
476 registry.add_morphology(
478 "transpose_xy".to_string(),
479 Morphology {
480 morphology_type: MorphologyType::Functions,
481 parameters: MorphologyParameters::Functions {},
482 class: "core".to_string(),
483 },
484 );
485
486 registry.add_morphology(
488 "transpose_yz".to_string(),
489 Morphology {
490 morphology_type: MorphologyType::Functions,
491 parameters: MorphologyParameters::Functions {},
492 class: "core".to_string(),
493 },
494 );
495
496 registry.add_morphology(
498 "transpose_xz".to_string(),
499 Morphology {
500 morphology_type: MorphologyType::Functions,
501 parameters: MorphologyParameters::Functions {},
502 class: "core".to_string(),
503 },
504 );
505
506 registry.add_morphology(
508 "sweeper".to_string(),
509 Morphology {
510 morphology_type: MorphologyType::Functions,
511 parameters: MorphologyParameters::Functions {},
512 class: "core".to_string(),
513 },
514 );
515
516 registry.add_morphology(
518 "last_to_first".to_string(),
519 Morphology {
520 morphology_type: MorphologyType::Functions,
521 parameters: MorphologyParameters::Functions {},
522 class: "core".to_string(),
523 },
524 );
525
526 registry.add_morphology(
528 "first_to_last".to_string(),
529 Morphology {
530 morphology_type: MorphologyType::Functions,
531 parameters: MorphologyParameters::Functions {},
532 class: "core".to_string(),
533 },
534 );
535
536 registry.add_morphology(
538 "episodic_memory".to_string(),
539 Morphology {
540 morphology_type: MorphologyType::Functions,
541 parameters: MorphologyParameters::Functions {},
542 class: "core".to_string(),
543 },
544 );
545
546 registry.add_morphology(
548 "memory_replay".to_string(),
549 Morphology {
550 morphology_type: MorphologyType::Functions,
551 parameters: MorphologyParameters::Functions {},
552 class: "core".to_string(),
553 },
554 );
555
556 registry.add_morphology(
558 "associative_memory".to_string(),
559 Morphology {
560 morphology_type: MorphologyType::Functions,
561 parameters: MorphologyParameters::Functions {},
562 class: "core".to_string(),
563 },
564 );
565
566 registry.add_morphology(
568 "rotator_z".to_string(),
569 Morphology {
570 morphology_type: MorphologyType::Functions,
571 parameters: MorphologyParameters::Functions {},
572 class: "core".to_string(),
573 },
574 );
575
576 registry.add_morphology(
578 "bitmask_encoder_x".to_string(),
579 Morphology {
580 morphology_type: MorphologyType::Functions,
581 parameters: MorphologyParameters::Functions {},
582 class: "core".to_string(),
583 },
584 );
585
586 registry.add_morphology(
588 "bitmask_encoder_y".to_string(),
589 Morphology {
590 morphology_type: MorphologyType::Functions,
591 parameters: MorphologyParameters::Functions {},
592 class: "core".to_string(),
593 },
594 );
595
596 registry.add_morphology(
598 "bitmask_encoder_z".to_string(),
599 Morphology {
600 morphology_type: MorphologyType::Functions,
601 parameters: MorphologyParameters::Functions {},
602 class: "core".to_string(),
603 },
604 );
605
606 registry.add_morphology(
608 "bitmask_decoder_x".to_string(),
609 Morphology {
610 morphology_type: MorphologyType::Functions,
611 parameters: MorphologyParameters::Functions {},
612 class: "core".to_string(),
613 },
614 );
615
616 registry.add_morphology(
618 "bitmask_decoder_y".to_string(),
619 Morphology {
620 morphology_type: MorphologyType::Functions,
621 parameters: MorphologyParameters::Functions {},
622 class: "core".to_string(),
623 },
624 );
625
626 registry.add_morphology(
628 "bitmask_decoder_z".to_string(),
629 Morphology {
630 morphology_type: MorphologyType::Functions,
631 parameters: MorphologyParameters::Functions {},
632 class: "core".to_string(),
633 },
634 );
635
636 registry.add_morphology(
638 "all_to_0-0-0".to_string(),
639 Morphology {
640 morphology_type: MorphologyType::Patterns,
641 parameters: MorphologyParameters::Patterns {
642 patterns: vec![[
643 vec![
644 crate::PatternElement::Wildcard,
645 crate::PatternElement::Wildcard,
646 crate::PatternElement::Wildcard,
647 ],
648 vec![
649 crate::PatternElement::Value(0),
650 crate::PatternElement::Value(0),
651 crate::PatternElement::Value(0),
652 ],
653 ]],
654 },
655 class: "core".to_string(),
656 },
657 );
658
659 registry.add_morphology(
661 "0-0-0_to_all".to_string(),
662 Morphology {
663 morphology_type: MorphologyType::Patterns,
664 parameters: MorphologyParameters::Patterns {
665 patterns: vec![[
666 vec![
667 crate::PatternElement::Value(0),
668 crate::PatternElement::Value(0),
669 crate::PatternElement::Value(0),
670 ],
671 vec![
672 crate::PatternElement::Wildcard,
673 crate::PatternElement::Wildcard,
674 crate::PatternElement::Wildcard,
675 ],
676 ]],
677 },
678 class: "core".to_string(),
679 },
680 );
681
682 registry.add_morphology(
684 "tile".to_string(),
685 Morphology {
686 morphology_type: MorphologyType::Composite,
687 parameters: MorphologyParameters::Composite {
688 src_seed: [16, 16, 1],
689 src_pattern: vec![[1, 0], [1, 0], [1, 0]],
690 mapper_morphology: "projector".to_string(),
691 },
692 class: "core".to_string(),
693 },
694 );
695
696 registry.add_morphology(
698 "lateral_+x".to_string(),
699 Morphology {
700 morphology_type: MorphologyType::Vectors,
701 parameters: MorphologyParameters::Vectors {
702 vectors: vec![[1, 0, 0]],
703 },
704 class: "core".to_string(),
705 },
706 );
707
708 registry.add_morphology(
710 "lateral_-x".to_string(),
711 Morphology {
712 morphology_type: MorphologyType::Vectors,
713 parameters: MorphologyParameters::Vectors {
714 vectors: vec![[-1, 0, 0]],
715 },
716 class: "core".to_string(),
717 },
718 );
719
720 registry.add_morphology(
722 "lateral_+y".to_string(),
723 Morphology {
724 morphology_type: MorphologyType::Vectors,
725 parameters: MorphologyParameters::Vectors {
726 vectors: vec![[0, 1, 0]],
727 },
728 class: "core".to_string(),
729 },
730 );
731
732 registry.add_morphology(
734 "lateral_-y".to_string(),
735 Morphology {
736 morphology_type: MorphologyType::Vectors,
737 parameters: MorphologyParameters::Vectors {
738 vectors: vec![[0, -1, 0]],
739 },
740 class: "core".to_string(),
741 },
742 );
743
744 registry.add_morphology(
746 "lateral_+z".to_string(),
747 Morphology {
748 morphology_type: MorphologyType::Vectors,
749 parameters: MorphologyParameters::Vectors {
750 vectors: vec![[0, 0, 1]],
751 },
752 class: "core".to_string(),
753 },
754 );
755
756 registry.add_morphology(
758 "lateral_-z".to_string(),
759 Morphology {
760 morphology_type: MorphologyType::Vectors,
761 parameters: MorphologyParameters::Vectors {
762 vectors: vec![[0, 0, -1]],
763 },
764 class: "core".to_string(),
765 },
766 );
767}
768
769pub fn load_essential_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
773 use crate::genome::loader::load_genome_from_json;
774 let mut genome = load_genome_from_json(ESSENTIAL_GENOME_JSON)?;
775 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
776 if areas_added > 0 || morphs_added > 0 {
777 tracing::info!(
778 "Essential genome: added {} core areas, {} core morphologies",
779 areas_added,
780 morphs_added
781 );
782 }
783 Ok(genome)
784}
785
786pub fn load_barebones_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
790 use crate::genome::loader::load_genome_from_json;
791 let mut genome = load_genome_from_json(BAREBONES_GENOME_JSON)?;
792 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
793 if areas_added > 0 || morphs_added > 0 {
794 tracing::info!(
795 "Barebones genome: added {} core areas, {} core morphologies",
796 areas_added,
797 morphs_added
798 );
799 }
800 Ok(genome)
801}
802
803pub fn load_test_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
807 use crate::genome::loader::load_genome_from_json;
808 let mut genome = load_genome_from_json(TEST_GENOME_JSON)?;
809 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
810 if areas_added > 0 || morphs_added > 0 {
811 tracing::info!(
812 "Test genome: added {} core areas, {} core morphologies",
813 areas_added,
814 morphs_added
815 );
816 }
817 Ok(genome)
818}
819
820pub fn load_vision_genome() -> Result<RuntimeGenome, crate::types::EvoError> {
824 use crate::genome::loader::load_genome_from_json;
825 let mut genome = load_genome_from_json(VISION_GENOME_JSON)?;
826 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
827 if areas_added > 0 || morphs_added > 0 {
828 tracing::info!(
829 "Vision genome: added {} core areas, {} core morphologies",
830 areas_added,
831 morphs_added
832 );
833 }
834 Ok(genome)
835}
836
837#[cfg(test)]
838mod tests {
839 use super::*;
840
841 #[test]
842 fn test_create_minimal_genome() {
843 let genome = create_minimal_genome("test_genome".to_string(), "Test Genome".to_string());
844
845 assert_eq!(genome.metadata.genome_id, "test_genome");
846 assert_eq!(genome.metadata.version, "2.0");
847 assert_eq!(genome.cortical_areas.len(), 0);
848 assert_eq!(genome.morphologies.count(), 0);
849 }
850
851 #[test]
852 fn test_create_genome_with_core_areas() {
853 let genome =
854 create_genome_with_core_areas("test_genome".to_string(), "Test Genome".to_string());
855
856 assert_eq!(genome.metadata.genome_id, "test_genome");
857 assert_eq!(genome.cortical_areas.len(), 7);
858
859 let death_id = crate::genome::parser::string_to_cortical_id("_death").expect("Valid ID");
860 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
861 let fatigue_id =
862 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid ID");
863 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid ID");
864 let pleasure_id =
865 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid ID");
866 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid ID");
867 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid ID");
868 assert!(genome.cortical_areas.contains_key(&death_id));
869 assert!(genome.cortical_areas.contains_key(&power_id));
870 assert!(genome.cortical_areas.contains_key(&fatigue_id));
871 assert!(genome.cortical_areas.contains_key(&pain_id));
872 assert!(genome.cortical_areas.contains_key(&pleasure_id));
873 assert!(genome.cortical_areas.contains_key(&fear_id));
874 assert!(genome.cortical_areas.contains_key(&hope_id));
875
876 let power = genome.cortical_areas.get(&power_id).unwrap();
878 assert_eq!(power.cortical_id.as_base_64(), power_id.as_base_64());
879 assert_eq!(power.cortical_idx, 1);
880 assert_eq!(power.dimensions.width, 1);
881 assert_eq!(power.dimensions.height, 1);
882 assert_eq!(power.dimensions.depth, 1);
883 assert_eq!(
884 power
885 .properties
886 .get("degeneration")
887 .and_then(|v| v.as_f64()),
888 Some(0.0)
889 );
890 assert_eq!(
891 power
892 .properties
893 .get("psp_uniform_distribution")
894 .and_then(|v| v.as_bool()),
895 Some(true)
896 );
897 }
898
899 #[test]
900 fn test_create_genome_with_core_morphologies() {
901 let genome = create_genome_with_core_morphologies(
902 "test_genome".to_string(),
903 "Test Genome".to_string(),
904 );
905
906 assert_eq!(genome.metadata.genome_id, "test_genome");
907 assert!(genome.morphologies.count() > 0);
908 assert!(genome.morphologies.contains("block_to_block"));
909 assert!(genome.morphologies.contains("projector"));
910 assert!(genome.morphologies.contains("centered_projector"));
911 assert!(genome.morphologies.contains("transpose_xy"));
912 assert!(genome.morphologies.contains("transpose_yz"));
913 assert!(genome.morphologies.contains("transpose_xz"));
914 assert!(genome.morphologies.contains("first_to_last"));
915 assert!(genome.morphologies.contains("lateral_+x"));
916 }
917
918 #[test]
919 fn test_add_core_morphologies() {
920 let mut registry = MorphologyRegistry::new();
921 add_core_morphologies(&mut registry);
922
923 assert!(registry.count() >= 11);
925 assert!(registry.contains("block_to_block"));
926 assert!(registry.contains("projector"));
927 assert!(registry.contains("centered_projector"));
928 assert!(registry.contains("transpose_xy"));
929 assert!(registry.contains("transpose_yz"));
930 assert!(registry.contains("transpose_xz"));
931 assert!(registry.contains("first_to_last"));
932 assert!(registry.contains("all_to_0-0-0"));
933 assert!(registry.contains("lateral_+x"));
934 assert!(registry.contains("lateral_-z"));
935 }
936
937 #[test]
938 fn test_embedded_genomes_exist() {
939 #[allow(clippy::const_is_empty)]
943 {
944 assert!(!ESSENTIAL_GENOME_JSON.is_empty());
945 assert!(!BAREBONES_GENOME_JSON.is_empty());
946 assert!(!TEST_GENOME_JSON.is_empty());
947 assert!(!VISION_GENOME_JSON.is_empty());
948 }
949 }
950
951 fn assert_power_has_zero_degeneration_and_psp_uniform(genome: &RuntimeGenome) {
952 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
953 let power = genome
954 .cortical_areas
955 .get(&power_id)
956 .expect("default genomes must include Power");
957 assert_eq!(
958 power
959 .properties
960 .get("degeneration")
961 .and_then(|v| v.as_f64()),
962 Some(0.0),
963 "default-genome Power degeneration must be 0"
964 );
965 assert_eq!(
966 power
967 .properties
968 .get("psp_uniform_distribution")
969 .and_then(|v| v.as_bool()),
970 Some(true),
971 "default-genome Power must have PSP uniformity on"
972 );
973 }
974
975 #[test]
976 fn test_load_essential_genome() {
977 let genome = load_essential_genome().expect("Failed to load essential genome");
978 assert!(!genome.cortical_areas.is_empty());
979 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
981 assert!(genome.cortical_areas.contains_key(&power_id));
982 assert_power_has_zero_degeneration_and_psp_uniform(&genome);
983 }
984
985 #[test]
986 fn test_load_barebones_genome_power_defaults() {
987 let genome = load_barebones_genome().expect("Failed to load barebones genome");
988 assert_power_has_zero_degeneration_and_psp_uniform(&genome);
989 }
990
991 #[test]
992 fn test_ensure_core_components_adds_missing_areas() {
993 let mut genome = create_minimal_genome("test".to_string(), "Test".to_string());
995
996 assert_eq!(genome.cortical_areas.len(), 0);
997
998 let (areas_added, _) = ensure_core_components(&mut genome);
1000
1001 assert_eq!(areas_added, 7);
1003
1004 let death_id = crate::genome::parser::string_to_cortical_id("_death").expect("Valid ID");
1005 let power_id = crate::genome::parser::string_to_cortical_id("_power").expect("Valid ID");
1006 let fatigue_id =
1007 crate::genome::parser::string_to_cortical_id("_fatigue").expect("Valid ID");
1008 let pain_id = crate::genome::parser::string_to_cortical_id("_pain").expect("Valid ID");
1009 let pleasure_id =
1010 crate::genome::parser::string_to_cortical_id("_pleasure").expect("Valid ID");
1011 let fear_id = crate::genome::parser::string_to_cortical_id("_fear").expect("Valid ID");
1012 let hope_id = crate::genome::parser::string_to_cortical_id("_hope").expect("Valid ID");
1013 assert!(genome.cortical_areas.contains_key(&death_id));
1014 assert!(genome.cortical_areas.contains_key(&power_id));
1015 assert!(genome.cortical_areas.contains_key(&fatigue_id));
1016 assert!(genome.cortical_areas.contains_key(&pain_id));
1017 assert!(genome.cortical_areas.contains_key(&pleasure_id));
1018 assert!(genome.cortical_areas.contains_key(&fear_id));
1019 assert!(genome.cortical_areas.contains_key(&hope_id));
1020
1021 assert_eq!(
1023 genome.cortical_areas.get(&death_id).unwrap().cortical_idx,
1024 0
1025 );
1026 assert_eq!(
1027 genome.cortical_areas.get(&power_id).unwrap().cortical_idx,
1028 1
1029 );
1030 assert_eq!(
1031 genome.cortical_areas.get(&fatigue_id).unwrap().cortical_idx,
1032 2
1033 );
1034 assert_eq!(genome.cortical_areas.get(&pain_id).unwrap().cortical_idx, 3);
1035 assert_eq!(
1036 genome
1037 .cortical_areas
1038 .get(&pleasure_id)
1039 .unwrap()
1040 .cortical_idx,
1041 4
1042 );
1043 assert_eq!(genome.cortical_areas.get(&fear_id).unwrap().cortical_idx, 5);
1044 assert_eq!(genome.cortical_areas.get(&hope_id).unwrap().cortical_idx, 6);
1045 }
1046
1047 #[test]
1048 fn test_ensure_core_components_adds_missing_morphologies() {
1049 let mut genome = create_genome_with_core_areas("test".to_string(), "Test".to_string());
1051
1052 assert_eq!(genome.morphologies.count(), 0);
1053
1054 let (_, morphs_added) = ensure_core_components(&mut genome);
1056
1057 assert!(morphs_added > 0);
1059 assert!(genome.morphologies.contains("block_to_block"));
1060 assert!(genome.morphologies.contains("projector"));
1061 assert!(genome.morphologies.contains("centered_projector"));
1062 assert!(genome.morphologies.contains("transpose_xy"));
1063 assert!(genome.morphologies.contains("transpose_yz"));
1064 assert!(genome.morphologies.contains("transpose_xz"));
1065 assert!(genome.morphologies.contains("first_to_last"));
1066 assert!(genome.morphologies.contains("episodic_memory"));
1067 assert!(genome.morphologies.contains("lateral_+x"));
1068 }
1069
1070 #[test]
1071 fn test_ensure_core_components_idempotent() {
1072 let mut genome = create_genome_with_core_areas("test".to_string(), "Test".to_string());
1074 add_core_morphologies(&mut genome.morphologies);
1075
1076 let (areas_added, morphs_added) = ensure_core_components(&mut genome);
1078
1079 assert_eq!(areas_added, 0);
1081 assert_eq!(morphs_added, 0);
1082 }
1083}