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 count(&self) -> usize {
95 self.morphologies.len()
96 }
97
98 pub fn iter(&self) -> impl Iterator<Item = (&String, &Morphology)> {
100 self.morphologies.iter()
101 }
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct Morphology {
107 pub morphology_type: MorphologyType,
109
110 pub parameters: MorphologyParameters,
112
113 pub class: String,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
119#[serde(rename_all = "lowercase")]
120pub enum MorphologyType {
121 Vectors,
123
124 Patterns,
126
127 Functions,
129
130 Composite,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136#[serde(untagged)]
137pub enum MorphologyParameters {
138 Vectors { vectors: Vec<[i32; 3]> },
140
141 Patterns {
143 patterns: Vec<[Vec<PatternElement>; 2]>,
144 },
145
146 Functions {},
148
149 Composite {
151 src_seed: [u32; 3],
152 src_pattern: Vec<[i32; 2]>,
153 mapper_morphology: String,
154 },
155}
156
157#[derive(Debug, Clone, PartialEq, Eq)]
159pub enum PatternElement {
160 Value(i32),
162 Wildcard, Skip, Exclude, }
169
170impl Serialize for PatternElement {
172 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
173 where
174 S: serde::Serializer,
175 {
176 match self {
177 PatternElement::Value(v) => serializer.serialize_i32(*v),
178 PatternElement::Wildcard => serializer.serialize_str("*"),
179 PatternElement::Skip => serializer.serialize_str("?"),
180 PatternElement::Exclude => serializer.serialize_str("!"),
181 }
182 }
183}
184
185impl<'de> Deserialize<'de> for PatternElement {
187 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
188 where
189 D: serde::Deserializer<'de>,
190 {
191 let value = serde_json::Value::deserialize(deserializer)?;
192 match value {
193 serde_json::Value::Number(n) => {
194 if let Some(i) = n.as_i64() {
195 Ok(PatternElement::Value(i as i32))
196 } else {
197 Err(serde::de::Error::custom(
198 "Pattern element must be an integer",
199 ))
200 }
201 }
202 serde_json::Value::String(s) => match s.as_str() {
203 "*" => Ok(PatternElement::Wildcard),
204 "?" => Ok(PatternElement::Skip),
205 "!" => Ok(PatternElement::Exclude),
206 _ => Err(serde::de::Error::custom(format!(
207 "Unknown pattern element: {}",
208 s
209 ))),
210 },
211 _ => Err(serde::de::Error::custom(
212 "Pattern element must be number or string",
213 )),
214 }
215 }
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct PhysiologyConfig {
221 pub simulation_timestep: f64,
223
224 pub max_age: u64,
226
227 pub evolution_burst_count: u64,
229
230 pub ipu_idle_threshold: u64,
232
233 pub plasticity_queue_depth: usize,
235
236 pub lifespan_mgmt_interval: u64,
238
239 #[serde(default = "default_quantization_precision")]
242 pub quantization_precision: String,
243}
244
245pub fn default_quantization_precision() -> String {
246 "int8".to_string() }
248
249impl Default for PhysiologyConfig {
250 fn default() -> Self {
251 Self {
252 simulation_timestep: 0.025,
253 max_age: 10_000_000,
254 evolution_burst_count: 50,
255 ipu_idle_threshold: 1000,
256 plasticity_queue_depth: 3,
257 lifespan_mgmt_interval: 10,
258 quantization_precision: default_quantization_precision(),
259 }
260 }
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct GenomeSignatures {
266 pub genome: String,
268
269 pub blueprint: String,
271
272 pub physiology: String,
274
275 #[serde(skip_serializing_if = "Option::is_none")]
277 pub morphologies: Option<String>,
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize, Default)]
282pub struct GenomeStats {
283 pub innate_cortical_area_count: usize,
285
286 pub innate_neuron_count: usize,
288
289 pub innate_synapse_count: usize,
291}
292
293#[cfg(test)]
294mod tests {
295 use super::*;
296
297 #[test]
298 fn test_morphology_registry_creation() {
299 let registry = MorphologyRegistry::new();
300 assert_eq!(registry.count(), 0);
301 }
302
303 #[test]
304 fn test_morphology_registry_add_and_get() {
305 let mut registry = MorphologyRegistry::new();
306
307 let morphology = Morphology {
308 morphology_type: MorphologyType::Vectors,
309 parameters: MorphologyParameters::Vectors {
310 vectors: vec![[1, 0, 0], [0, 1, 0]],
311 },
312 class: "test".to_string(),
313 };
314
315 registry.add_morphology("test_morph".to_string(), morphology);
316
317 assert_eq!(registry.count(), 1);
318 assert!(registry.contains("test_morph"));
319 assert!(registry.get("test_morph").is_some());
320 }
321
322 #[test]
323 fn test_physiology_config_default() {
324 let config = PhysiologyConfig::default();
325 assert_eq!(config.simulation_timestep, 0.025);
326 assert_eq!(config.max_age, 10_000_000);
327 }
328}