Skip to content

leimbernon/genetic-algorithms

genetic_algorithms (v3.0.0)

v3.0.0 users: see MIGRATION.md for the full list of breaking changes and migration recipes.

Rust Unit Tests

Modular and concurrent evolutionary computation library for Rust. Provides 17 optimization engines — standard GA, multi-objective (NSGA-II/III, MOEA/D, SPEA2, SMS-EMOA, IBEA), island model, Differential Evolution, CMA-ES (with IPOP/BIPOP restarts), Particle Swarm Optimization, Estimation of Distribution (UMDA), Scatter Search, Cellular GA, ALPS, Hill Climbing, exhaustive Permutation search, and Genetic Programming (GP) — all generic over chromosome and gene types via traits.

Key capabilities:

  • 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: preserve top N individuals across generations.
  • Extension strategies for population diversity control (mass extinction, genesis, degeneration, deduplication).
  • Variable-length chromosomes: ChromosomeLength::Variable { min, max } with Mutation::Insertion / Mutation::Deletion and Crossover::VariableLength.
  • Parsimony pressure: length-penalized fitness during survivor selection via with_length_penalty.
  • Genetic Programming engine (GpGa) with subtree crossover, subtree/point/hoist mutation, ramped half-and-half initialization, and built-in MathNode / BoolNode primitive sets.
  • CMA-ES (CmaEngine) with Hansen-default parameter formulas, Jacobi eigendecomposition (no LAPACK, WASM-compatible), and RestartStrategy::Ipop / Bipop for multimodal landscapes.
  • PSO (PsoEngine) with configurable inertia (Constant, LinearDecay, RandomRange), topology (Global, Ring, VonNeumann), and absorbing boundary handling.
  • EDA (EdaEngine / EdaRealEngine) — UMDA Bernoulli and Gaussian probabilistic models; no crossover/mutation required.
  • Constraint handling (ConstraintHandling) — Static / Dynamic / Adaptive / Death penalties and feasibility-rules support.
  • Hall of Fame (HallOfFame) — bounded elite archive with deduplication and optional minimum-distance diversity (DistanceMetric).
  • Adaptive Operator Selection (AosStrategy) — Probability Matching, Adaptive Pursuit, and Multi-Armed Bandit credit assignment.
  • Batch fitness (BatchFitnessEvaluator) and surrogate-assisted evaluation (SurrogateModel) for expensive black-box objectives.
  • Memetic algorithms via LocalSearchOperator (Lamarckian / Baldwinian modes).
  • Standard benchmark suite (benchmarks feature): Sphere, Rastrigin, Ackley, ZDT1–6, DTLZ1–7 and multi-objective indicators (Hypervolume, GD, IGD, Spread).
  • Lifecycle observer system (GaObserver, 13 hooks including on_restart) with built-in LogObserver, CompositeObserver, MetricsObserver, TracingObserver, AllObserver, and NoopObserver.
  • Optional visualization feature for PNG/SVG fitness, diversity, and Pareto-front charts.
  • Cow<[Gene]> for zero-copy DNA operations.
  • Compound stopping criteria: stagnation, convergence threshold, time limit.
  • First-class WebAssembly support (wasm32-unknown-unknown is a CI gate).

Table of Contents

Documentation

Installation

Add to your Cargo.toml:

[dependencies]
genetic_algorithms = "3.0.0"

Optional feature flags:

# PNG/SVG fitness and diversity charts
genetic_algorithms = { version = "3.0.0", features = ["visualization"] }

# Checkpoint serialization (serde/serde_json) — includes stack-safe GP tree serialization
genetic_algorithms = { version = "3.0.0", features = ["serde"] }

# Standard benchmark functions (Sphere, Rastrigin, Rosenbrock, ZDT, DTLZ) and quality indicators
genetic_algorithms = { version = "3.0.0", features = ["benchmarks"] }

# Observer integration with the `tracing` crate
genetic_algorithms = { version = "3.0.0", features = ["observer-tracing"] }

