use super::*;
pub(crate) fn batch_evaluate<U>(
evaluator: Arc<dyn crate::fitness::BatchFitnessEvaluator<U> + Send + Sync>,
cache_opt: Option<Arc<std::sync::Mutex<crate::fitness::cache::FitnessCache>>>,
pop: &mut [U],
) -> Result<(), GaError>
where
U: LinearChromosome + Clone,
U::Gene: Debug,
{
if pop.is_empty() {
return Ok(());
}
match cache_opt {
None => {
let values = evaluator.evaluate_batch(pop);
debug_assert_eq!(
values.len(),
pop.len(),
"evaluate_batch returned {} values for {} chromosomes (T-60-01)",
values.len(),
pop.len()
);
for (i, chromosome) in pop.iter_mut().enumerate() {
chromosome.set_fitness(values[i]);
}
}
Some(cache_handle) => {
let mut fitness_values: Vec<f64> = vec![0.0; pop.len()];
let mut miss_indices: Vec<usize> = Vec::new();
{
let mut cache = cache_handle.lock().map_err(|_| {
GaError::InternalError("fitness cache mutex poisoned".to_string())
})?;
for (i, chromosome) in pop.iter().enumerate() {
let key = crate::fitness::cache::hash_dna(chromosome.dna());
match cache.get(key) {
Some(f) => fitness_values[i] = f,
None => miss_indices.push(i),
}
}
}
if !miss_indices.is_empty() {
let miss_chromosomes: Vec<U> = miss_indices
.iter()
.map(|&orig_i| pop[orig_i].clone())
.collect();
let miss_values = evaluator.evaluate_batch(&miss_chromosomes);
debug_assert_eq!(
miss_values.len(),
miss_indices.len(),
"evaluate_batch returned {} values for {} miss chromosomes (T-60-01)",
miss_values.len(),
miss_indices.len()
);
{
let mut cache = cache_handle.lock().map_err(|_| {
GaError::InternalError("fitness cache mutex poisoned".to_string())
})?;
for (pos, &orig_i) in miss_indices.iter().enumerate() {
let f = miss_values[pos];
fitness_values[orig_i] = f;
let key = crate::fitness::cache::hash_dna(pop[orig_i].dna());
cache.put(key, f);
}
} }
for (i, chromosome) in pop.iter_mut().enumerate() {
chromosome.set_fitness(fitness_values[i]);
}
}
}
Ok(())
}