use crate::error::GaError;
use crate::operations::crossover::pmx::pmx_build_child;
use crate::traits::LinearChromosome;
use std::borrow::Cow;
pub fn multi_group_pmx<U: LinearChromosome>(parent_1: &U, parent_2: &U) -> Result<Vec<U>, GaError> {
let groups = parent_1.group_ranges();
if groups.is_empty() {
return Err(GaError::ConfigurationError(
"MultiUniqueChromosome must have at least one group for multi-group PMX crossover. \
Check that group alphabets were supplied when constructing the chromosome."
.to_string(),
));
}
let p2_groups = parent_2.group_ranges();
if groups != p2_groups {
return Err(GaError::ConfigurationError(format!(
"MultiGroupPmx: parents have different group structures. \
Parent 1 groups: {:?}, Parent 2 groups: {:?}",
groups, p2_groups
)));
}
let p1_dna = parent_1.dna();
let p2_dna = parent_2.dna();
let mut child_dna_1 = p1_dna.to_vec();
let mut child_dna_2 = p2_dna.to_vec();
for (start, end) in &groups {
let group_len = end - start;
let slice_1 = pmx_build_child(&p1_dna[*start..=*end], &p2_dna[*start..=*end], 0, group_len);
let slice_2 = pmx_build_child(&p2_dna[*start..=*end], &p1_dna[*start..=*end], 0, group_len);
child_dna_1[*start..=*end].clone_from_slice(&slice_1);
child_dna_2[*start..=*end].clone_from_slice(&slice_2);
}
let mut child_1 = U::new();
let mut child_2 = U::new();
child_1.set_dna(Cow::Owned(child_dna_1));
child_2.set_dna(Cow::Owned(child_dna_2));
Ok(vec![child_1, child_2])
}