# Observer integration with the `metrics` crate
genetic_algorithms = { version = "3.0.0", features = ["observer-metrics"] }

To shed the log crate entirely for embedded / ultra-lean / wasm-only builds:

genetic_algorithms = { version = "3.0.0", default-features = false }

The logging feature is on by default. Disabling it removes the log dependency and causes all internal log emissions to expand to () at compile time. LogObserver is also unavailable without this feature.

The parallel feature is also on by default. Disable via default-features = false to shed the rayon + crossbeam dependencies for embedded / wasm-only builds:

# Disable rayon for wasm-only or embedded builds
genetic_algorithms = { version = "3.0.0", default-features = false, features = ["logging"] }
Feature Description Default
logging log crate events via LogObserver On
parallel Parallel fitness evaluation via rayon (default-on; disable to shed rayon + crossbeam dependencies for embedded / wasm-only builds) On

Quick Start

Minimal GA using Range<f64> chromosomes, minimizing the Rastrigin function:

use genetic_algorithms::chromosomes::Range as RangeChromosome;
use genetic_algorithms::configuration::ProblemSolving;
use genetic_algorithms::ga::Ga;
use genetic_algorithms::genotypes::Range as RangeGenotype;
use genetic_algorithms::initializers::range_random_initialization;
use genetic_algorithms::operations::{Crossover, Mutation, Selection, Survivor};
use genetic_algorithms::traits::{ConfigurationT, CrossoverConfig, MutationConfig, SelectionConfig, StoppingConfig};
use genetic_algorithms::{CompositeObserver, LogObserver};
use std::sync::Arc;

let fitness_fn = |dna: &[RangeGenotype<f64>]| -> f64 {
    let a = 10.0;
    let n = dna.len() as f64;
    a * n + dna.iter().map(|g| g.value.powi(2) - a * (2.0 * std::f64::consts::PI * g.value).cos()).sum::<f64>()
};

let alleles = vec![RangeGenotype::new(0, vec![(-5.12, 5.12)], 0.0_f64)];
let alleles_clone = alleles.clone();

let mut ga = Ga::new()
    .with_genes_per_chromosome(5_usize)
    .with_population_size(100)
    .with_initialization_fn(move |genes_per_chromosome, _, _| {
        range_random_initialization(genes_per_chromosome, Some(&alleles_clone), Some(false))
    })
    .with_fitness_fn(fitness_fn)
    .with_selection_method(Selection::Tournament)
    .with_crossover_method(Crossover::Uniform)
    .with_mutation_method(Mutation::Gaussian)
    .with_survivor_method(Survivor::Fitness)
    .with_problem_solving(ProblemSolving::Minimization)
    .with_max_generations(500)
    .with_observer(Arc::new(CompositeObserver::new().add(Arc::new(LogObserver))))
    .build()
    .expect("Invalid configuration");

let population = ga.run().expect("GA run failed");
println!("Best fitness: {:.4}", population.best_chromosome.fitness);

Ergonomic Imports

Instead of multiple import lines, use the prelude for a single glob import:

use genetic_algorithms::prelude::*;
use genetic_algorithms::chromosomes::Range as RangeChromosome;
use genetic_algorithms::genotypes::Range as RangeGenotype;
use genetic_algorithms::initializers::range_random_initialization;

The prelude includes all engine entry points, configuration traits, operator enums, core traits, and error types. Concrete chromosome/genotype types and initializer functions are imported separately since they are problem-specific.

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 and all engine configuration structs.

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::Binary — chromosome built from Binary genes.
  • chromosomes::Range<T> — chromosome built from Range<T> genes.
  • chromosomes::ListChromosome<T> — chromosome built from List<T> genes.
  • chromosomes::ChromosomeLengthFixed(usize) or Variable { min, max } — controls length-changing operators.
  • gp::GpChromosome<N> — tree chromosome for Genetic Programming (see Genetic Programming).

Custom chromosomes can be added by implementing ChromosomeT.

