use feagi_structures::genomic::cortical_area::CorticalArea;
use feagi_structures::genomic::cortical_area::CorticalID;
use feagi_structures::genomic::BrainRegion;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct RuntimeGenome {
pub metadata: GenomeMetadata,
pub cortical_areas: HashMap<CorticalID, CorticalArea>,
pub brain_regions: HashMap<String, BrainRegion>,
pub morphologies: MorphologyRegistry,
pub physiology: PhysiologyConfig,
pub signatures: GenomeSignatures,
pub stats: GenomeStats,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenomeMetadata {
pub genome_id: String,
pub genome_title: String,
pub genome_description: String,
pub version: String,
pub timestamp: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub brain_regions_root: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct MorphologyRegistry {
morphologies: HashMap<String, Morphology>,
}
impl MorphologyRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn add_morphology(&mut self, id: String, morphology: Morphology) {
self.morphologies.insert(id, morphology);
}
pub fn get(&self, id: &str) -> Option<&Morphology> {
self.morphologies.get(id)
}
pub fn contains(&self, id: &str) -> bool {
self.morphologies.contains_key(id)
}
pub fn morphology_ids(&self) -> Vec<String> {
self.morphologies.keys().cloned().collect()
}
pub fn remove_morphology(&mut self, id: &str) -> bool {
self.morphologies.remove(id).is_some()
}
pub fn count(&self) -> usize {
self.morphologies.len()
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &Morphology)> {
self.morphologies.iter()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Morphology {
pub morphology_type: MorphologyType,
pub parameters: MorphologyParameters,
pub class: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum MorphologyType {
Vectors,
Patterns,
Functions,
Composite,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum MorphologyParameters {
Vectors { vectors: Vec<[i32; 3]> },
Patterns {
patterns: Vec<[Vec<PatternElement>; 2]>,
},
Functions {},
Composite {
src_seed: [u32; 3],
src_pattern: Vec<[i32; 2]>,
mapper_morphology: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PatternElement {
Value(i32),
Wildcard, Skip, Exclude, }
impl Serialize for PatternElement {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
PatternElement::Value(v) => serializer.serialize_i32(*v),
PatternElement::Wildcard => serializer.serialize_str("*"),
PatternElement::Skip => serializer.serialize_str("?"),
PatternElement::Exclude => serializer.serialize_str("!"),
}
}
}
impl<'de> Deserialize<'de> for PatternElement {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = serde_json::Value::deserialize(deserializer)?;
match value {
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
Ok(PatternElement::Value(i as i32))
} else {
Err(serde::de::Error::custom(
"Pattern element must be an integer",
))
}
}
serde_json::Value::String(s) => match s.as_str() {
"*" => Ok(PatternElement::Wildcard),
"?" => Ok(PatternElement::Skip),
"!" => Ok(PatternElement::Exclude),
_ => Err(serde::de::Error::custom(format!(
"Unknown pattern element: {}",
s
))),
},
_ => Err(serde::de::Error::custom(
"Pattern element must be number or string",
)),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PhysiologyConfig {
pub simulation_timestep: f64,
pub max_age: u64,
pub evolution_burst_count: u64,
pub ipu_idle_threshold: u64,
pub plasticity_queue_depth: usize,
pub lifespan_mgmt_interval: u64,
#[serde(default = "default_quantization_precision")]
pub quantization_precision: String,
}
pub fn default_quantization_precision() -> String {
"int8".to_string() }
impl Default for PhysiologyConfig {
fn default() -> Self {
Self {
simulation_timestep: 0.025,
max_age: 10_000_000,
evolution_burst_count: 50,
ipu_idle_threshold: 1000,
plasticity_queue_depth: 3,
lifespan_mgmt_interval: 10,
quantization_precision: default_quantization_precision(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenomeSignatures {
pub genome: String,
pub blueprint: String,
pub physiology: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub morphologies: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct GenomeStats {
pub innate_cortical_area_count: usize,
pub innate_neuron_count: usize,
pub innate_synapse_count: usize,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_morphology_registry_creation() {
let registry = MorphologyRegistry::new();
assert_eq!(registry.count(), 0);
}
#[test]
fn test_morphology_registry_add_and_get() {
let mut registry = MorphologyRegistry::new();
let morphology = Morphology {
morphology_type: MorphologyType::Vectors,
parameters: MorphologyParameters::Vectors {
vectors: vec![[1, 0, 0], [0, 1, 0]],
},
class: "test".to_string(),
};
registry.add_morphology("test_morph".to_string(), morphology);
assert_eq!(registry.count(), 1);
assert!(registry.contains("test_morph"));
assert!(registry.get("test_morph").is_some());
}
#[test]
fn test_physiology_config_default() {
let config = PhysiologyConfig::default();
assert_eq!(config.simulation_timestep, 0.025);
assert_eq!(config.max_age, 10_000_000);
}
}