// 🌌 [BioPhys 6.0] Karl Friston 자유 μ—λ„ˆμ§€ 원리 및 예츑 λΆ€ν˜Έν™” μ—”μ§„ (src/free_energy_engine.rs) // μ—­μ „νŒŒ(Backpropagation) 없이 λ³€λΆ„ 자유 μ—λ„ˆμ§€(Variational Free Energy)λ₯Ό κ΅­μ†Œμ μœΌλ‘œ μ΅œμ†Œν™”ν•˜μ—¬ 였차 μŠ€νŒŒμ΄ν¬λ§Œμ„ μ „νŒŒν•˜λŠ” 신경망 μ—”μ§„ use std::time::Instant; /// πŸ”¬ 자유 μ—λ„ˆμ§€ μ—”μ§„ μ„€μ • νŒŒλΌλ―Έν„° (Config) #[derive(Clone, Debug)] pub struct FreeEnergyConfig { pub num_layers: usize, pub hidden_dim: usize, pub prediction_precision: f32, // 감각 정밀도 (Precision Weight, κΈ°λ³Έ: 1.25) pub learning_rate: f32, // κ΅­μ†Œ 적응λ₯  (κΈ°λ³Έ: 0.05) pub complexity_penalty: f32, // λ³΅μž‘λ„ νŽ˜λ„ν‹° (KL Divergence κ³„μˆ˜, κΈ°λ³Έ: 0.01) } impl Default for FreeEnergyConfig { fn default() -> Self { Self { num_layers: 4, hidden_dim: 256, prediction_precision: 1.25, learning_rate: 0.05, complexity_penalty: 0.01, } } } /// 🧠 예츑 λΆ€ν˜Έν™” 계측 (Predictive Coding Layer) #[derive(Clone, Debug)] pub struct PredictiveCodingLayer { pub layer_id: usize, pub representation_mu: Vec, // λ‚΄λΆ€ μƒνƒœ ν‘œμƒ (Internal States) pub prediction_error: Vec, // 예츑 였차 슀파이크 (Epsilon = Input - Mu) pub generative_weights: Vec, // ν•˜ν–₯식 예츑 생성 κ°€μ€‘μΉ˜ } impl PredictiveCodingLayer { pub fn new(layer_id: usize, dim: usize) -> Self { Self { layer_id, representation_mu: vec![0.0f32; dim], prediction_error: vec![0.0f32; dim], generative_weights: (0..dim).map(|i| (i as f32 * 0.1).cos() * 0.5).collect(), } } } /// πŸ›οΈ 자유 μ—λ„ˆμ§€ λŠ₯동적 μΆ”λ‘  μ—”μ§„ (Main Engine Struct) pub struct FreeEnergyEngine { pub config: FreeEnergyConfig, pub layers: Vec, pub current_free_energy: f32, pub total_surprises_resolved: usize, } impl FreeEnergyEngine { pub fn new(config: FreeEnergyConfig) -> Self { let layers = (0..config.num_layers) .map(|i| PredictiveCodingLayer::new(i, config.hidden_dim)) .collect(); Self { config, layers, current_free_energy: 0.0, total_surprises_resolved: 0, } } /// [자유 μ—λ„ˆμ§€ μ΅œμ†Œν™” μΆ”λ‘ ]: μž…λ ₯ μ‹ ν˜Έμ— λŒ€ν•΄ 상ν–₯식 μ˜€μ°¨μ™€ ν•˜ν–₯식 μ˜ˆμΈ‘μ„ 반볡 μ •λ ¬ pub fn infer_and_minimize(&mut self, sensory_input: &[f32]) -> (f32, u128) { let t_start = Instant::now(); let dim = self.config.hidden_dim.min(sensory_input.len()); let mut total_accuracy_error = 0.0f32; let mut total_complexity_cost = 0.0f32; // 1. μ΅œν•˜μœ„ 감각 계측 (Layer 0) 였차 계산 for i in 0..dim { let pred = self.layers[0].representation_mu[i] * self.layers[0].generative_weights[i]; let error = sensory_input[i] - pred; self.layers[0].prediction_error[i] = error; total_accuracy_error += self.config.prediction_precision * error * error; // κ΅­μ†Œμ  μƒνƒœ κ°±μ‹ : dMu = eta * (Precision * Error - Complexity) let d_mu = self.config.learning_rate * (self.config.prediction_precision * error - self.config.complexity_penalty * self.layers[0].representation_mu[i]); self.layers[0].representation_mu[i] += d_mu; total_complexity_cost += self.config.complexity_penalty * self.layers[0].representation_mu[i].powi(2); } // 2. 계측적 μƒμœ„ 계측 μ „νŒŒ (Hierarchical Predictive Propagation) for l in 1..self.config.num_layers { let prev_mu = self.layers[l - 1].representation_mu.clone(); for i in 0..dim { let top_pred = self.layers[l].representation_mu[i] * self.layers[l].generative_weights[i]; let error = prev_mu[i] - top_pred; self.layers[l].prediction_error[i] = error; total_accuracy_error += self.config.prediction_precision * error * error; let d_mu = self.config.learning_rate * (self.config.prediction_precision * error - self.config.complexity_penalty * self.layers[l].representation_mu[i]); self.layers[l].representation_mu[i] += d_mu; total_complexity_cost += self.config.complexity_penalty * self.layers[l].representation_mu[i].powi(2); } } // 3. λ³€λΆ„ 자유 μ—λ„ˆμ§€ F = Accuracy Error + Complexity Cost self.current_free_energy = total_accuracy_error + total_complexity_cost; self.total_surprises_resolved += 1; let latency_us = t_start.elapsed().as_micros(); (self.current_free_energy, latency_us) } /// [μ΅œμƒμœ„ 예츑 ν‘œμƒ 벑터 λ°˜ν™˜] pub fn get_top_representation(&self) -> &[f32] { &self.layers[self.config.num_layers - 1].representation_mu } /// [자유 μ—λ„ˆμ§€ μƒνƒœ μš”μ•½] pub fn telemetry_summary(&self) -> String { format!( "🧠 [자유 μ—λ„ˆμ§€ FEP]: 계측 {}개 | ν˜„μž¬ 자유 μ—λ„ˆμ§€ F = {:.4} | ν•΄κ²°λœ λ†€λžŒ(Surprise) 회수: {}회", self.config.num_layers, self.current_free_energy, self.total_surprises_resolved ) } }