~ruther/ctu-fee-eoa

03a0e7a6502a93d9b582b2d04f65bff49a1a885b — Rutherther 11 days ago bc75bdd
feat: Add BlendCrossover for reals
1 files changed, 62 insertions(+), 0 deletions(-)

M codes/eoa_lib/src/crossover.rs
M codes/eoa_lib/src/crossover.rs => codes/eoa_lib/src/crossover.rs +62 -0
@@ 393,3 393,65 @@ where
        Population::from_vec(offsprings)
    }
}


pub struct BlendCrossover<D: Dim, TOutput> {
    alpha: f64,
    _phantom1: PhantomData<D>,
    _phantom2: PhantomData<TOutput>,
}

impl<D: Dim, TOutput> BlendCrossover<D, TOutput> {
    pub fn new(alpha: f64) -> Self {
        BlendCrossover {
            alpha,
            _phantom1: PhantomData,
            _phantom2: PhantomData,
        }
    }
}

impl<D, TOutput> Crossover<2> for BlendCrossover<D, TOutput>
where
    D: Dim,
    DefaultAllocator: Allocator<D>
{
    type Chromosome = OVector<f64, 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 mut offsprings = Vec::new();

        for pair in pairs {
            let (
                parent1,
                parent2
            ) = (&population.population[pair.x], &population.population[pair.y]);

            let (
                chromosome1,
                chromosome2
            ) = (&parent1.chromosome, &parent2.chromosome);

            offsprings.push(
                chromosome1.zip_map(
                    &chromosome2,
                    |first, second| {
                        let min = first.min(second);
                        let max = first.max(second);

                        let interval = (min - self.alpha * (max - min))..=(max + self.alpha * (max - min));

                        rng.random_range(interval)
                    }
                ));
        }

        Population::from_vec(offsprings)
    }
}