// ๐ŸŒŒ [BioPhys 6.0] ์„ฑ์ƒ๊ต์„ธํฌ(Astrocyte) 3์ค‘ ์‹œ๋ƒ…์Šค ์žฅ๊ธฐ ๊ธฐ์–ต ์กฐ์ ˆ๊ธฐ (src/astrocyte_glia_controller.rs) // ๋ฐ€๋ฆฌ์ดˆ(ms) ๋‰ด๋Ÿฐ ์ŠคํŒŒ์ดํฌ ์œ„์— ์ดˆ(sec) ๋‹จ์œ„ ์นผ์Š˜ ํŒŒ๋™(Caยฒโบ Waves)์„ ์˜ค๋ฒ„๋ ˆ์ดํ•˜์—ฌ ์žฅ๊ธฐ ๊ฐ•ํ™”(LTP) ๋ฐ ๋ง๊ฐ(LTD)์„ ๋ฉ”ํƒ€ ์กฐ์ ˆํ•˜๋Š” ๊ธ€๋ฆฌ์•„ ์‹ ๊ฒฝ๋ง ์—”์ง„ use std::time::Instant; /// ๐Ÿ”ฌ ์„ฑ์ƒ๊ต์„ธํฌ ์„ค์ • ํŒŒ๋ผ๋ฏธํ„ฐ (Config) #[derive(Clone, Debug)] pub struct AstrocyteConfig { pub num_astrocytes: usize, pub calcium_decay_rate: f32, // ์นผ์Š˜ ๋†๋„ ์ž์—ฐ ๊ฐ์‡ ์œจ (๊ธฐ๋ณธ: 0.08) pub gliotransmitter_potency: f32, // ๊ธ€๋ฆฌ์˜คํŠธ๋žœ์Šค๋ฏธํ„ฐ ๋ฐฉ์ถœ ๊ฐ•๋„ (๊ธฐ๋ณธ: 1.45) pub ltp_consolidation_threshold: f32, // ์žฅ๊ธฐ ๊ธฐ์–ต ๊ณ ์ • ์ž„๊ณ„์น˜ (๊ธฐ๋ณธ: 0.65) } impl Default for AstrocyteConfig { fn default() -> Self { Self { num_astrocytes: 64, calcium_decay_rate: 0.08, gliotransmitter_potency: 1.45, ltp_consolidation_threshold: 0.65, } } } /// ๐ŸŒŸ ๊ฐœ๋ณ„ ์„ฑ์ƒ๊ต์„ธํฌ ๋„๋ฉ”์ธ ๋…ธ๋“œ (Astrocyte Micro-Domain) #[derive(Clone, Debug)] pub struct AstrocyteDomain { pub domain_id: usize, pub intracellular_calcium: f32, // ์„ธํฌ๋‚ด ์นผ์Š˜ ์ด์˜จ ๋†๋„ [Caยฒโบ] pub gliotransmitter_level: f32, // ๊ธ€๋ฆฌ์˜คํŠธ๋žœ์Šค๋ฏธํ„ฐ(D-Serine/ATP) ๋ถ„๋น„๋Ÿ‰ pub consolidated_memory_strength: f32, // ์˜๊ตฌ ๋ณด์กด ๊ธฐ์–ต ๊ฐ•๋„ } impl AstrocyteDomain { pub fn new(domain_id: usize) -> Self { Self { domain_id, intracellular_calcium: 0.1, gliotransmitter_level: 0.0, consolidated_memory_strength: 1.0, } } } /// ๐Ÿ›๏ธ ์„ฑ์ƒ๊ต์„ธํฌ ๊ธ€๋ฆฌ์•„ ๋ฉ”ํƒ€ ์ปจํŠธ๋กค๋Ÿฌ (Main Engine Struct) pub struct AstrocyteGliaController { pub config: AstrocyteConfig, pub astrocytes: Vec, pub global_calcium_wave_energy: f32, pub total_memories_consolidated: usize, } impl AstrocyteGliaController { pub fn new(config: AstrocyteConfig) -> Self { let astrocytes = (0..config.num_astrocytes) .map(|i| AstrocyteDomain::new(i)) .collect(); Self { config, astrocytes, global_calcium_wave_energy: 0.0, total_memories_consolidated: 0, } } /// [3์ค‘ ์‹œ๋ƒ…์Šค ์ƒํ˜ธ์ž‘์šฉ ๋ฐ ์นผ์Š˜ ํŒŒ๋™ ์ „ํŒŒ]: ๋‰ด๋Ÿฐ ์ŠคํŒŒ์ดํฌ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๋ฉ”ํƒ€ ๊ฐ€์†Œ์„ฑ ์กฐ์ ˆ pub fn modulate_synaptic_field(&mut self, spike_activities: &[f32]) -> (f32, u128) { let t_start = Instant::now(); let num_astro = self.astrocytes.len(); let mut total_calcium = 0.0f32; for (i, ast) in self.astrocytes.iter_mut().enumerate() { // 1. ์‹œ๋ƒ…์Šค ํ™œ๋™ ๊ฐ์ง€ ๋ฐ ์นผ์Š˜ ์œ ์ž… (IP3-mediated Caยฒโบ release) let sensory_idx = i % spike_activities.len().max(1); let raw_activity = if !spike_activities.is_empty() { spike_activities[sensory_idx].abs() } else { 0.0 }; ast.intracellular_calcium += raw_activity * 0.25; ast.intracellular_calcium *= 1.0 - self.config.calcium_decay_rate; // ์ž์—ฐ ๊ฐ์‡  // 2. ๊ธ€๋ฆฌ์˜คํŠธ๋žœ์Šค๋ฏธํ„ฐ ๋ฐฉ์ถœ if ast.intracellular_calcium > 0.3 { ast.gliotransmitter_level = (ast.intracellular_calcium * self.config.gliotransmitter_potency).min(2.0); } else { ast.gliotransmitter_level *= 0.9; } // 3. ์žฅ๊ธฐ ๊ธฐ์–ต ๊ณ ์ • (LTP Consolidation) if ast.gliotransmitter_level > self.config.ltp_consolidation_threshold { ast.consolidated_memory_strength += 0.05; self.total_memories_consolidated += 1; } else if ast.intracellular_calcium < 0.05 { // ๋…ธ์ด์ฆˆ์„ฑ ๋‹จ๊ธฐ ๊ธฐ์–ต ์ž์—ฐ ๋ง๊ฐ (LTD) ast.consolidated_memory_strength = (ast.consolidated_memory_strength * 0.98).max(0.5); } total_calcium += ast.intracellular_calcium; } self.global_calcium_wave_energy = total_calcium / num_astro as f32; let latency_us = t_start.elapsed().as_micros(); (self.global_calcium_wave_energy, latency_us) } /// [๊ธ€๋ฆฌ์•„ ๋ฉ”ํƒ€-๊ฐ€์†Œ์„ฑ ๊ฐ€์ค‘์น˜ ์Šค์ผ€์ผ ๋ฐ˜ํ™˜] pub fn get_synaptic_gain(&self, domain_idx: usize) -> f32 { let idx = domain_idx % self.astrocytes.len(); self.astrocytes[idx].consolidated_memory_strength } /// [์„ฑ์ƒ๊ต์„ธํฌ ์ƒํƒœ ์š”์•ฝ] pub fn telemetry_summary(&self) -> String { format!( "๐Ÿงฌ [์„ฑ์ƒ๊ต์„ธํฌ ๊ธ€๋ฆฌ์•„]: ๋„๋ฉ”์ธ {}๊ฐœ | ๊ธ€๋กœ๋ฒŒ Caยฒโบ ํŒŒ๋™ ์—๋„ˆ์ง€: {:.4} | ๊ณ ์ •๋œ ์žฅ๊ธฐ ๊ธฐ์–ต ์ˆ˜: {}๊ฐœ", self.config.num_astrocytes, self.global_calcium_wave_energy, self.total_memories_consolidated ) } }