dirtydata_core/
mutation.rs1use rand::prelude::*;
5use rand::rngs::StdRng;
6use rand::SeedableRng;
7use crate::types::*;
8
9pub struct MutationEngine {
12 rng: StdRng,
13}
14
15impl MutationEngine {
16 pub fn new(seed: u64) -> Self {
17 Self { rng: StdRng::seed_from_u64(seed) }
18 }
19
20 pub fn mutate(&mut self, base: &CircuitDefinition, intensity: MutationIntensity) -> (CircuitDefinition, MutationRecord) {
23 let mut new_def = base.clone();
24 let mut changes = Vec::new();
25
26 if intensity >= MutationIntensity::Safe {
28 let drift_amount = match intensity {
29 MutationIntensity::Safe => 0.05,
30 _ => 0.25,
31 };
32
33 changes.push(MutationType::ParamDrift {
34 index: 0,
35 key: "resistance".into(),
36 amount: self.rng.gen_range(-drift_amount..drift_amount),
37 });
38 }
39
40 if intensity >= MutationIntensity::Wild {
42 changes.push(MutationType::ComponentSwap {
43 index: 2,
44 old_type: "SiliconDiode".into(),
45 new_type: "GermaniumDiode".into(),
46 });
47 }
48
49 if intensity >= MutationIntensity::Radioactive {
51 changes.push(MutationType::TopologyChange {
52 description: "Induced Feedback Loop (parasitic oscillation)".into(),
53 added_nodes: vec![1, 6],
54 removed_nodes: vec![],
55 });
56 }
57
58 let report = self.evaluate(&new_def, intensity);
59
60 let record = MutationRecord {
61 timestamp: Timestamp::now(),
62 intensity,
63 changes,
64 report,
65 };
66
67 new_def.mutation_history.push(record.clone());
68 (new_def, record)
69 }
70}