use crate::error::GaError;
use crate::traits::ChromosomeT;
use log::{debug, trace};
use rand::Rng;
use std::borrow::Cow;
pub fn uniform<U: ChromosomeT>(parent_1: &U, parent_2: &U) -> Result<Vec<U>, GaError> {
if parent_1.dna().len() != parent_2.dna().len() {
return Err(GaError::CrossoverError(format!(
"parent 1 and parent 2 must have the same dna length. Currently parent 1 has a length of {} and parent 2 {}",
parent_1.dna().len(), parent_2.dna().len())));
}
let mut rng = crate::rng::make_rng();
let len = parent_1.dna().len();
let mut dna_child_1 = Vec::with_capacity(len);
let mut dna_child_2 = Vec::with_capacity(len);
debug!(target="crossover_events", method="uniform"; "Starting the uniform crossover");
let mut child_1 = parent_1.clone();
let mut child_2 = parent_2.clone();
for i in 0..len {
let crossover = rng.random_range(0..2);
trace!(target="crossover_events", method="uniform"; "Random crossover number {}", crossover);
if crossover == 0 {
dna_child_1.push(parent_1.dna().get(i).cloned().unwrap());
dna_child_2.push(parent_2.dna().get(i).cloned().unwrap());
} else {
dna_child_1.push(parent_2.dna().get(i).cloned().unwrap());
dna_child_2.push(parent_1.dna().get(i).cloned().unwrap());
}
}
child_1.set_dna(Cow::Owned(dna_child_1));
child_2.set_dna(Cow::Owned(dna_child_2));
debug!(target="crossover_events", method="uniform"; "Uniform crossover finished");
Ok(vec![child_1, child_2])
}