use crate::chromosomes::ChromosomeLength;
use crate::error::GaError;
use crate::traits::LinearChromosome;
use rand::Rng;
use std::borrow::Cow;
pub fn length_insertion_mutation<U: LinearChromosome>(
individual: &mut U,
chromosome_length: ChromosomeLength,
) -> Result<(), GaError> {
let (min, max) = match chromosome_length {
ChromosomeLength::Fixed(_) => {
return Err(GaError::MutationError(
"Mutation::Insertion requires ChromosomeLength::Variable. \
ChromosomeLength::Fixed does not allow changing chromosome length."
.to_string(),
));
}
ChromosomeLength::Variable { min, max } => (min, max),
};
let current_len = individual.dna().len();
if current_len == 0 {
crate::log_debug!(target = "mutation_events", method = "length_insertion"; "Empty DNA, skipping insertion");
return Ok(());
}
if current_len >= max {
crate::log_debug!(target = "mutation_events", method = "length_insertion";
"DNA length {} already at max {}, skipping insertion", current_len, max);
return Ok(());
}
let _ = min;
let mut rng = crate::rng::make_rng();
let source_idx = rng.random_range(0..current_len);
let new_gene = individual.dna()[source_idx].clone();
let insert_pos = rng.random_range(0..=current_len);
let mut dna = individual.dna().to_vec();
dna.insert(insert_pos, new_gene);
individual.set_dna(Cow::Owned(dna));
crate::log_debug!(target = "mutation_events", method = "length_insertion";
"Inserted gene at position {} (new length: {})", insert_pos, current_len + 1);
Ok(())
}
pub fn length_deletion_mutation<U: LinearChromosome>(
individual: &mut U,
chromosome_length: ChromosomeLength,
) -> Result<(), GaError> {
let (min, max) = match chromosome_length {
ChromosomeLength::Fixed(_) => {
return Err(GaError::MutationError(
"Mutation::Deletion requires ChromosomeLength::Variable. \
ChromosomeLength::Fixed does not allow changing chromosome length."
.to_string(),
));
}
ChromosomeLength::Variable { min, max } => (min, max),
};
let current_len = individual.dna().len();
if current_len == 0 {
crate::log_debug!(target = "mutation_events", method = "length_deletion"; "Empty DNA, skipping deletion");
return Ok(());
}
if current_len <= min {
crate::log_debug!(target = "mutation_events", method = "length_deletion";
"DNA length {} already at min {}, skipping deletion", current_len, min);
return Ok(());
}
let _ = max;
let mut rng = crate::rng::make_rng();
let delete_pos = rng.random_range(0..current_len);
let mut dna = individual.dna().to_vec();
dna.remove(delete_pos);
individual.set_dna(Cow::Owned(dna));
crate::log_debug!(target = "mutation_events", method = "length_deletion";
"Deleted gene at position {} (new length: {})", delete_pos, current_len - 1);
Ok(())
}