#genetic #ga


A genetic algorithm implementation

13 unstable releases (6 breaking)

new 0.7.0 May 25, 2023
0.6.0 Oct 14, 2022
0.5.4 Oct 14, 2022
0.5.0 Jul 7, 2022

#202 in Algorithms

33 downloads per month


4.5K SLoC


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 strategy (the search strategy)
    • Evolve (evolution strategy)
    • Permutate (for small search spaces, with a 100% guarantee)
    • HillClimb (when search space is convex with little local optima or when crossover is impossible/inefficient)


  • Population: a population has population_size number of individuals (called chromosomes).
  • Chromosome: a chromosome has genes_size number of genes
  • Gene: a gene is a combination of position in the chromosome and value of the gene (allele)
  • Allele: alleles are the possible values of the genes
  • Genotype: holds the genes_size and alleles and knows how to generate and mutate chromosomes efficiently
  • Fitness: knows how to determine the fitness of a chromosome


See docs.rs

Quick Usage

use genetic_algorithm::strategy::evolve::prelude::*;

// the search space
let genotype = BinaryGenotype::builder() // boolean alleles
    .with_genes_size(100)                // 100 genes per chromosome

println!("{}", genotype);

// the search goal to optimize towards (maximize or minimize)
#[derive(Clone, Debug)]
pub struct CountTrue;
impl Fitness for CountTrue {
    type Genotype = BinaryGenotype;
    fn calculate_for_chromosome(&mut self, chromosome: &Chromosome<Self::Genotype>) -> Option<FitnessValue> {
        Some(chromosome.genes.iter().filter(|&value| *value).count() as FitnessValue)

// the search strategy
let mut rng = rand::thread_rng();     // a randomness provider implementing Trait rand::Rng
let evolve = Evolve::builder()
    .with_population_size(100)        // evolve with 100 chromosomes
    .with_target_fitness_score(100)   // goal is 100 times true in the best chromosome
    .with_fitness(CountTrue)          // count the number of true values in the chromosomes
    .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(ExtensionNoop::new())    // extension step, disabled
    .call(&mut rng);

println!("{}", evolve);


Run with cargo run --example [EXAMPLE_BASENAME] --release


Run tests with cargo test


Implemented using criterion. Run benchmarks with cargo bench


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


  • Make duration stats return Duration, so we can choose sec/milli/micro afterwards.
  • Make fitness/simple_sum generic
  • Does Fitness need an associated trait for Genotype? Can this be made more lightweight?
  • Add simulated annealing strategy


  • Add Roulette competition with and without duplicates (with fitness ordering)
  • Add OrderOne crossover for UniqueGenotype?
  • Add WholeArithmetic crossover for ContinuousGenotype?
  • Rename Continuous to Real?


  • MutateDynamicOnce and MutateDynamicRounds are mutable, but the MutateDispatch reinitializes each round. Fix in feature/enum_plugins branch


~95K SLoC