pub mod cmaes;
pub mod dds;
pub mod de;
pub mod epsilon_lshade;
pub mod glue;
pub mod lshade;
pub mod lsrtde;
pub mod moead;
pub mod nsga2;
pub mod nsga3;
pub mod padds;
pub mod parallel;
pub mod pso;
pub mod pt;
pub mod sa;
pub mod sce;
pub mod sms_emoa;
pub use cmaes::{CmaEs, Restart, RestartCmaEs};
pub use dds::Dds;
pub use de::De;
pub use epsilon_lshade::EpsilonLShade;
pub use glue::{Behavioral, Glue, GlueResult, GlueSample};
pub use lshade::LShade;
pub use lsrtde::LSrtde;
pub use moead::Moead;
pub use nsga2::NsgaII;
pub use nsga3::NsgaIII;
pub use padds::{Padds, PaddsSelection};
pub use parallel::ensemble;
pub use pso::Pso;
pub use pt::{ParallelTempering, TemperingResult};
pub use sa::{Anneal, Sa, SaResult, Schedule};
pub use sce::Sce;
pub use sms_emoa::SmsEmoa;
use crate::problem::{Bound, Problem};
use crate::rng::Rng;
use crate::solution::{Report, Solution, StopReason};
use crate::termination::Termination;
pub trait Optimizer: Sync {
fn optimize(&self, problem: &dyn Problem, term: &Termination) -> Report;
fn with_seed(&self, seed: u64) -> Self
where
Self: Sized;
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum Algorithm {
Dds(Dds),
Sce(Sce),
De(De),
LShade(LShade),
LSrtde(LSrtde),
Pso(Pso),
CmaEs(CmaEs),
RestartCmaEs(RestartCmaEs),
}
impl Optimizer for Algorithm {
fn optimize(&self, problem: &dyn Problem, term: &Termination) -> Report {
match self {
Algorithm::Dds(c) => c.optimize(problem, term),
Algorithm::Sce(c) => c.optimize(problem, term),
Algorithm::De(c) => c.optimize(problem, term),
Algorithm::LShade(c) => c.optimize(problem, term),
Algorithm::LSrtde(c) => c.optimize(problem, term),
Algorithm::Pso(c) => c.optimize(problem, term),
Algorithm::CmaEs(c) => c.optimize(problem, term),
Algorithm::RestartCmaEs(c) => c.optimize(problem, term),
}
}
fn with_seed(&self, seed: u64) -> Self {
match self {
Algorithm::Dds(c) => Algorithm::Dds(c.with_seed(seed)),
Algorithm::Sce(c) => Algorithm::Sce(c.with_seed(seed)),
Algorithm::De(c) => Algorithm::De(c.with_seed(seed)),
Algorithm::LShade(c) => Algorithm::LShade(c.with_seed(seed)),
Algorithm::LSrtde(c) => Algorithm::LSrtde(c.with_seed(seed)),
Algorithm::Pso(c) => Algorithm::Pso(c.with_seed(seed)),
Algorithm::CmaEs(c) => Algorithm::CmaEs(c.with_seed(seed)),
Algorithm::RestartCmaEs(c) => Algorithm::RestartCmaEs(c.with_seed(seed)),
}
}
}
pub(crate) fn sample(bounds: &[Bound], rng: &mut Rng) -> Vec<f64> {
bounds
.iter()
.map(|&(lo, hi)| rng.uniform_in(lo, hi))
.collect()
}
#[inline]
pub(crate) fn clamp(x: f64, lo: f64, hi: f64) -> f64 {
x.max(lo).min(hi)
}
pub(crate) struct Evaluator<'a> {
problem: &'a dyn Problem,
term: &'a Termination,
pub evaluations: usize,
pub best: Solution,
}
impl<'a> Evaluator<'a> {
pub fn new(problem: &'a dyn Problem, term: &'a Termination, first: Solution) -> Self {
Evaluator {
problem,
term,
evaluations: 1,
best: first,
}
}
pub fn eval(&mut self, x: &[f64]) -> f64 {
let v = self.problem.objective(x);
self.evaluations += 1;
if v.is_finite() && v <= self.best.value {
self.best = Solution {
x: x.to_vec(),
value: v,
};
}
v
}
#[inline]
pub fn done(&self) -> bool {
self.term
.reason(self.evaluations, self.best.value)
.is_some()
}
pub fn finish(self) -> Report {
let stop = self
.term
.reason(self.evaluations, self.best.value)
.unwrap_or(StopReason::BudgetExhausted);
Report {
solution: self.best,
stop,
evaluations: self.evaluations,
}
}
}