genetic_algorithm 0.27.1

A genetic algorithm implementation
Documentation
use criterion::*;
use genetic_algorithm::chromosome::Chromosome;
use genetic_algorithm::fitness::placeholders::{
    CountTrue, CountTrueWithSleep, Countdown, CountdownNoisy, SumGenes,
};
use genetic_algorithm::fitness::Fitness;
use genetic_algorithm::genotype::{BinaryGenotype, Genotype, ListGenotype, RangeGenotype};
use genetic_algorithm::population::Population;
use rand::prelude::*;
use rand::rngs::SmallRng;
use thread_local::ThreadLocal;

pub fn placeholders_benchmark(c: &mut Criterion) {
    let mut group = c.benchmark_group("fitness-placeholders");

    group.bench_function("count_true", |b| {
        let genotype = BinaryGenotype::builder()
            .with_genes_size(1000)
            .build()
            .unwrap();
        let chromosome = Chromosome::new(vec![true; 1000]);
        let mut fitness = CountTrue;
        b.iter(|| fitness.calculate_for_chromosome(black_box(&chromosome), &genotype))
    });

    group.bench_function("sum_genes_with_precision", |b| {
        let genotype = RangeGenotype::builder()
            .with_genes_size(1000)
            .with_allele_range(0.0..=1.0)
            .build()
            .unwrap();
        let chromosome = Chromosome::new(vec![1.0; 1000]);
        let mut fitness = SumGenes::new_with_precision(1e-5);
        b.iter(|| fitness.calculate_for_chromosome(black_box(&chromosome), &genotype))
    });

    group.bench_function("sum_genes", |b| {
        let genotype = ListGenotype::builder()
            .with_genes_size(1000)
            .with_allele_list((0_u32..100_u32).collect())
            .build()
            .unwrap();
        let chromosome = Chromosome::<u32>::new(vec![1; 1000]);
        let mut fitness = SumGenes::new();
        b.iter(|| fitness.calculate_for_chromosome(black_box(&chromosome), &genotype))
    });

    group.bench_function("countdown", |b| {
        let genotype = ListGenotype::builder()
            .with_genes_size(1000)
            .with_allele_list((0_u32..100_u32).collect())
            .build()
            .unwrap();
        let chromosome = Chromosome::<u32>::new(vec![1; 1000]);
        let mut fitness = Countdown::new(usize::MAX);
        b.iter(|| fitness.calculate_for_chromosome(black_box(&chromosome), &genotype))
    });

    group.bench_function("countdown_with_noise", |b| {
        let genotype = ListGenotype::builder()
            .with_genes_size(1000)
            .with_allele_list((0_u32..100_u32).collect())
            .build()
            .unwrap();
        let chromosome = Chromosome::<u32>::new(vec![1; 1000]);
        let mut fitness = CountdownNoisy::new(usize::MAX - 10_000, 1000, 1..10_000);
        b.iter(|| fitness.calculate_for_chromosome(black_box(&chromosome), &genotype))
    });
}

pub fn multithreading_benchmark(c: &mut Criterion) {
    let mut group = c.benchmark_group("fitness-multithreading");

    let mut rng = SmallRng::from_entropy();
    let genotype = BinaryGenotype::builder()
        .with_genes_size(100)
        .build()
        .unwrap();

    let chromosomes = (0..100)
        .map(|_| Chromosome::new(genotype.random_genes_factory(&mut rng)))
        .collect();
    let population = Population::new(chromosomes, true);

    group.sample_size(30);
    group.bench_function("fitness-CountTrueWithSleep-single-threaded", |b| {
        let mut fitness = CountTrueWithSleep::new(1000, true);
        b.iter_batched(
            || population.clone(),
            |mut data| {
                fitness.call_for_population(&mut data, &genotype, None, None);
            },
            BatchSize::SmallInput,
        );
    });

    // reuse thread fitness for all runs (as in evolve loop)
    let fitness_thread_local = Some(ThreadLocal::new());
    group.sample_size(300);
    group.bench_function("fitness-CountTrueWithSleep-multi-threaded", |b| {
        let mut fitness = CountTrueWithSleep::new(1000, true);
        b.iter_batched(
            || population.clone(),
            |mut data| {
                fitness.call_for_population(
                    &mut data,
                    &genotype,
                    fitness_thread_local.as_ref(),
                    None,
                );
            },
            BatchSize::SmallInput,
        );
    });
}

criterion_group!(benches, placeholders_benchmark, multithreading_benchmark);
criterion_main!(benches);