File size: 6,143 Bytes
be99550 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | // π [BioPhys 6.0 μ΄μμλ μ κΈ°μ μνκ³ μ§ν μμ§] (src/ecosystem_evolution.rs)
// 1. μλμ λΉνΈ ν립 λμ°λ³μ΄ (Mutation Injector)
// 2. μλΈλ£¨ν΄ 무μμ λμ λ―Ήμ (Subconscious Bleed Mixer)
// 3. μ΄μ± μ μ μ 1-Bit ν¬μ μμΆ λ° λΉμ λ°μκΈ° (Spore Archiver & Germinator)
use std::collections::HashMap;
use std::time::Instant;
/// 𧬠[1. μλμ λΉνΈ ν립 λμ°λ³μ΄ μΈμ ν°]
pub struct MutationInjector {
pub mutation_rate: f32, // λμ°λ³μ΄ λ°μ νλ₯ (κΈ°λ³Έ 0.001 = 0.1%)
pub total_mutations_applied: usize,
pub beneficial_mutations: usize,
}
impl MutationInjector {
pub fn new(mutation_rate: f32) -> Self {
MutationInjector {
mutation_rate,
total_mutations_applied: 0,
beneficial_mutations: 0,
}
}
/// 2-Bit ν¨νΉλ κ°μ€μΉ λ°°μ΄μ μ€μ μ°μ£Ό λ°©μ¬μ (λΉνΈ ν립)μ κ°νκ³ μ ν©λ(Fitness) νκ°
pub fn inject_cosmic_mutation(
&mut self,
packed_weights: &mut [u32],
baseline_energy: f32,
eval_fn: impl Fn(&[u32]) -> f32,
) -> bool {
let len = packed_weights.len();
if len == 0 { return false; }
let mut mutated_indices = Vec::new();
let mut old_values = Vec::new();
// 1. νλ₯ μ λΉνΈ ν립 μν
for i in 0..len {
let pseudo_rand = ((i as u32 * 1103515245 + 12345) & 0x7FFFFFFF) as f32 / 2147483648.0;
if pseudo_rand < self.mutation_rate {
let bit_shift = (i % 16) * 2;
let flip_mask = 0b11 << bit_shift;
old_values.push((i, packed_weights[i]));
packed_weights[i] ^= flip_mask; // 2-Bit μμ μ μ΄
mutated_indices.push(i);
self.total_mutations_applied += 1;
}
}
if mutated_indices.is_empty() { return false; }
// 2. μ ν©λ(Fitness) νκ°: μλ‘μ΄ κ³λ©΄ μλμ§κ° μΉ΄μ€μ€ μ΅μ μ (0.50~0.55)μ λ κ°κΉμμ‘λμ§ κ²μ¦
let new_energy = eval_fn(packed_weights);
let old_diff = (baseline_energy - 0.52).abs();
let new_diff = (new_energy - 0.52).abs();
if new_diff <= old_diff {
// μ μ΅ν λμ°λ³μ΄: μꡬ 보쑴(보쑴)
self.beneficial_mutations += 1;
true
} else {
// ν΄λ‘μ΄ λμ°λ³μ΄: μμ° λν (μ볡 Rollback)
for (idx, old_val) in old_values {
packed_weights[idx] = old_val;
}
false
}
}
}
/// π [2. μλΈλ£¨ν΄ 무μμ λμ λ―Ήμ (Subconscious Bleed Mixer)]
pub struct SubconsciousMixer {
pub residual_wave: Vec<f32>, // μ΄μ μΈμ
μ 무μμμ μμ¬ μ§λ νν
pub bleed_ratio: f32, // λμ λΉμ¨ (κΈ°λ³Έ 0.03 = 3%)
pub session_count: usize,
}
impl SubconsciousMixer {
pub fn new(dim: usize, bleed_ratio: f32) -> Self {
SubconsciousMixer {
residual_wave: vec![0.0; dim],
bleed_ratio,
session_count: 0,
}
}
/// μ΄μ μΈμ
μ μκ°(μ μ¬ μν)μ νμ¬ μ°μ°μ 3% λ―ΈμΈ κ²°ν©νμ¬ μ°½μμ μκ° μ λ
pub fn blend_subconscious(&mut self, current_hidden: &mut [f32]) {
self.session_count += 1;
let len = current_hidden.len().min(self.residual_wave.len());
for i in 0..len {
// 무μμ λμ: νμ¬ μκ° + (μ΄μ μμ¬ κΈ°μ΅ * 3%)
let inspiration = self.residual_wave[i] * self.bleed_ratio;
current_hidden[i] += inspiration;
// νμ¬ μκ°μ 20%λ₯Ό λ€μ μΈμ
μ 무μμ μμ¬ ννμΌλ‘ μ μ₯ (κ°μ μ μ₯)
self.residual_wave[i] = (self.residual_wave[i] * 0.7) + (current_hidden[i] * 0.2);
}
}
}
/// π [3. μ΄μ± μ μ μ 1-Bit ν¬μ μμΆ λ° λΉμ λ°μκΈ°]
pub struct SporeArchiver {
pub spores: HashMap<String, Vec<u8>>, // 1-Bit κ·Ήλ¨ μμΆλ μ¨μ μ μ₯μ
pub total_archived: usize,
pub total_germinated: usize,
}
impl SporeArchiver {
pub fn new() -> Self {
SporeArchiver {
spores: HashMap::new(),
total_archived: 0,
total_germinated: 0,
}
}
/// λΉνμ±/μ΄μ± κ°μ€μΉ ν
μλ₯Ό 1-Bit ν¬μ(Spore) ννλ‘ μμΆ μ μ₯ (8λ°° μΆκ° μμΆ)
pub fn archive_to_spore(&mut self, gene_name: &str, packed_2bit: &[u32]) {
let mut spore_bytes = Vec::with_capacity(packed_2bit.len() / 2);
for chunk in packed_2bit.chunks(8) {
let mut byte: u8 = 0;
for (bit_idx, &word) in chunk.iter().enumerate() {
// μμ ν₯λΆμ± μμ(0b11, 0b01)λ§ 1λ‘ μΆμΆνμ¬ 1-Bitλ‘ κ·Ήλ¨ μμΆ
let is_active = (word & 0x55555555).count_ones() > 8;
if is_active {
byte |= 1 << bit_idx;
}
}
spore_bytes.push(byte);
}
self.spores.insert(gene_name.to_string(), spore_bytes);
self.total_archived += 1;
}
/// λͺ¨λ λΆκ΄΄(Mode Collapse) λλ λ―Έμ§μ ν둬ννΈ λ°μ μ 1-Bit ν¬μλ₯Ό 2-Bit κ°μ€μΉλ‘ μ¦κ° λ°μ(Re-activate)
pub fn germinate_spore(&mut self, gene_name: &str, output_len: usize) -> Option<Vec<u32>> {
if let Some(spore_bytes) = self.spores.get(gene_name) {
self.total_germinated += 1;
let mut recovered_2bit = Vec::with_capacity(output_len);
for &b in spore_bytes {
for bit_idx in 0..8 {
if recovered_2bit.len() >= output_len { break; }
let bit = (b >> bit_idx) & 1;
let reconstructed_word = if bit == 1 { 0x55555555 } else { 0x00000000 };
recovered_2bit.push(reconstructed_word);
}
}
while recovered_2bit.len() < output_len {
recovered_2bit.push(0x00000000);
}
Some(recovered_2bit)
} else {
None
}
}
}
|