# genetic_algorithms (v2.1.0)
[](https://github.com/leimbernon/rust_genetic_algorithms/actions/workflows/rust-unit-tests.yml)
Modular and concurrent Genetic Algorithms (GA) library for Rust featuring:
- Clear abstractions (traits for genes, chromosomes, and configuration).
- Composable operators (selection, crossover, mutation, survivor, extension).
- Multi-threaded execution via `rayon` (fitness evaluation, reproduction, mutation in parallel).
- Adaptive GA mode (dynamic crossover and mutation probabilities based on population performance).
- Elitism support (preserve top N individuals across generations).
- Extension strategies for population diversity control (mass extinction, genesis, degeneration, deduplication).
- Population diversity metric tracked per generation.
- Lifecycle reporter hooks (`on_start`, `on_generation_complete`, `on_new_best`, `on_finish`).
- Compound stopping criteria (stagnation, convergence, time limit).
- `Cow` for minimizing unnecessary DNA copies.
- Optional `visualization` feature for PNG/SVG fitness and diversity charts.
## Table of Contents
- [Documentation](#documentation)
- [Changelog](CHANGELOG.md)
- [Status & Key Changes 2.0.0](#status--key-changes-200)
- [Features](#features)
- [Traits](#traits)
- [Included Genotypes & Chromosomes](#included-genotypes--chromosomes)
- [Initializers](#initializers)
- [Operators](#operators)
- [Reporter](#reporter)
- [Visualization](#visualization)
- [GA Configuration](#ga-configuration)
- [Adaptive GA](#adaptive-ga)
- [Multithreading & Performance](#multithreading--performance)
- [Quick Example](#quick-example)
- [Full Example (Range)](#full-example-range)
- [Examples](#examples)
- [Usage](#usage)
- [Development](#development)
- [Roadmap / Notes](#roadmap--notes)
- [License](#license)
## Documentation
Latest published docs: [docs.rs/genetic_algorithms](https://docs.rs/genetic_algorithms/latest/genetic_algorithms)
## Status & Key Changes 2.0.0
Main differences vs 1.x:
- Crate version: 2.0.0 (update your `Cargo.toml`).
- Structured error handling: all operators return `Result<T, GaError>` instead of panicking.
- Parallelism via `rayon` replacing manual thread management.
- `GeneT::get_id()` now returns `i32` directly.
- `ChromosomeT::set_dna` now uses `Cow<'a, [Gene]>` to avoid redundant copies.
- Added `Range<T>` genotype alongside `Binary` (supports numeric ranges).
- New operators: `SinglePoint`, `Order` (OX), `BitFlip`, `Value`, `Creep`, `Gaussian` mutations; `SBX`, `BlendAlpha` crossovers; `Rank` selection.
- Elitism: `with_elitism(n)` preserves the top N individuals across generations.
- Compound stopping criteria: stagnation detection, convergence threshold, time limit.
- Per-generation statistics tracking via `GenerationStats`.
- Adaptive probability helpers: `aga_probability` for crossover & mutation.
- Expanded configuration: `FixedFitness`, logging levels (`Off`..`Trace`), configurable threads.
- Internal benchmarks use Criterion 0.7 (pprof integration removed due to version conflict).
## Features
### Traits
- `GeneT`:
- Requires: `Default + Clone + Send + Sync`.
- Key methods: `new()`, `get_id() -> i32`, `set_id(i32)`.
- `ChromosomeT`:
- Associated: `type Gene: GeneT`.
- Supports: `get_dna()`, `set_dna(Cow<[Gene]>)`, `set_gene(idx, gene)`, `set_fitness_fn(...)`, `calculate_fitness()`, `get_fitness()`, `set_fitness(f64)`, `get_age()`, `set_age(i32)`.
- Derived metric: `get_fitness_distance(&fitness_target)`.
- `ConfigurationT`: builder-style API for `Ga` / `GaConfiguration`.
### Included Genotypes & Chromosomes
- `genotypes::Binary` (boolean gene).
- `genotypes::Range<T>` (values constrained to one or more `(min,max)` intervals).
- `genotypes::List<T>` (values drawn from a finite symbolic alphabet).
- `chromosomes::Range<T>` (chromosome built from `Range<T>` genes).
- `chromosomes::ListChromosome<T>` (chromosome built from `List<T>` genes).
- (Custom chromosomes can be added by implementing `ChromosomeT`).
### Initializers
- `initializers::binary_random_initialization`.
- `initializers::range_random_initialization`.
- `initializers::list_random_initialization` (for `List<T>` chromosomes, with repetition).
- `initializers::list_random_initialization_without_repetitions` (permutation problems).
- `initializers::generic_random_initialization` (takes allele slice, optional unique IDs).
- `initializers::generic_random_initialization_without_repetitions` (no allele repetition).
### Operators
- **Selection:** `Random`, `RouletteWheel`, `StochasticUniversalSampling`, `Tournament`, `Rank`.
- **Crossover:** `Cycle`, `MultiPoint`, `Uniform`, `SinglePoint`, `Order` (OX), `Sbx` (Simulated Binary), `BlendAlpha` (BLX-α).
- **Mutation:** `Swap`, `Inversion`, `Scramble`, `Value` (Range<T>), `BitFlip` (Binary), `Creep` (uniform perturbation), `Gaussian` (normal perturbation), `ListValue` (List<T>).
- **Survivor:** `Fitness` (keep best), `Age` (prefer younger / age-based pruning).
- **Extension:** `Noop`, `MassExtinction`, `MassGenesis`, `MassDegeneration`, `MassDeduplication`.
### Reporter
Attach a lifecycle observer to `Ga` via `.with_reporter(Box::new(r))`. Four hooks: `on_start`, `on_generation_complete`, `on_new_best`, `on_finish`. Zero overhead when no reporter is configured (stored as `Option`).
Built-in reporters:
- `reporter::NoopReporter` — default, no-op.
- `reporter::SimpleReporter::new(n)` — prints a progress line every N generations.
- `reporter::DurationReporter::new()` — reports total elapsed time and per-generation average at finish.
Implement `Reporter<U>` to build custom observers.
### Visualization
Optional feature flag. Add to `Cargo.toml`:
```toml
genetic_algorithms = { version = "2.1.0", features = ["visualization"] }
```
Three functions in `genetic_algorithms::visualization`:
```rust
// Fitness over generations (best, average, worst lines)
visualization::plot_fitness(&stats, "fitness.png")?;
visualization::plot_fitness(&stats, "fitness.svg")?;
// Diversity over generations
visualization::plot_diversity(&stats, "diversity.png")?;
// Fitness distribution for a generation (raw fitness values)
```
Format is determined by path extension (`.png` or `.svg`). All functions return `Result<(), VisualizationError>`.
### GA Configuration
`GaConfiguration` (or the `Ga` builder) exposes:
- **Limits:** `problem_solving` (`Minimization | Maximization | FixedFitness`), `max_generations`, `fitness_target`, `population_size`, `genes_per_chromosome`, `needs_unique_ids`, `alleles_can_be_repeated`.
- **Selection:** `number_of_couples`, `method`.
- **Crossover:** `number_of_points` (MultiPoint), `probability_min` / `probability_max`, `method`, `sbx_eta` (SBX distribution index), `blend_alpha` (BLX-α alpha parameter).
- **Mutation:** `probability_min` / `probability_max`, `method`, `step` (Creep step size), `sigma` (Gaussian standard deviation).
- **Survivor:** `survivor`.
- **Elitism:** `elitism_count` — preserve the top N individuals unchanged across generations.
- **Extension:** `extension_configuration` — optional diversity control strategies. Configure with `with_extension_method()`, `with_extension_diversity_threshold()`, `with_extension_survival_rate()`, `with_extension_mutation_rounds()`, `with_extension_elite_count()`.
- **Stopping criteria:** `StoppingCriteria` with `stagnation_generations`, `convergence_threshold`, `max_duration_secs`. The GA stops when **any** enabled criterion is met.
- **Infra:** `adaptive_ga`, `number_of_threads`, `log_level`.
- **Progress** (present but not yet wired): `save_progress_configuration` (future/experimental).
### Adaptive GA
When `adaptive_ga = true`:
- Crossover & mutation probabilities are recomputed per parent pair using relative fitness (`f_max`, `f_avg`).
- You must set both `probability_min` and `probability_max` for crossover and mutation.
When `adaptive_ga = false`:
- If `probability_max` is absent, defaults to 1.0 (operator always applied).
### Multithreading & Performance
- `with_threads(n)` configures parallelism (internally uses `rayon`).
- Selection, crossover, mutation, and fitness evaluation are parallelized each generation.
- `Cow` prevents needless cloning of DNA vectors.
## Quick Example
Minimal GA using `Range<i32>` chromosomes targeting fitness 0 (minimization):
```rust
use genetic_algorithms::ga::Ga;
use genetic_algorithms::traits::ConfigurationT;
use genetic_algorithms::configuration::ProblemSolving;
use genetic_algorithms::operations::{Selection, Crossover, Mutation, Survivor};
use genetic_algorithms::genotypes::Range as RangeGene;
use genetic_algorithms::initializers::range_random_initialization;
use genetic_algorithms::chromosomes::Range as RangeChromosome; // Chromosome type
fn fitness_fn(dna: &[RangeGene<i32>]) -> f64 { // Replace with domain logic
dna.iter().map(|g| g.get_value() as f64).sum() // Simple example
}
let alleles = vec![RangeGene::new(0, vec![(0, 7)], 0)];
let alleles_clone = alleles.clone();
let mut ga = Ga::<RangeChromosome<i32>>::new();
let _population = ga
.with_genes_per_chromosome(8)
.with_population_size(100)
.with_initialization_fn(move |genes, _, _| {
range_random_initialization(genes, Some(&alleles_clone), Some(false))
})
.with_fitness_fn(fitness_fn)
.with_selection_method(Selection::Tournament)
.with_crossover_method(Crossover::Uniform)
.with_mutation_method(Mutation::Swap)
.with_survivor_method(Survivor::Fitness)
.with_problem_solving(ProblemSolving::Minimization)
.with_max_generations(500)
.with_fitness_target(0.0)
.with_threads(4)
.run();
```
## Full Example (Range)
Includes adaptive GA and probabilities:
```rust
use genetic_algorithms::{ga::Ga, traits::ConfigurationT};
use genetic_algorithms::configuration::ProblemSolving;
use genetic_algorithms::operations::{Selection, Crossover, Mutation, Survivor};
use genetic_algorithms::genotypes::Range as RangeGene;
use genetic_algorithms::chromosomes::Range as RangeChromosome;
use genetic_algorithms::initializers::range_random_initialization;
fn fitness_fn(dna: &[RangeGene<i32>]) -> f64 {
// Penalize greater values: minimization goal
dna.iter().map(|g| g.get_value() as f64).sum()
}
let alleles = vec![RangeGene::new(0, vec![(0, 50)], 0)];
let alleles_clone = alleles.clone();
let mut ga = Ga::<RangeChromosome<i32>>::new();
let population = ga
.with_adaptive_ga(true)
.with_genes_per_chromosome(16)
.with_population_size(200)
.with_initialization_fn(move |genes, _, _| {
range_random_initialization(genes, Some(&alleles_clone), Some(false))
})
.with_fitness_fn(fitness_fn)
.with_selection_method(Selection::StochasticUniversalSampling)
.with_crossover_method(Crossover::MultiPoint)
.with_crossover_number_of_points(3)
.with_crossover_probability_min(0.4)
.with_crossover_probability_max(0.9)
.with_mutation_method(Mutation::Inversion)
.with_mutation_probability_min(0.05)
.with_mutation_probability_max(0.3)
.with_survivor_method(Survivor::Fitness)
.with_problem_solving(ProblemSolving::Minimization)
.with_max_generations(2000)
.with_fitness_target(0.0)
.with_threads(8)
.with_logs(genetic_algorithms::configuration::LogLevel::Info)
.run();
println!("Best fitness: {}", population.unwrap().best_chromosome.get_fitness());
```
## Examples
Run any example directly with `cargo run`:
| `rastrigin` | Continuous optimization | `cargo run --example rastrigin` |
| `nsga2_zdt1` | Multi-objective (NSGA-II) | `cargo run --example nsga2_zdt1` |
| `island_model` | Parallel / island model | `cargo run --example island_model` |
| `job_scheduling` | Permutation / scheduling | `cargo run --example job_scheduling` |
| `feature_selection` | Binary / adaptive GA | `cargo run --example feature_selection` |
| `niching` | Multimodal / niching | `cargo run --example niching` |
| `knapsack_binary` | Binary / combinatorial | `cargo run --example knapsack_binary` |
| `nqueens_range` | Constraint satisfaction | `cargo run --example nqueens_range` |
| `onemax_binary` | Binary / baseline | `cargo run --example onemax_binary` |
| `onemax_extension` | Binary / diversity control | `cargo run --example onemax_extension` |
## Usage
Add to your `Cargo.toml`:
```toml
[dependencies]
genetic_algorithms = "2.1.0"
# Optional: enable PNG/SVG chart generation
# genetic_algorithms = { version = "2.1.0", features = ["visualization"] }
```
## Development
### Build
```bash
cargo build # Debug build
cargo build --release # Optimized release build
```
### Run Tests
```bash
cargo test # Run all tests
cargo test --features serde # Include serde tests
cargo test --features visualization # Include visualization tests
cargo test -- --nocapture # With visible stdout/stderr
```
### Run Benchmarks
Benchmarks use [Criterion](https://github.com/bheisler/criterion.rs) and are located in `benches/`.
```bash
cargo bench # Run all benchmarks
cargo bench --bench crossover # Run only crossover benchmarks
cargo bench --bench mutation # Run only mutation benchmarks
cargo bench --bench selection # Run only selection benchmarks
cargo bench --bench survivor # Run only survivor benchmarks
cargo bench --no-run # Only compile benchmarks (useful for CI)
```
Reports are generated in `target/criterion/` and can be viewed in a browser.
### Code Quality
```bash
cargo fmt --check # Check formatting (no changes)
cargo fmt # Auto-format code
cargo clippy # Run linter
```
## Roadmap / Notes
- `save_progress_configuration`: fields present but not wired into the main loop yet (future: periodic population / best chromosome persistence).
- Optional flamegraph profiling integration removed to avoid Criterion version conflicts.
- For heavy fitness functions consider external profiling tools.
## License
Apache-2.0. See LICENSE file.