Crossover

Trait Crossover 

Source
pub trait Crossover:
    Clone
    + Send
    + Sync
    + Debug {
    type Genotype: EvolveGenotype;

    // Required method
    fn call<R: Rng, SR: StrategyReporter<Genotype = Self::Genotype>>(
        &mut self,
        genotype: &Self::Genotype,
        state: &mut EvolveState<Self::Genotype>,
        config: &EvolveConfig,
        reporter: &mut SR,
        rng: &mut R,
    );

    // Provided methods
    fn require_crossover_indexes(&self) -> bool { ... }
    fn require_crossover_points(&self) -> bool { ... }
}
Expand description

§Optional Custom User implementation (rarely needed)

For the user API, the Crossover Trait has an associated Genotype. This way the user can implement a specialized Crossover alterative with access to the user’s Genotype specific methods at hand.

§Example

use genetic_algorithm::strategy::evolve::prelude::*;
use std::time::Instant;
use itertools::Itertools;
use rand::Rng;

#[derive(Clone, Debug)]
struct CustomCrossover {
    pub selection_rate: f32,
};
impl Crossover for CustomCrossover {
    type Genotype = MultiRangeGenotype<f32>;

    fn call<R: Rng, SR: StrategyReporter<Genotype = Self::Genotype>>(
        &mut self,
        genotype: &Self::Genotype,
        state: &mut EvolveState<Self::Genotype>,
        config: &EvolveConfig,
        reporter: &mut SR,
        _rng: &mut R,
    ) {
        let now = Instant::now();
        let existing_population_size = state.population.chromosomes.len();
        let selected_population_size =
            (existing_population_size as f32 * self.selection_rate).ceil() as usize;

        // Important!!! Append offspring as recycled clones from parents (will crossover later)
        // Use population's methods for safe chromosome recycling
        state.population.extend_from_within(selected_population_size);

        // Skip the parents, iterate over the freshly appended offspring
        let iterator = state
            .population
            .chromosomes
            .iter_mut()
            .skip(existing_population_size);

        // Crossover the offspring clones
        for (offspring1, offspring2) in iterator.tuples() {
            // Custom logic, for instance, swap all genes with even index
            for even_index in (0..genotype.genes_size()).filter(|x| x % 2 == 0) {
                std::mem::swap(&mut offspring1.genes[even_index], &mut offspring2.genes[even_index]);
                // MultiRangeGenotype specific methods are available if needed
            }
            // Important!!! Remember to reset the chromosome metadata after manipulation
            offspring1.reset_metadata(genotype.genes_hashing);
            offspring2.reset_metadata(genotype.genes_hashing);
        }

        // Optionally, log one ore more events
        reporter.on_crossover_event(
            CrossoverEvent("MyEvent".to_string()),
            genotype,
            state,
            config,
        );

        // Optionally, keep track of duration for reporting
        state.add_duration(StrategyAction::Crossover, now.elapsed());
    }
}

Required Associated Types§

Required Methods§

Source

fn call<R: Rng, SR: StrategyReporter<Genotype = Self::Genotype>>( &mut self, genotype: &Self::Genotype, state: &mut EvolveState<Self::Genotype>, config: &EvolveConfig, reporter: &mut SR, rng: &mut R, )

Provided Methods§

Source

fn require_crossover_indexes(&self) -> bool

to guard against invalid Crossover strategies which break the internal consistency of the genes, unique genotypes can’t simply exchange genes without gene duplication issues

Source

fn require_crossover_points(&self) -> bool

to guard against invalid Crossover strategies which break the internal consistency of the genes, unique genotypes can’t simply exchange genes without gene duplication issues

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§