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