Struct genetic_algorithm::strategy::evolve::Evolve
source · pub struct Evolve<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> {
pub genotype: G,
pub fitness: F,
pub plugins: EvolvePlugins<M, S, C, E>,
pub config: EvolveConfig,
pub state: EvolveState<G>,
/* private fields */
}Expand description
The Evolve strategy initializes with a random population of chromosomes (unless the genotype seeds specific genes to start with). Then the Evolve strategy runs through generations of chromosomes in a loop:
- crossover to produce new offspring with a mix of parents chromosome genes
- mutate a subset of chromosomes to add some additional diversity
- calculate fitness for all chromosomes
- compete to pair up chromosomes for crossover in next generation and drop excess chromosomes
- store best chromosome
- check ending conditions
- extension an optional additional step (e.g. MassExtinction)
The ending conditions are one or more of the following:
- target_fitness_score: when the ultimate goal in terms of fitness score is known and reached
- max_stale_generations: when the ultimate goal in terms of fitness score is unknown and one depends on some convergion threshold, or one wants a duration limitation next to the target_fitness_score
There are reporting hooks in the loop receiving the EvolveState, which can by handled by an EvolveReporter (e.g. EvolveReporterNoop, EvolveReporterSimple). But you are encouraged to roll your own, see EvolveReporter.
At the EvolveBuilder level, there are two additional mechanisms:
- call_repeatedly: this runs multiple independent evolve strategies and returns the best one (or short circuits when the target_fitness_score is reached)
- call_speciated: this runs multiple independent evolve strategies and then competes their best results against each other in one final evolve strategy
See EvolveBuilder for initialization options.
Example:
use genetic_algorithm::strategy::evolve::prelude::*;
use genetic_algorithm::fitness::placeholders::CountTrue;
// the search space
let genotype = BinaryGenotype::builder() // boolean alleles
.with_genes_size(100) // 100 genes per chromosome
.build()
.unwrap();
// the search strategy
let mut rng = rand::thread_rng(); // a randomness provider implementing Trait rand::Rng
let evolve = Evolve::builder()
.with_genotype(genotype)
.with_target_population_size(100) // evolve with 100 chromosomes
.with_target_fitness_score(0) // ending condition if 0 times true in the best chromosome
.with_valid_fitness_score(10) // block ending conditions until at most a 10 times true in the best chromosome
.with_max_stale_generations(1000) // stop searching if there is no improvement in fitness score for 1000 generations
.with_max_chromosome_age(10) // kill chromosomes after 10 generations
.with_fitness(CountTrue) // count the number of true values in the chromosomes
.with_fitness_ordering(FitnessOrdering::Minimize) // aim for the least true values
.with_multithreading(true) // use all cores for calculating the fitness of the population
.with_crossover(CrossoverUniform::new(true)) // crossover all individual genes between 2 chromosomes for offspring
.with_mutate(MutateSingleGeneRandom::new(0.2)) // mutate a single gene with a 20% probability per chromosome
.with_compete(CompeteElite::new()) // sort the chromosomes by fitness to determine crossover order
.with_extension(ExtensionMassExtinction::new(10, 0.1)) // simulate cambrian explosion by mass extinction, when fitness score cardinality drops to 10, trim to 10% of population
.with_reporter(EvolveReporterNoop::new()) // no reporting
.call(&mut rng)
.unwrap();
// it's all about the best chromosome after all
let best_chromosome = evolve.best_chromosome().unwrap();
assert_eq!(best_chromosome.genes, vec![false; 100])Fields§
§genotype: G§fitness: F§plugins: EvolvePlugins<M, S, C, E>§config: EvolveConfig§state: EvolveState<G>Implementations§
source§impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> Evolve<G, M, F, S, C, E, SR>
impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> Evolve<G, M, F, S, C, E, SR>
pub fn builder() -> EvolveBuilder<G, M, F, S, C, E, SR>
pub fn population_factory<R: Rng>(&mut self, rng: &mut R) -> Population<G>
Trait Implementations§
source§impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> Display for Evolve<G, M, F, S, C, E, SR>
impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> Display for Evolve<G, M, F, S, C, E, SR>
source§impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> Strategy<G> for Evolve<G, M, F, S, C, E, SR>
impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> Strategy<G> for Evolve<G, M, F, S, C, E, SR>
fn call<R: Rng>(&mut self, rng: &mut R)
fn best_chromosome(&self) -> Option<Chromosome<G>>
fn best_generation(&self) -> usize
fn best_fitness_score(&self) -> Option<FitnessValue>
Auto Trait Implementations§
impl<G, M, F, S, C, E, SR> Freeze for Evolve<G, M, F, S, C, E, SR>
impl<G, M, F, S, C, E, SR> RefUnwindSafe for Evolve<G, M, F, S, C, E, SR>where
G: RefUnwindSafe,
F: RefUnwindSafe,
SR: RefUnwindSafe,
M: RefUnwindSafe,
S: RefUnwindSafe,
C: RefUnwindSafe,
E: RefUnwindSafe,
<G as Genotype>::Allele: RefUnwindSafe,
impl<G, M, F, S, C, E, SR> Send for Evolve<G, M, F, S, C, E, SR>
impl<G, M, F, S, C, E, SR> Sync for Evolve<G, M, F, S, C, E, SR>
impl<G, M, F, S, C, E, SR> Unpin for Evolve<G, M, F, S, C, E, SR>
impl<G, M, F, S, C, E, SR> UnwindSafe for Evolve<G, M, F, S, C, E, SR>where
G: UnwindSafe,
F: UnwindSafe,
SR: UnwindSafe,
M: UnwindSafe,
S: UnwindSafe,
C: UnwindSafe,
E: UnwindSafe,
<G as Genotype>::Allele: UnwindSafe,
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more