@@ 1,7 1,8 @@
use std::marker::PhantomData;
use nalgebra::{allocator::Allocator, DefaultAllocator, Dim, OVector, Scalar, U1};
-use rand::{Rng, RngCore};
+use rand::{seq::IteratorRandom, Rng, RngCore};
+use rand_distr::Uniform;
use crate::{binary_string::BinaryString, pairing::ParentPairing, replacement::{EvaluatedPopulation, Population}};
@@ 69,10 70,14 @@ where
) = (&population.population[pair.x], &population.population[pair.y]);
let (
- chromosome1,
- chromosome2
+ mut chromosome1,
+ mut chromosome2
) = (&parent1.chromosome, &parent2.chromosome);
+ if rng.random_bool(0.5) {
+ (chromosome1, chromosome2) = (chromosome2, chromosome1)
+ }
+
let cross_point = self.find_cross_point(&population.population[0].chromosome, rng);
offsprings.push(BinaryString::from_ovector(
@@ 87,6 92,173 @@ where
}
}
+pub struct BinaryTwoPointCrossover<D: Dim, TOutput> {
+ _phantom1: PhantomData<D>,
+ _phantom2: PhantomData<TOutput>
+}
+
+impl<D: Dim, TOutput> BinaryTwoPointCrossover<D, TOutput>
+where
+ DefaultAllocator: Allocator<D>
+{
+ pub fn new() -> Self {
+ Self {
+ _phantom1: PhantomData,
+ _phantom2: PhantomData,
+ }
+ }
+
+ fn find_cross_points(&self, chromosome: &BinaryString<D>, rng: &mut dyn RngCore) -> [usize; 2] {
+ let (min, max) = (0, chromosome.vec.len());
+ let first = rng.random_range(min..max);
+ let second = rng.random_range(min..max);
+
+ [ first.min(second), first.max(second) ]
+ }
+}
+
+impl<D, TOutput> Crossover<2> for BinaryTwoPointCrossover<D, TOutput>
+where
+ D: Dim,
+ DefaultAllocator: Allocator<D>
+{
+ type Chromosome = BinaryString<D>;
+ type Out = TOutput;
+
+ fn crossover(
+ &self,
+ population: &EvaluatedPopulation<Self::Chromosome, Self::Out>,
+ pairs: impl Iterator<Item = ParentPairing<2>>,
+ rng: &mut dyn RngCore
+ ) -> Population<Self::Chromosome> {
+
+ let chromosome = &population.population[0].chromosome.vec;
+ let len = population.population[0].chromosome.vec.len();
+ let indices = OVector::<usize, D>::from_iterator_generic(chromosome.shape_generic().0, U1, 0..len);
+
+ let mut offsprings = Vec::new();
+ for pair in pairs {
+ let (
+ parent1,
+ parent2
+ ) = (&population.population[pair.x], &population.population[pair.y]);
+
+ let (
+ mut chromosome1,
+ mut chromosome2
+ ) = (&parent1.chromosome, &parent2.chromosome);
+
+ if rng.random_bool(0.5) {
+ (chromosome1, chromosome2) = (chromosome2, chromosome1)
+ }
+
+ let cross_point = self.find_cross_points(&population.population[0].chromosome, rng);
+
+ offsprings.push(BinaryString::from_ovector(
+ chromosome1.vec.zip_zip_map(
+ &chromosome2.vec,
+ &indices,
+ |first, second, i| if i <= cross_point[0] {
+ first
+ } else if i < cross_point[1] {
+ second
+ } else {
+ first
+ }
+ )));
+ }
+
+ Population::from_vec(offsprings)
+ }
+}
+
+pub struct BinaryNPointCrossover<const N: usize, D: Dim, TOutput> {
+ _phantom1: PhantomData<D>,
+ _phantom2: PhantomData<TOutput>,
+}
+
+impl<const N: usize, D: Dim, TOutput> BinaryNPointCrossover<N, D, TOutput>
+where
+ DefaultAllocator: Allocator<D>
+{
+ pub fn new() -> Self {
+ Self {
+ _phantom1: PhantomData,
+ _phantom2: PhantomData,
+ }
+ }
+
+ fn find_cross_points(&self, chromosome: &BinaryString<D>, rng: &mut dyn RngCore) -> [usize; N] {
+ let mut res = [0; N];
+ (0..chromosome.vec.len()).choose_multiple_fill(rng, &mut res);
+ res.as_mut_slice().sort_unstable();
+
+ res
+ }
+}
+
+impl<const N: usize, D, TOutput> Crossover<2> for BinaryNPointCrossover<N, D, TOutput>
+where
+ D: Dim,
+ DefaultAllocator: Allocator<D>
+{
+ type Chromosome = BinaryString<D>;
+ type Out = TOutput;
+
+ fn crossover(
+ &self,
+ population: &EvaluatedPopulation<Self::Chromosome, Self::Out>,
+ pairs: impl Iterator<Item = ParentPairing<2>>,
+ rng: &mut dyn RngCore
+ ) -> Population<Self::Chromosome> {
+
+ let chromosome = &population.population[0].chromosome;
+ let len = chromosome.vec.len();
+
+ let mut offsprings = Vec::new();
+ for pair in pairs {
+ let (
+ parent1,
+ parent2
+ ) = (&population.population[pair.x], &population.population[pair.y]);
+
+ let (
+ mut chromosome1,
+ mut chromosome2
+ ) = (&parent1.chromosome.vec, &parent2.chromosome.vec);
+
+ if rng.random_bool(0.5) {
+ (chromosome1, chromosome2) = (chromosome2, chromosome1)
+ }
+
+ let parents = [chromosome1, chromosome2];
+
+ let cross_points = self.find_cross_points(chromosome, rng);
+
+ let mut offspring =
+ OVector::zeros_generic(chromosome1.shape_generic().0, U1);
+
+ let mut start = 0;
+ let mut parent = 0;
+ for cross_point in cross_points {
+ for i in start..cross_point {
+ offspring[i] = parents[parent][i];
+ }
+
+ parent = 1 - parent; // switch parent
+ start = cross_point;
+ }
+
+ for i in start..len {
+ offspring[i] = parents[parent][i];
+ }
+
+ offsprings.push(BinaryString::from_ovector(offspring));
+ }
+
+ Population::from_vec(offsprings)
+ }
+}
pub struct OVectorOnePointCrossover<D: Dim, T: Scalar, TOutput> {
_phantom1: PhantomData<D>,