| Crates.io | gentle-ga |
| lib.rs | gentle-ga |
| version | 0.1.0 |
| created_at | 2025-10-31 13:34:53.358255+00 |
| updated_at | 2025-10-31 13:34:53.358255+00 |
| description | Ergonomic, strongly-typed genetic algorithm framework (static dispatch). |
| homepage | |
| repository | https://github.com/MatthewScholefield/gentle-ga |
| max_upload_size | |
| id | 1910034 |
| size | 18,615 |
Ergonomic, strongly-typed genetic algorithm framework for Rust. The core goal: make it dead-simple to plug in your domain logic (genome + fitness) with a single trait, while the engine handles population orchestration, selection, mutation/crossover rates, seeding, and elitism — all with zero-cost static dispatch.
Problem (your genome and fitness).GA::builder(...) API.This example evolves a single f64 to maximize cos(x) - x^2 using tournament selection, crossover-as-average, and small uniform mutation. It showcases the minimal surface area you implement and the ergonomic builder.
use gentle_ga::prelude::*;
struct Hill;
impl Problem for Hill {
type Genome = f64;
type Fitness = f64;
fn random_genome<R: rand::Rng + ?Sized>(&mut self, rng: &mut R) -> Self::Genome {
rand::Rng::gen_range(rng, -5.0..5.0)
}
fn fitness(&self, x: &Self::Genome) -> Self::Fitness {
x.cos() - x * x
}
fn mutate<R: rand::Rng + ?Sized>(&mut self, x: &mut Self::Genome, rng: &mut R) {
*x += rand::Rng::gen_range(rng, -0.2..0.2);
}
fn crossover<R: rand::Rng + ?Sized>(
&mut self,
a: &Self::Genome,
b: &Self::Genome,
_rng: &mut R,
) -> Self::Genome {
0.5 * (*a + *b)
}
}
fn main() {
// Build and run the GA with ergonomic configuration.
let mut ga = GA::builder(Hill)
.pop_size(200)
.mutation_rate(0.2)
.crossover_rate(0.7)
.elitism(2)
.seed(42)
.build();
let result = ga.run_for(200);
println!(
"gen={} best x={:.4} fitness={:.6} avg_fitness={:.6}",
result.generations, result.best.genome, result.best.fitness, result.average_fitness
);
}
Using Cargo Add:
cargo add gentle-ga
Or add to your Cargo.toml:
[dependencies]
gentle-ga = "0.1"