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