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§
type Genotype: EvolveGenotype
Required Methods§
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§
Sourcefn require_crossover_indexes(&self) -> bool
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
Sourcefn require_crossover_points(&self) -> bool
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.