genetic-algorithm
A genetic algorithm implementation for Rust. Inspired by the book Genetic Algorithms in Elixir
There are three main elements to this approach:
- The Genotype (the search space)
- The Fitness function (the search goal)
- The Evolve strategy (the search strategy)
Documentation
See crate.io
Quick Usage
use *;
// the search space
let genotype = builder // boolean genes
.with_gene_size // 100 of them
.build
.unwrap;
println!;
// the search goal to optimize towards (maximize or minimize)
;
// the search strategy
let mut rng = thread_rng; // a randomness provider implementing Trait rand::Rng
let evolve = builder
.with_genotype
.with_population_size // evolve with 100 chromosomes
.with_target_fitness_score // goal is 100 times true in the best chromosome
.with_fitness // count the number of true values in the chromosomes
.with_crossover // crossover all individual genes between 2 chromosomes for offspring
.with_mutate // mutate a single gene with a 20% probability per chromosome
.with_compete // sort the chromosomes by fitness to determine crossover order
.build
.unwrap
.call;
println!;
Examples
Run with cargo run --example [EXAMPLE_BASENAME] --release
- N-Queens puzzle https://en.wikipedia.org/wiki/Eight_queens_puzzle.
- See example/evolve_nqueens
UniqueDiscreteGenotype<u8>
with a 64x64 chess board setup and customNQueensFitness
fitness
- Knapsack problem: https://en.wikipedia.org/wiki/Knapsack_problem
- See example/evolve_knapsack
DiscreteGenotype<(weight, value)>
with a customKnapsackFitness(weight_limit)
fitness
- Infinite Monkey theorem: https://en.wikipedia.org/wiki/Infinite_monkey_theorem
- See example/evolve_monkeys
DiscreteGenotype<u8>
100 monkeys randomly typing characters in a loop
- Custom Fitness function with LRU cache
- See example/evolve_binary_lru_cache_fitness
- Note: doesn't help performance much in this case...
- Permutation strategy instead of Evolve strategy for small search spaces
Tests
Run tests with cargo test
Benchmarks
Implemented using criterion. Run benchmarks with cargo bench
Profiling
Implemented using criterion and pprof.
Find the flamegraph in: ./target/criterion/profile_evolve_binary/profile/flamegraph.svg
Run with cargo run --example profile_evolve_binary --release -- --bench --profile-time 5
TODO
- Maybe seed best_chromosome back into population after degenerate?
- Make duration stats return Duration, so we can choose sec/milli/micro afterwards.
- Make fitness/simple_sum generic
- Support genotypes with variable length (for knapsack problem). A Bag / Set type?
- Add a chromosome stream for Permutate, instead of initializing the full population