Struct genetic_algorithm::strategy::evolve::Evolve
source · pub struct Evolve<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension> {
pub genotype: G,
pub fitness: F,
pub plugins: EvolvePlugins<M, S, C, E>,
pub config: EvolveConfig,
pub state: EvolveState<G>,
}
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
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(MutateOnce::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(0.9, 0.1)) // simulate cambrian explosion by mass extinction, when reaching 90% uniformity, trim to 10% of population
.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§
Trait Implementations§
source§impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension> Display for Evolve<G, M, F, S, C, E>
impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension> Display for Evolve<G, M, F, S, C, E>
source§impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension> Strategy<G> for Evolve<G, M, F, S, C, E>
impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension> Strategy<G> for Evolve<G, M, F, S, C, E>
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> Freeze for Evolve<G, M, F, S, C, E>
impl<G, M, F, S, C, E> RefUnwindSafe for Evolve<G, M, F, S, C, E>where
G: RefUnwindSafe,
F: RefUnwindSafe,
M: RefUnwindSafe,
S: RefUnwindSafe,
C: RefUnwindSafe,
E: RefUnwindSafe,
<G as Genotype>::Allele: RefUnwindSafe,
impl<G, M, F, S, C, E> Send for Evolve<G, M, F, S, C, E>
impl<G, M, F, S, C, E> Sync for Evolve<G, M, F, S, C, E>
impl<G, M, F, S, C, E> Unpin for Evolve<G, M, F, S, C, E>
impl<G, M, F, S, C, E> UnwindSafe for Evolve<G, M, F, S, C, E>where
G: UnwindSafe,
F: 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