use crate::traits::{ChromosomeT, GeneT};
use rayon::prelude::*;
use std::borrow::Cow;
use std::sync::Arc;
pub type InitializationFn<G> = dyn Fn(usize, Option<&[G]>, Option<bool>) -> Vec<G> + Send + Sync;
pub type FitnessFn<G> = dyn Fn(&[G]) -> f64 + Send + Sync;
fn build_one_chromosome<U>(
genes_per_chromosome: usize,
alleles: Option<&[U::Gene]>,
alleles_flag: Option<bool>,
init_fn: &InitializationFn<U::Gene>,
fitness_fn: Option<&Arc<FitnessFn<U::Gene>>>,
age: usize,
) -> U
where
U: ChromosomeT,
U::Gene: GeneT,
{
let dna = init_fn(genes_per_chromosome, alleles, alleles_flag);
let mut chromosome = U::new();
chromosome.set_dna(Cow::Owned(dna));
if let Some(ff) = fitness_fn {
let ff_clone = Arc::clone(ff);
chromosome.set_fitness_fn(move |genes| ff_clone(genes));
chromosome.calculate_fitness();
}
chromosome.set_age(age);
chromosome
}
pub fn initialize_chromosomes<U>(
count: usize,
genes_per_chromosome: usize,
alleles: Option<&[U::Gene]>,
alleles_flag: Option<bool>,
init_fn: &Arc<InitializationFn<U::Gene>>,
fitness_fn: Option<&Arc<FitnessFn<U::Gene>>>,
age: usize,
) -> Vec<U>
where
U: ChromosomeT,
U::Gene: GeneT,
{
(0..count)
.map(|_| {
build_one_chromosome(
genes_per_chromosome,
alleles,
alleles_flag,
init_fn.as_ref(),
fitness_fn,
age,
)
})
.collect()
}
pub fn initialize_chromosomes_par<U>(
count: usize,
genes_per_chromosome: usize,
alleles: Option<&[U::Gene]>,
alleles_flag: Option<bool>,
init_fn: &Arc<InitializationFn<U::Gene>>,
fitness_fn: Option<&Arc<FitnessFn<U::Gene>>>,
age: usize,
) -> Vec<U>
where
U: ChromosomeT,
U::Gene: GeneT,
{
(0..count)
.into_par_iter()
.map(|_| {
build_one_chromosome(
genes_per_chromosome,
alleles,
alleles_flag,
init_fn.as_ref(),
fitness_fn,
age,
)
})
.collect()
}