Expand description
§evolve
A generic, composable genetic algorithm framework for Rust.
evolve provides the building blocks to assemble genetic algorithms from reusable,
type-safe components. Operators are composed using combinators — chain them into
pipelines, weight them probabilistically, or repeat them to fill a population —
all with zero-cost abstractions.
§Features
- Fully generic over genome type, fitness type, RNG, and fitness comparator
- Built-in operators for selection, crossover, and mutation
- Composable combinators for structuring the flow of the algorithm
MaximizeandMinimizefitness comparators out of the box- Closures work as fitness evaluators and comparators via blanket trait impls
- No dependencies beyond
rand
§Quick Start
The simplest way to get started is to use Random initialization,
a MaxGenerations termination condition, and
Fill with a mutation operator:
use evolve::{
algorithm::ga::GeneticAlgorithm,
fitness::Maximize,
initialization::Random,
operators::combinator::Fill,
operators::mutation::RandomReset,
termination::MaxGenerations,
};
use std::num::NonZero;
let mut ga = GeneticAlgorithm::new(
Random::new(),
MaxGenerations::new(100),
|args: &[u32; 2]| args[0] as usize + args[1] as usize,
Fill::from_population_size(RandomReset::new()),
NonZero::new(500).unwrap(),
rand::rng(),
Maximize,
);
let result = ga.run();
let best = result.population.best(&Maximize);
println!("Best genome: {:?}, fitness: {:?}", best.genome(), best.fitness());§Composing Operators
The real power of evolve comes from composing operators using combinators.
A typical genetic algorithm pipeline selects parents, crosses them over, and
mutates the offspring:
use evolve::{
algorithm::ga::GeneticAlgorithm,
fitness::Maximize,
initialization::Random,
operators::combinator::{Combine, Fill, Pipeline},
operators::crossover::SinglePoint,
operators::mutation::RandomReset,
operators::selection::TournamentSelection,
termination::MaxGenerations,
};
use std::num::NonZero;
// Select two parents → crossover → mutate, repeated until the population is full
let operators = Fill::from_population_size(Pipeline::new((
Combine::new((
TournamentSelection::new(NonZero::new(3).unwrap()),
TournamentSelection::new(NonZero::new(3).unwrap()),
)),
SinglePoint::new(),
RandomReset::new(),
)));
let mut ga = GeneticAlgorithm::new(
Random::new(),
MaxGenerations::new(200),
|g: &[u8; 8]| g.iter().map(|x| *x as u32).sum::<u32>(),
operators,
NonZero::new(100).unwrap(),
rand::rng(),
Maximize,
);
let result = ga.run();§Weighted Operator Selection
Use Weighted to probabilistically choose
between different operators each time:
use evolve::operators::combinator::{Fill, Weighted};
use evolve::operators::mutation::RandomReset;
use evolve::operators::crossover::SinglePoint;
use std::num::NonZero;
// 75% chance of mutation, 25% chance of crossover
let operators = Fill::from_population_size(Weighted::new((
(RandomReset::<u8>::new(), NonZero::new(3u16).unwrap()),
(SinglePoint::<u8>::new(), NonZero::new(1u16).unwrap()),
)));§Custom Fitness
Any closure Fn(&G) -> F works as a FitnessEvaluator,
and any closure Fn(&F, &F) -> bool works as a FitnessComparator:
use evolve::{
algorithm::ga::GeneticAlgorithm,
initialization::Random,
operators::combinator::Fill,
operators::mutation::RandomReset,
termination::MaxGenerations,
};
use std::num::NonZero;
// Custom comparator: prefer fitness values closer to 100
let mut ga = GeneticAlgorithm::new(
Random::new(),
MaxGenerations::new(100),
|g: &[u8; 2]| (g[0] as i32 + g[1] as i32 - 100).abs(),
Fill::from_population_size(RandomReset::new()),
NonZero::new(200).unwrap(),
rand::rng(),
|a: &i32, b: &i32| a < b, // lower distance is better
);
let result = ga.run();§Custom Operators
Implement GeneticOperator to define your own:
use evolve::{
core::{context::Context, offspring::Offspring, state::State},
operators::GeneticOperator,
};
struct MyOperator;
impl<G, F, Fe, R, C> GeneticOperator<G, F, Fe, R, C> for MyOperator {
fn apply(&self, state: &State<G, F>, ctx: &mut Context<Fe, R, C>) -> Offspring<G, F> {
todo!()
}
}Modules§
- algorithm
- Algorithm runners.
- core
- Core types that make up the genetic algorithm.
- fitness
- Fitness evaluation and comparison.
- initialization
- Population initialization strategies.
- observer
- Observers for monitoring algorithm execution.
- operators
- Genetic operators and combinators.
- random
- Random value generation for genomes and genes.
- termination
- Termination conditions for the algorithm.