@@ 1,11 1,45 @@
use std::marker::PhantomData;
-use nalgebra::{allocator::Allocator, DefaultAllocator, Dim, Const, OMatrix, OVector};
+use nalgebra::{allocator::Allocator, Const, DefaultAllocator, Dim, OMatrix, OVector, U1};
use rand::{prelude::IteratorRandom, Rng, RngCore};
use eoa_lib::replacement::Population;
use itertools::Itertools;
use eoa_lib::crossover::Crossover;
use crate::tsp::NodePermutation;
+pub struct NoCrossover<D> {
+ _phantom: PhantomData<D>
+}
+
+impl<D> NoCrossover<D> {
+ pub fn new() -> Self {
+ Self { _phantom: PhantomData }
+ }
+}
+
+impl<D> Crossover<2> for NoCrossover<D>
+where
+ D: Dim,
+ DefaultAllocator: Allocator<D>,
+{
+ type Chromosome = NodePermutation<D>;
+ type Out = f64;
+
+ fn crossover(
+ &self,
+ parents: &eoa_lib::replacement::EvaluatedPopulation<Self::Chromosome, Self::Out>,
+ pairs: impl Iterator<Item = eoa_lib::pairing::ParentPairing<2>>,
+ _: &mut dyn RngCore
+ ) -> Population<Self::Chromosome> {
+ let mut offsprings = vec![];
+ for pair in pairs {
+ offsprings.push(parents.population[pair[0]].chromosome.clone());
+ offsprings.push(parents.population[pair[1]].chromosome.clone());
+ }
+
+ Population::from_vec(offsprings)
+ }
+}
+
pub struct EdgeRecombinationCrossover<D> {
_phantom: PhantomData<D>
}
@@ 138,3 172,167 @@ where
Population::from_vec(offsprings)
}
}
+
+pub struct CycleCrossover<D: Dim> {
+ _phantom: PhantomData<D>
+}
+
+impl<D: Dim> CycleCrossover<D>
+where
+ D: Dim,
+ DefaultAllocator: Allocator<D>,
+{
+ pub fn new() -> Self {
+ Self { _phantom: PhantomData }
+ }
+
+ fn perform_crossover(
+ &self,
+ parent1: &OVector<usize, D>,
+ parent2: &OVector<usize, D>,
+ city_positions: &mut [usize]
+ ) -> NodePermutation<D> {
+ let mut offspring = parent2.clone();
+
+ for (i, &city) in parent1.iter().enumerate() {
+ city_positions[city] = i;
+ }
+
+ let mut i = 0;
+ let mut first = true;
+ while i != 0 || first {
+ first = false;
+
+ let city = parent1[i];
+
+ offspring[i] = city;
+
+ let city = parent2[i];
+ i = city_positions[city];
+ }
+
+ NodePermutation { permutation: offspring }
+ }
+}
+
+impl<D: Dim> Crossover<2> for CycleCrossover<D>
+where
+ D: Dim,
+ DefaultAllocator: Allocator<D>,
+{
+ type Chromosome = NodePermutation<D>;
+ type Out = f64;
+
+ fn crossover(
+ &self,
+ parents: &eoa_lib::replacement::EvaluatedPopulation<Self::Chromosome, Self::Out>,
+ pairs: impl Iterator<Item = eoa_lib::pairing::ParentPairing<2>>,
+ rng: &mut dyn RngCore
+ ) -> Population<Self::Chromosome> {
+ let mut offsprings = vec![];
+
+ let permutation = &parents.population[0].chromosome.permutation;
+ let mut city_positions =
+ OVector::zeros_generic(permutation.shape_generic().0, U1);
+
+ for pair in pairs {
+ let parent1 = &parents.population[pair.x].chromosome;
+ let parent2 = &parents.population[pair.y].chromosome;
+
+ let (perm1, perm2) = (
+ &parent1.permutation,
+ &parent2.permutation
+ );
+
+ offsprings.push(self.perform_crossover(perm1, perm2, city_positions.as_mut_slice()));
+ offsprings.push(self.perform_crossover(perm2, perm1, city_positions.as_mut_slice()));
+ }
+
+ Population::from_vec(offsprings)
+ }
+}
+
+pub struct PartiallyMappedCrossover<D: Dim> {
+ _phantom: PhantomData<D>
+}
+
+impl<D: Dim> PartiallyMappedCrossover<D>
+where
+ D: Dim,
+ DefaultAllocator: Allocator<D>,
+{
+ pub fn new() -> Self {
+ Self { _phantom: PhantomData }
+ }
+
+ fn find_cross_points(&self, chromosome: &NodePermutation<D>, rng: &mut dyn RngCore) -> [usize; 2] {
+ let (min, max) = (0, chromosome.permutation.len());
+ let first = rng.random_range(min..max);
+ let second = rng.random_range(min..max);
+
+ [ first.min(second), first.max(second) ]
+ }
+
+ fn perform_crossover(
+ &self,
+ parent1: &OVector<usize, D>,
+ parent2: &OVector<usize, D>,
+ crossover_points: &[usize; 2],
+ city_positions: &mut [usize]
+ ) -> NodePermutation<D> {
+ let mut offspring = parent1.clone();
+
+ for (i, &city) in parent1.iter().enumerate() {
+ city_positions[city] = i;
+ }
+
+ for i in crossover_points[0]..crossover_points[1] {
+ let city = parent2[i];
+
+ offspring.swap_rows(
+ i,
+ city_positions[city]
+ );
+ }
+
+ NodePermutation { permutation: offspring }
+ }
+}
+
+impl<D: Dim> Crossover<2> for PartiallyMappedCrossover<D>
+where
+ D: Dim,
+ DefaultAllocator: Allocator<D>,
+{
+ type Chromosome = NodePermutation<D>;
+ type Out = f64;
+
+ fn crossover(
+ &self,
+ parents: &eoa_lib::replacement::EvaluatedPopulation<Self::Chromosome, Self::Out>,
+ pairs: impl Iterator<Item = eoa_lib::pairing::ParentPairing<2>>,
+ rng: &mut dyn RngCore
+ ) -> Population<Self::Chromosome> {
+ let mut offsprings = vec![];
+
+ let permutation = &parents.population[0].chromosome.permutation;
+ let mut city_positions =
+ OVector::zeros_generic(permutation.shape_generic().0, U1);
+
+ for pair in pairs {
+ let parent1 = &parents.population[pair.x].chromosome;
+ let parent2 = &parents.population[pair.y].chromosome;
+
+ let (perm1, perm2) = (
+ &parent1.permutation,
+ &parent2.permutation
+ );
+
+ let cross_points = self.find_cross_points(parent1, rng);
+ offsprings.push(self.perform_crossover(perm1, perm2, &cross_points, city_positions.as_mut_slice()));
+ offsprings.push(self.perform_crossover(perm2, perm1, &cross_points, city_positions.as_mut_slice()));
+ }
+
+ Population::from_vec(offsprings)
+ }
+}