Initializers

  • initializers::binary_random_initialization
  • initializers::range_random_initialization
  • initializers::list_random_initialization (with repetition)
  • initializers::list_random_initialization_without_repetitions (permutation problems)
  • initializers::generic_random_initialization (allele slice, optional unique IDs)
  • initializers::generic_random_initialization_without_repetitions

Operators

  • Selection: Random, RouletteWheel, StochasticUniversalSampling, Tournament, Rank, Boltzmann, Truncation, Clearing, Lexicase, EpsilonLexicase
  • Crossover: Cycle, MultiPoint, Uniform, SinglePoint, Order (OX), Pmx (Partially Mapped), Sbx (Simulated Binary), BlendAlpha (BLX-α), Arithmetic, Clone, Rejuvenate, EdgeRecombination, VariableLength(AlignmentStrategy) (for variable-length chromosomes), Undx, Spx, Pcx (multi-parent real-valued crossover via the RealValued marker trait)
  • Mutation: Swap, Inversion, Scramble, Value (Range), BitFlip (Binary), Creep (uniform perturbation), Gaussian (normal perturbation), Polynomial (NSGA-II style), NonUniform (decreasing magnitude), PermutationInsert (permutation move), Insertion (grow variable-length chromosome), Deletion (shrink variable-length chromosome), Cauchy, LevyFlight, Uniform, ListValue (List), Differential, SelfAdaptiveGaussian (log-normal sigma update, requires SelfAdaptive chromosome)
  • Survivor: Fitness (keep best), Age (prefer younger), MuPlusLambda (parents + offspring compete), MuCommaLambda (offspring only), DeterministicCrowding; parsimony pressure via with_length_penalty
  • Extension: Noop, MassExtinction, MassGenesis, MassDegeneration, MassDeduplication

Engines

Which engine should I use?

Start from your problem, not from the algorithm. Pick the first row that matches; the Description table below has the details.

Your problem Use Why
Real-valued, expensive/black-box, ≤ ~40 dims CmaEngine<U> Self-adapting covariance; strongest general real-valued optimizer. Add RestartStrategy::Ipop/Bipop if multimodal
Real-valued, fast to evaluate, want a swarm PsoEngine<U> Few parameters, quick convergence on smooth landscapes
Real-valued, rugged/multimodal, robust default DeEngine<U> Differential Evolution; JADE/L-SHADE self-tune the rates
Binary or categorical (feature selection, OneMax…) Ga<U> or EdaEngine<U> Ga for general use; EdaEngine (UMDA) when the variables are near-independent
Permutation (TSP, scheduling, routing) Ga<U> with UniqueChromosome<T> + Crossover::Ox/Pmx Permutation-safe genotype and operators; multiple groups → MultiUniqueChromosome<T>
Per-gene different bounds (heterogeneous reals) Ga<U> with MultiRangeChromosome<T> Each gene clamps to its own (lo, hi)
Evolving programs / symbolic expressions GpGa<N> Tree chromosomes, bloat control, ramped half-and-half init
2–3 objectives (trade-off front) Nsga2Ga<U> The standard, well-understood MOO baseline
4+ objectives (many-objective) Nsga3Ga<U> or MoeaDGa<U> Reference-point / decomposition based; NSGA-II degrades past 3
Multi-objective, want explicit hypervolume quality SmsEmoaGa<U> / IbeaGa<U> Indicator-driven selection
Large/structured population, premature-convergence concerns IslandGa<U>, CellularEngine<U>, or AlpsEngine<U> Migration / spatial / age-layering preserve diversity
Just need a local-search or exhaustive baseline HillClimbEngine<U> / PermutateEngine<U> Sanity-check baselines; Permutate only for tiny spaces

Anything RealGene-bound (CmaEngine, PsoEngine, real EdaEngine) needs a real-valued genotype such as RangeChromosome<f64> or MultiRangeChromosome<f64>.

