use crate::evolution::{Chromosome, GenePool};
use crate::types::{Budget, EvolutionError, OracleVerdict, SearchStats};
use rand::rngs::StdRng;
use std::cmp::Ordering;
#[derive(Debug, Clone)]
pub struct EvalCandidate {
pub id: u64,
pub chromosome: Chromosome,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SubmitResult {
Accepted,
UnknownIds(usize),
}
pub trait SearchAlgorithm: Send + Sync + std::fmt::Debug {
fn name(&self) -> &'static str;
fn initialize(&mut self, population: Vec<Chromosome>, gene_pool: &GenePool, rng: &mut StdRng);
fn request_evaluations(&mut self, n: usize, rng: &mut StdRng) -> Vec<EvalCandidate>;
fn submit_evaluations(&mut self, results: Vec<(u64, OracleVerdict)>);
fn should_terminate(&self, stats: &SearchStats, budget: &Budget) -> bool;
fn best(&self) -> Option<&Chromosome>;
fn checkpoint(&self) -> Result<Vec<u8>, EvolutionError>;
fn restore(&mut self, bytes: &[u8]) -> Result<(), EvolutionError>;
fn population_snapshot(&self) -> Vec<Chromosome> {
self.best().cloned().into_iter().collect()
}
fn clone_box(&self) -> Box<dyn SearchAlgorithm>;
}
#[must_use]
pub(crate) fn comparable_fitness(value: f64) -> f64 {
if value.is_finite() {
value
} else {
f64::NEG_INFINITY
}
}
#[must_use]
pub(crate) fn fitness_cmp(a: f64, b: f64) -> Ordering {
comparable_fitness(a)
.partial_cmp(&comparable_fitness(b))
.unwrap_or(Ordering::Equal)
}
pub mod hill_climb;
pub mod map_elites;
pub mod novelty;
pub mod sim_anneal;
pub mod tabu;
pub use hill_climb::HillClimbing;
pub use map_elites::MapElites;
pub use novelty::NoveltySearch;
pub use sim_anneal::SimulatedAnnealing;
pub use tabu::TabuSearch;