use crate::chromosomes::Range as RangeChromosome;
use crate::operations::mutation::gaussian::GaussianConvertible;
use crate::traits::LinearChromosome;
use rand::Rng;
use std::fmt::Debug;
pub fn cauchy_mutation<T>(individual: &mut RangeChromosome<T>, scale: f64)
where
T: Sync + Send + Clone + Default + Debug + PartialOrd + Copy + 'static + GaussianConvertible,
{
let len = individual.dna().len();
if len == 0 {
return;
}
let mut rng = crate::rng::make_rng();
let idx = rng.random_range(0..len);
let mut gene = individual.dna()[idx].clone();
if gene.ranges.is_empty() {
return;
}
let range_idx = rng.random_range(0..gene.ranges.len());
let (lo, hi) = gene.ranges[range_idx];
let current: f64 = T::to_f64(gene.value);
let lo_f64: f64 = T::to_f64(lo);
let hi_f64: f64 = T::to_f64(hi);
let u: f64 = rng.random_range(f64::EPSILON..1.0 - f64::EPSILON);
let noise: f64 = scale * (std::f64::consts::PI * (u - 0.5)).tan();
let new_val_f64 = (current + noise).clamp(lo_f64, hi_f64);
gene.value = T::from_f64(new_val_f64);
individual.set_gene(idx, gene);
crate::log_debug!(
target: "mutation_events",
"Cauchy mutation applied at idx={} range_idx={} scale={}",
idx, range_idx, scale
);
}