Engine Module Objectives Description
Ga<U> ga Single Standard single-population GA with full operator support, adaptive mode, elitism, and extensions
IslandGa<U> island Single Island model with configurable migration topology, frequency, and migrant selection
DeEngine<U> de Single Differential Evolution — 5 mutation strategies + JADE/L-SHADE adaptive variants
CmaEngine<U> cma Single Covariance Matrix Adaptation Evolution Strategy (CMA-ES); Hansen-default formulas; RestartStrategy::Ipop / Bipop for multimodal landscapes
PsoEngine<U> pso Single Particle Swarm Optimization — configurable inertia (PsoInertia), topology (PsoTopology), absorbing boundary
EdaEngine<U> / EdaRealEngine<U> eda Single UMDA: Bernoulli model for binary problems, Gaussian model for continuous — no crossover/mutation
ScatterEngine<U> scatter Single Scatter Search with reference set diversification and combination methods
CellularEngine<U> cellular Single Cellular GA on a 2D toroidal grid with 4 neighborhood topologies
AlpsEngine<U> alps Single Age-Layered Population Structure with 3 age schemes and cross-layer mating
HillClimbEngine<U> hill_climb Single Local-search baseline strategy — Stochastic or SteepestAscent mode
PermutateEngine<U> permutate Single Exhaustive enumeration over a permutation space with a hard safety gate against combinatorial explosion
GpGa<N> gp Single Genetic Programming — tree chromosomes, subtree/point/hoist mutation, ramped half-and-half initialization
Nsga2Ga<U> nsga2 2+ NSGA-II — fast non-dominated sorting with crowding distance diversity
Nsga3Ga<U> nsga3 3+ NSGA-III — reference-point based selection for many-objective problems
MoeaDGa<U> moead 2+ MOEA/D — decomposition-based scalarization (Tchebycheff, PBI, weighted sum)
Spea2Ga<U> spea2 2+ SPEA2 — strength-Pareto archive with k-nearest density estimation
SmsEmoaGa<U> / IbeaGa<U> sms_emoa/ibea 2+ Hypervolume contribution / indicator-based MOEAs

Variable-Length Chromosomes

Set ChromosomeLength::Variable { min, max } on the mutation configuration to enable chromosomes whose length can change during evolution.

use genetic_algorithms::chromosomes::ChromosomeLength;
use genetic_algorithms::operations::Mutation;
use genetic_algorithms::traits::MutationConfig;

// Enable length-changing mutations (grow or shrink by 1 gene per application).
let mut ga = Ga::new()
    .with_mutation_method(Mutation::Insertion)          // grow by 1
    // or .with_mutation_method(Mutation::Deletion)     // shrink by 1
    .with_chromosome_length(ChromosomeLength::Variable { min: 2, max: 20 })
    // Optional: penalize longer chromosomes during survivor selection.
    .with_length_penalty(0.01)
    // ... rest of configuration
    .build()
    .expect("valid config");

For variable-length parents use Crossover::VariableLength(AlignmentStrategy):

use genetic_algorithms::operations::{Crossover, AlignmentStrategy};

// Trim both parents to min(len_a, len_b) before single-point crossover.
.with_crossover_method(Crossover::VariableLength(AlignmentStrategy::Trim))

// Pad the shorter parent (from its alleles) to max(len_a, len_b).
.with_crossover_method(Crossover::VariableLength(AlignmentStrategy::Pad))

Genetic Programming (GpGa)

GpGa<N> evolves tree-structured chromosomes (GpChromosome<N>). Implement GpNode on your own enum to define the function and terminal set.

use genetic_algorithms::gp::{GpConfiguration, GpGa, GpMutation, MathNode};

let config = GpConfiguration::new()
    .with_population_size(100)
    .with_max_generations(50)
    .with_init_max_depth(4)
    .with_max_depth(8)
    .with_max_node_count(200)
    .with_mutations(vec![
        (GpMutation::SubtreeMutation { mutation_max_depth: 4 }, 0.1),
        (GpMutation::PointMutation { p_per_node: 0.05 }, 0.1),
    ]);

