genetic-algorithm-meta
This library was extracted from the crate genetic_algorithm and therefore depends on it. Version numbers are kept in-sync to indicate compatibility.
One cool thing to do with genotypes is to make a meta-genotype of all the Crossover/Mutate/Compete strategies and other Evolve parameters. This could be used to optimize the parameters of some other genetic algorithm. Yes, a simple nested for loop would also work, but where is the fun in that? But I wasn't able to find an elegant approach to creating such a heterogene setup. It was tried with Trait objects, Any and Enums, but all didn't work well:
- Genotype wasn't allowed to become a Trait object due to it's other traits and generics.
- Any worked, but you still need to know all possible Genotypes up front for downcasting, defeating the flexible purpose
- Enum worked, but you still need to know all possible Genotypes up front for wrapping, defeating the flexible purpose
So, after some consideration I settled on using an nested index based Genotype
MultiDiscreteGenotype<usize>
indices of external vectors of arbitrary types, which should
then be retrieved in the fitness function. Only one type is allowed per external vector, so the
Crossover/Mutate/Compete strategies all have a Wrapper implementation forwarding to the
underlying types (e.g. CompeteTournament::new(4).into()
)
Currently implemented as a permutation, but with caching an evolve strategy could also be used for larger search spaces.
Documentation
See docs.rs
Examples
Run with cargo run --example [EXAMPLE_BASENAME] --release
- example/meta_evolve_binary
cargo run --example meta_evolve_binary --release
- example/meta_evolve_milp
cargo run --example meta_evolve_milp --release
- example/meta_evolve_monkeys
cargo run --example meta_evolve_monkeys --release
- example/meta_evolve_nqueens
cargo run --example meta_evolve_nqueens --release
"Quick" Usage
use CountTrue;
use *;
use *;
let rounds = 10;
let target_population_sizes = vec!;
let max_stale_generations_options = vec!;
let max_chromosome_age_options = vec!;
let target_fitness_score_options = vec!;
let mutates = vec!;
let crossovers = vec!;
let competes = vec!;
let extensions = vec!;
let genotype = builder
.with_genes_size
.build
.unwrap;
let fitness = CountTrue;
let evolve_builder = new
.with_genotype
.with_fitness
.with_fitness_ordering;
let evolve_fitness_to_micro_second_factor = 1_000_000;
let config = builder
.with_evolve_builder
.with_evolve_fitness_to_micro_second_factor
.with_rounds
.with_target_population_sizes
.with_max_stale_generations_options
.with_max_chromosome_age_options
.with_target_fitness_score_options
.with_mutates
.with_crossovers
.with_competes
.with_extensions
.build
.unwrap;
let permutate = new.call;
println!;
println!;
// meta-permutate population_size: 270
// [...]
// meta-permutate:
// best_target_population_size: 2
// best_max_stale_generations: Some(10)
// best_max_chromosome_age: Some(10)
// best_target_fitness_score: Some(0)
// best_mutate: Some(Once(Once { mutation_probability: 0.4 }))
// best_crossover: Some(Clone(Clone { keep_parent: true }))
// best_compete: Some(Elite(Elite))
// best_extension: Some(Noop(Noop))
Tests
Run tests with cargo test