BioPhys-Neural-Agent / src /free_energy_engine.rs
minseok
🌟 Implement 3 Frontier Theories: Karl Friston FEP Predictive Coding, Astrocyte Tripartite Glia, Ryu-Takayanagi Wormhole Calibration Filter
1bfe9c1
Raw
History Blame Contribute Delete
5.32 kB
// 🌌 [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<f32>, // λ‚΄λΆ€ μƒνƒœ ν‘œμƒ (Internal States)
pub prediction_error: Vec<f32>, // 예츑 였차 슀파이크 (Epsilon = Input - Mu)
pub generative_weights: Vec<f32>, // ν•˜ν–₯식 예츑 생성 κ°€μ€‘μΉ˜
}
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<PredictiveCodingLayer>,
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
)
}
}