// GpGa::with_ramped_half_and_half uses the built-in initializer automatically.
let mut engine = GpGa::<MathNode>::with_ramped_half_and_half(config, |tree| {
    // Evaluate the expression tree — return a fitness value.
    // Use Node::<MathNode>::eval_with_vars(tree, &[x0, x1]) for variable injection.
    0.0
});
let result = engine.run().unwrap();
println!("Best fitness: {}", result.best_fitness);
println!("Best program: {}", result.best); // Prints Lisp S-expression

Built-in primitive sets:

  • MathNodeAdd, Sub, Mul, ProtectedDiv, Const(f64) (ERC), Var(usize) — for symbolic regression.
  • BoolNodeAnd, Or, Not, Gt, Lt — for classification tree learning.

GP mutation operators:

Variant Description
GpMutation::SubtreeMutation { mutation_max_depth } Replaces a random subtree with a freshly grown random tree
GpMutation::PointMutation { p_per_node } Replaces each node's primitive with a same-arity alternative
GpMutation::HoistMutation Replaces a subtree with one of its own descendants (always shrinks)

Observer (GaObserver)

v3.0.0: the legacy Reporter<U> trait has been removed. Use GaObserver instead — see MIGRATION.md.

Attach a lifecycle observer via .with_observer(Arc::new(my_observer)). All hooks take &self — safe in rayon parallel regions. Zero overhead when no observer is attached (stored as Option<Arc<_>>).

Core trait: GaObserver<U>

Hook When it fires
on_run_start Before the first generation
on_generation_start At the start of each generation
on_selection_complete After parent selection
on_crossover_complete After crossover batch
on_mutation_complete After mutation batch
on_fitness_evaluation_complete After fitness re-evaluation
on_survivor_selection_complete After survivor selection
on_new_best When a new best chromosome is found
on_stagnation When no improvement for N generations
on_extension_triggered When diversity extension fires
on_restart When CmaEngine triggers an IPOP/BIPOP restart (RestartEvent)
on_generation_end End of each generation (with GenerationStats)
on_run_end After the last generation

Engine-specific sub-traits

  • IslandGaObserver<U> — additional hooks for island migration events; attach via island::IslandGa::with_observer.
  • Nsga2Observer<U> — additional hooks for NSGA-II pareto-front and crowding events; attach via nsga2::Nsga2::with_observer.
  • Nsga3Observer<U> — additional hooks for NSGA-III reference-point and normalization events.
  • MoeaDObserver<U> — additional hooks for MOEA/D subproblem and neighborhood updates.
  • Spea2Observer<U> — additional hooks for SPEA2 archive and fitness assignment events.
  • SmsEmoaObserver<U> — additional hooks for SMS-EMOA hypervolume contribution events.
  • IbeaObserver<U> — additional hooks for IBEA indicator-based fitness events.

Built-in observers

LogObserver — logs every hook via the log crate. No feature flags required. Implements GaObserver, IslandGaObserver, and Nsga2Observer.

use std::sync::Arc;
use genetic_algorithms::{ga::Ga, LogObserver};

let mut ga = Ga::new()
    /* ...configuration... */
    .with_observer(Arc::new(LogObserver))
    .build()
    .expect("Invalid configuration");

CompositeObserver<U> — fan-out observer that forwards all hooks to a list of inner observers.

use std::sync::Arc;
use genetic_algorithms::{ga::Ga, CompositeObserver, LogObserver};

let composite = CompositeObserver::new()
    .add(Arc::new(LogObserver));

let mut ga = Ga::new()
    /* ...configuration... */
    .with_observer(Arc::new(composite))
    .build()
    .expect("Invalid configuration");

MetricsObserver — emits metrics-crate gauges, counters, and histograms per generation. Requires observer-metrics feature.

Emitted metrics: ga.generation.best_fitness, ga.generation.mean_fitness, ga.generation.diversity, ga.operator.*_ms histograms, ga.event.new_best / ga.event.stagnation / ga.event.extension_triggered counters.

TracingObserver — emits tracing-crate spans and events. Requires observer-tracing feature.

