1use feagi_structures::genomic::cortical_area::CorticalArea;
15use feagi_structures::genomic::cortical_area::CorticalID;
16use feagi_structures::genomic::BrainRegion;
17use serde::{Deserialize, Serialize};
18use std::collections::HashMap;
19
20#[derive(Debug, Clone)]
22pub struct RuntimeGenome {
23 pub metadata: GenomeMetadata,
25
26 pub cortical_areas: HashMap<CorticalID, CorticalArea>,
28
29 pub brain_regions: HashMap<String, BrainRegion>,
31
32 pub morphologies: MorphologyRegistry,
34
35 pub physiology: PhysiologyConfig,
37
38 pub signatures: GenomeSignatures,
40
41 pub stats: GenomeStats,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct GenomeMetadata {
48 pub genome_id: String,
49 pub genome_title: String,
50 pub genome_description: String,
51 pub version: String,
52 pub timestamp: f64, #[serde(skip_serializing_if = "Option::is_none")]
57 pub brain_regions_root: Option<String>,
58}
59
60#[derive(Debug, Clone, Default)]
62pub struct MorphologyRegistry {
63 morphologies: HashMap<String, Morphology>,
65}
66
67impl MorphologyRegistry {
68 pub fn new() -> Self {
70 Self::default()
71 }
72
73 pub fn add_morphology(&mut self, id: String, morphology: Morphology) {
75 self.morphologies.insert(id, morphology);
76 }
77
78 pub fn get(&self, id: &str) -> Option<&Morphology> {
80 self.morphologies.get(id)
81 }
82
83 pub fn contains(&self, id: &str) -> bool {
85 self.morphologies.contains_key(id)
86 }
87
88 pub fn morphology_ids(&self) -> Vec<String> {
90 self.morphologies.keys().cloned().collect()
91 }
92
93 pub fn remove_morphology(&mut self, id: &str) -> bool {
97 self.morphologies.remove(id).is_some()
98 }
99
100 pub fn count(&self) -> usize {
102 self.morphologies.len()
103 }
104
105 pub fn iter(&self) -> impl Iterator<Item = (&String, &Morphology)> {
107 self.morphologies.iter()
108 }
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct Morphology {
114 pub morphology_type: MorphologyType,
116
117 pub parameters: MorphologyParameters,
119
120 pub class: String,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
126#[serde(rename_all = "lowercase")]
127pub enum MorphologyType {
128 Vectors,
130
131 Patterns,
133
134 Functions,
136
137 Composite,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
143#[serde(untagged)]
144pub enum MorphologyParameters {
145 Vectors { vectors: Vec<[i32; 3]> },
147
148 Patterns {
150 patterns: Vec<[Vec<PatternElement>; 2]>,
151 },
152
153 Functions {},
155
156 Composite {
158 src_seed: [u32; 3],
159 src_pattern: Vec<[i32; 2]>,
160 mapper_morphology: String,
161 },
162}
163
164#[derive(Debug, Clone, PartialEq, Eq)]
166pub enum PatternElement {
167 Value(i32),
169 Wildcard, Skip, Exclude, }
176
177impl Serialize for PatternElement {
179 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
180 where
181 S: serde::Serializer,
182 {
183 match self {
184 PatternElement::Value(v) => serializer.serialize_i32(*v),
185 PatternElement::Wildcard => serializer.serialize_str("*"),
186 PatternElement::Skip => serializer.serialize_str("?"),
187 PatternElement::Exclude => serializer.serialize_str("!"),
188 }
189 }
190}
191
192impl<'de> Deserialize<'de> for PatternElement {
194 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
195 where
196 D: serde::Deserializer<'de>,
197 {
198 let value = serde_json::Value::deserialize(deserializer)?;
199 match value {
200 serde_json::Value::Number(n) => {
201 if let Some(i) = n.as_i64() {
202 Ok(PatternElement::Value(i as i32))
203 } else {
204 Err(serde::de::Error::custom(
205 "Pattern element must be an integer",
206 ))
207 }
208 }
209 serde_json::Value::String(s) => match s.as_str() {
210 "*" => Ok(PatternElement::Wildcard),
211 "?" => Ok(PatternElement::Skip),
212 "!" => Ok(PatternElement::Exclude),
213 _ => Err(serde::de::Error::custom(format!(
214 "Unknown pattern element: {}",
215 s
216 ))),
217 },
218 _ => Err(serde::de::Error::custom(
219 "Pattern element must be number or string",
220 )),
221 }
222 }
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct PhysiologyConfig {
228 pub simulation_timestep: f64,
230
231 pub max_age: u64,
233
234 pub evolution_burst_count: u64,
236
237 pub ipu_idle_threshold: u64,
239
240 pub plasticity_queue_depth: usize,
242
243 pub lifespan_mgmt_interval: u64,
245
246 #[serde(default = "default_quantization_precision")]
249 pub quantization_precision: String,
250}
251
252pub fn default_quantization_precision() -> String {
253 "int8".to_string() }
255
256impl Default for PhysiologyConfig {
257 fn default() -> Self {
258 Self {
259 simulation_timestep: 0.025,
260 max_age: 10_000_000,
261 evolution_burst_count: 50,
262 ipu_idle_threshold: 1000,
263 plasticity_queue_depth: 3,
264 lifespan_mgmt_interval: 10,
265 quantization_precision: default_quantization_precision(),
266 }
267 }
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct GenomeSignatures {
273 pub genome: String,
275
276 pub blueprint: String,
278
279 pub physiology: String,
281
282 #[serde(skip_serializing_if = "Option::is_none")]
284 pub morphologies: Option<String>,
285}
286
287#[derive(Debug, Clone, Serialize, Deserialize, Default)]
289pub struct GenomeStats {
290 pub innate_cortical_area_count: usize,
292
293 pub innate_neuron_count: usize,
295
296 pub innate_synapse_count: usize,
298}
299
300#[cfg(test)]
301mod tests {
302 use super::*;
303
304 #[test]
305 fn test_morphology_registry_creation() {
306 let registry = MorphologyRegistry::new();
307 assert_eq!(registry.count(), 0);
308 }
309
310 #[test]
311 fn test_morphology_registry_add_and_get() {
312 let mut registry = MorphologyRegistry::new();
313
314 let morphology = Morphology {
315 morphology_type: MorphologyType::Vectors,
316 parameters: MorphologyParameters::Vectors {
317 vectors: vec![[1, 0, 0], [0, 1, 0]],
318 },
319 class: "test".to_string(),
320 };
321
322 registry.add_morphology("test_morph".to_string(), morphology);
323
324 assert_eq!(registry.count(), 1);
325 assert!(registry.contains("test_morph"));
326 assert!(registry.get("test_morph").is_some());
327 }
328
329 #[test]
330 fn test_physiology_config_default() {
331 let config = PhysiologyConfig::default();
332 assert_eq!(config.simulation_timestep, 0.025);
333 assert_eq!(config.max_age, 10_000_000);
334 }
335}