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>

source

pub fn builder() -> EvolveBuilder<G, M, F, S, C, E, SR>

source

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>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
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>

source§

impl<G: Genotype, M: Mutate, F: Fitness<Genotype = G>, S: Crossover, C: Compete, E: Extension, SR: EvolveReporter<Genotype = G>> TryFrom<Builder<G, M, F, S, C, E, SR>> for Evolve<G, M, F, S, C, E, SR>

§

type Error = TryFromBuilderError

The type returned in the event of a conversion error.
source§

fn try_from( builder: EvolveBuilder<G, M, F, S, C, E, SR>, ) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementations§

§

impl<G, M, F, S, C, E, SR> Freeze for Evolve<G, M, F, S, C, E, SR>
where G: Freeze, F: Freeze, SR: Freeze, M: Freeze, S: Freeze, C: Freeze, E: Freeze,

§

impl<G, M, F, S, C, E, SR> RefUnwindSafe for Evolve<G, M, F, S, C, E, SR>

§

impl<G, M, F, S, C, E, SR> Send for Evolve<G, M, F, S, C, E, SR>
where M: Send, S: Send, C: Send, E: Send,

§

impl<G, M, F, S, C, E, SR> Sync for Evolve<G, M, F, S, C, E, SR>
where G: Sync, SR: Sync, M: Sync, S: Sync, C: Sync, E: Sync, <G as Genotype>::Allele: Sync,

§

impl<G, M, F, S, C, E, SR> Unpin for Evolve<G, M, F, S, C, E, SR>
where G: Unpin, F: Unpin, SR: Unpin, M: Unpin, S: Unpin, C: Unpin, E: Unpin, <G as Genotype>::Allele: Unpin,

§

impl<G, M, F, S, C, E, SR> UnwindSafe for Evolve<G, M, F, S, C, E, SR>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

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
source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V