NoopObserver — satisfies the GaObserver bound with no-op implementations. Useful for testing or disabling observers at compile time.

AllObserver — implements GaObserver, IslandGaObserver, and Nsga2Observer with blanket coverage, so a single observer type can be used across all engine types.

Custom observer

Implement GaObserver<U> on your own type. All hooks have default no-op implementations — only override what you need:

use genetic_algorithms::{GaObserver, stats::GenerationStats};

struct MyObserver;

impl<U: genetic_algorithms::traits::ChromosomeT> GaObserver<U> for MyObserver {
    fn on_generation_end(&self, stats: &GenerationStats) {
        println!("Gen {} best={:.4}", stats.generation, stats.best_fitness);
    }
}

Visualization

Requires the visualization feature. Three functions in genetic_algorithms::visualization:

// 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
let fitness: Vec<f64> = population.iter().map(|c| c.get_fitness()).collect();
visualization::plot_histogram(&fitness, "distribution.png")?;

Format is determined by path extension (.png or .svg). All functions return Result<(), VisualizationError>.

Multi-Objective Pareto Fronts

Algorithm Benchmark Plot
NSGA-II ZDT1 (2-obj) NSGA-II ZDT1 Pareto front
SPEA2 ZDT1 (2-obj) SPEA2 ZDT1 Pareto front
SMS-EMOA ZDT1 (2-obj) SMS-EMOA ZDT1 Pareto front
IBEA ZDT1 (2-obj) IBEA ZDT1 Pareto front
NSGA-III DTLZ2 (3-obj, three-panel) NSGA-III DTLZ2 Pareto front

Generate each plot by running the corresponding example with --plot, for example:

cargo run --example nsga2_zdt1 --features visualization -- --plot
cargo run --example sms_emoa_zdt1 --features "visualization,benchmarks" -- --plot

Single-Objective Fitness Progress

Rastrigin fitness over generations

Generated via:

cargo run --example rastrigin --features visualization -- --plot

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, blend_alpha, arithmetic_alpha.
  • Mutation: probability_min / probability_max, method, step (Creep), sigma (Gaussian), eta_m (Polynomial), non_uniform_b (NonUniform).
  • Survivor: survivor.
  • Elitism: elitism_count — preserve the top N individuals unchanged across generations.
  • Extension: configure via 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.

Adaptive GA

When adaptive_ga = true:

  • Crossover and mutation probabilities are recomputed per parent pair using relative fitness (f_max, f_avg).
  • Both probability_min and probability_max must be set 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 rayon parallelism.
  • Selection, crossover, mutation, and fitness evaluation are parallelized each generation.
  • Cow<[Gene]> prevents needless cloning of DNA vectors.
  • select_nth_unstable_by() used over full sort when finding top-k individuals.

Logging

The library emits structured log!() events (using the log facade) but does not install a logger. Install your own subscriber in main():

fn main() {
    env_logger::init(); // or: tracing_subscriber::fmt::init(), etc.

    let mut ga = Ga::new()
        // ... configure ...
        .build()
        .unwrap();
    ga.run().unwrap();
}

Control verbosity with RUST_LOG: RUST_LOG=genetic_algorithms=warn cargo run. The GA emits events on the ga_events, population_events, and related log targets.

Add env_logger to your project's [dev-dependencies] for examples and tests:

[dev-dependencies]
env_logger = "0.11"

WebAssembly

genetic_algorithms compiles for wasm32-unknown-unknown out of the box. No feature flags are required.

Setup

The repository ships a .cargo/config.toml that automatically applies the necessary rustflags when targeting WASM, so no manual configuration is needed beyond adding the dependency normally:

[dependencies]
genetic_algorithms = "3.0.0"

Build with wasm-pack or directly with Cargo:

# Check WASM compilation
cargo check --target wasm32-unknown-unknown

# Build with wasm-pack (typical frontend workflow)
wasm-pack build --target web

