2 releases
0.7.2 | Jul 27, 2024 |
---|---|
0.7.1 | Jul 27, 2024 |
#1094 in Algorithms
33KB
504 lines
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 genetic_algorithm::fitness::placeholders::CountTrue;
use genetic_algorithm::strategy::evolve::prelude::*;
use genetic_algorithm_meta::prelude::*;
let rounds = 10;
let target_population_sizes = vec![2, 4, 8];
let max_stale_generations_options = vec![Some(10)];
let max_chromosome_age_options = vec![Some(10)];
let target_fitness_score_options = vec![Some(0)];
let mutates = vec![
MutateOnce::new(0.05).into(),
MutateOnce::new(0.2).into(),
MutateOnce::new(0.4).into(),
];
let crossovers = vec![
CrossoverClone::new(true).into(),
CrossoverSingleGene::new(false).into(),
CrossoverSingleGene::new(true).into(),
CrossoverSinglePoint::new(true).into(),
CrossoverUniform::new(true).into(),
];
let competes = vec![
CompeteElite::new().into(),
CompeteTournament::new(3).into(),
CompeteTournament::new(4).into(),
];
let extensions = vec![
ExtensionNoop::new().into(),
ExtensionMassExtinction::new(0.9, 0.1).into(),
ExtensionMassGenesis::new(0.9).into(),
ExtensionMassInvasion::new(0.9, 0.1).into(),
ExtensionMassDegeneration::new(0.9, 10).into(),
];
let genotype = BinaryGenotype::builder()
.with_genes_size(10)
.build()
.unwrap();
let fitness = CountTrue;
let evolve_builder = EvolveBuilder::new()
.with_genotype(genotype)
.with_fitness(fitness)
.with_fitness_ordering(FitnessOrdering::Minimize);
let evolve_fitness_to_micro_second_factor = 1_000_000;
let config = MetaConfig::builder()
.with_evolve_builder(evolve_builder)
.with_evolve_fitness_to_micro_second_factor(evolve_fitness_to_micro_second_factor)
.with_rounds(rounds)
.with_target_population_sizes(target_population_sizes)
.with_max_stale_generations_options(max_stale_generations_options)
.with_max_chromosome_age_options(max_chromosome_age_options)
.with_target_fitness_score_options(target_fitness_score_options)
.with_mutates(mutates)
.with_crossovers(crossovers)
.with_competes(competes)
.with_extensions(extensions)
.build()
.unwrap();
let permutate = MetaPermutate::new(&config).call();
println!();
println!("{}", permutate);
// 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
Issues
Dependencies
~3.5MB
~65K SLoC