If you are pulling genetic_algorithms as a dependency inside a WASM crate (without inheriting this repo's .cargo/config.toml), add the following to your own .cargo/config.toml:

[target.wasm32-unknown-unknown]
rustflags = ["--cfg", "getrandom_backend=\"wasm_js\""]

This is required because getrandom 0.3 (a transitive dependency via rand) needs an explicit backend declaration for wasm32-unknown-unknown in addition to the wasm_js Cargo feature.

Note on GpGa: The GP engine is fully WASM-compatible. Fitness evaluation uses sequential iteration (iter_mut) instead of par_iter_mut on wasm32-unknown-unknown. Tree depth/size limits still apply.

Known limitations on WASM

Feature Behaviour
Parallelism (rayon) Disabled — all parallel iterators fall back to sequential. Population evaluation is single-threaded on WASM.
Observer timing Instant-based duration measurements are omitted (gated with #[cfg(not(target_arch = "wasm32"))]). Observer hooks still fire; only elapsed-time fields are absent.
max_duration_secs stopping criterion The wall-clock check is skipped on WASM. Use max_generations or fitness_target as stopping criteria instead.

Examples

Run any example directly with cargo run --example <name>:

Example Domain Command
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
nsga3_dtlz2 Many-objective (NSGA-III) cargo run --example nsga3_dtlz2
moead_dtlz2 Decomposition (MOEA/D) cargo run --example moead_dtlz2
spea2_zdt1 Strength Pareto (SPEA2) cargo run --example spea2_zdt1
sms_emoa_zdt1 Hypervolume-based (SMS-EMOA) cargo run --example sms_emoa_zdt1
ibea_zdt1 Indicator-based (IBEA) cargo run --example ibea_zdt1
aos_demo Adaptive operator selection cargo run --example aos_demo
constrained_g1 Constraint handling cargo run --example constrained_g1
hall_of_fame_demo Solution archive cargo run --example hall_of_fame_demo
memetic_rastrigin Memetic algorithm cargo run --example memetic_rastrigin
cma_es_rastrigin CMA-ES on Rastrigin cargo run --example cma_es_rastrigin
ipop_rastrigin CMA-ES + IPOP restarts cargo run --example ipop_rastrigin
pso_rastrigin Particle Swarm Optimization cargo run --example pso_rastrigin
eda_trap Estimation of Distribution (UMDA) cargo run --example eda_trap
surrogate_rastrigin Surrogate-assisted evaluation cargo run --example surrogate_rastrigin
de_rastrigin Differential Evolution (L-SHADE) cargo run --example de_rastrigin
scatter_search Scatter Search with local search cargo run --example scatter_search
cellular_ga Cellular GA (Moore neighborhood) cargo run --example cellular_ga
alps ALPS age-layered evolution cargo run --example alps
gp_symbolic_regression GP symbolic regression (MathNode) cargo run --example gp_symbolic_regression

Development

Prerequisites

  • Rust >= 1.81.0 (set in Cargo.toml rust-version)

Build

cargo build            # Debug build
cargo build --release  # Optimized release build

Run Tests

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 and are in benches/.

cargo bench                        # Run all benchmarks
cargo bench --bench crossover      # Run only crossover benchmarks
cargo bench --bench ga_run         # Run only GA run benchmarks
cargo bench --bench nsga2          # Run NSGA-II benchmarks
cargo bench --bench island_ga      # Run island model benchmarks
cargo bench --bench de             # Run Differential Evolution benchmarks
cargo bench --bench scatter        # Run Scatter Search benchmarks
cargo bench --bench alps           # Run ALPS benchmarks
cargo bench --bench cellular       # Run Cellular GA benchmarks
cargo bench --no-run               # Compile only (useful in CI)

Reports are generated in target/criterion/ and can be viewed in a browser.

Code Quality

cargo fmt --check   # Check formatting (no changes)
cargo fmt           # Auto-format
cargo clippy        # Run linter
cargo doc --no-deps # Generate documentation

See CONTRIBUTING.md for guidelines.

License

Apache-2.0. See LICENSE.

About

This library provides a simple framework to implement genetic algorithms (GA) with Rust.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors