1pub mod cmaes;
27pub mod dds;
28pub mod de;
29pub mod glue;
30pub mod lshade;
31pub mod lsrtde;
32pub mod nsga2;
33pub mod nsga3;
34pub mod parallel;
35pub mod pso;
36pub mod pt;
37pub mod sa;
38pub mod sce;
39
40pub use cmaes::CmaEs;
41pub use dds::Dds;
42pub use de::De;
43pub use glue::{Behavioral, Glue, GlueResult, GlueSample};
44pub use lshade::LShade;
45pub use lsrtde::LSrtde;
46pub use nsga2::NsgaII;
47pub use nsga3::NsgaIII;
48pub use parallel::ensemble;
49pub use pso::Pso;
50pub use pt::{ParallelTempering, TemperingResult};
51pub use sa::{Anneal, Sa, SaResult, Schedule};
52pub use sce::Sce;
53
54use crate::problem::{Bound, Problem};
55use crate::rng::Rng;
56use crate::solution::{Report, Solution, StopReason};
57use crate::termination::Termination;
58
59pub trait Optimizer: Sync {
65 fn optimize(&self, problem: &dyn Problem, term: &Termination) -> Report;
67
68 fn with_seed(&self, seed: u64) -> Self
70 where
71 Self: Sized;
72}
73
74#[derive(Debug, Clone, Copy)]
77pub enum Algorithm {
78 Dds(Dds),
79 Sce(Sce),
80 De(De),
81 LShade(LShade),
82 LSrtde(LSrtde),
83 Pso(Pso),
84 CmaEs(CmaEs),
85}
86
87impl Optimizer for Algorithm {
88 fn optimize(&self, problem: &dyn Problem, term: &Termination) -> Report {
90 match self {
91 Algorithm::Dds(c) => c.optimize(problem, term),
92 Algorithm::Sce(c) => c.optimize(problem, term),
93 Algorithm::De(c) => c.optimize(problem, term),
94 Algorithm::LShade(c) => c.optimize(problem, term),
95 Algorithm::LSrtde(c) => c.optimize(problem, term),
96 Algorithm::Pso(c) => c.optimize(problem, term),
97 Algorithm::CmaEs(c) => c.optimize(problem, term),
98 }
99 }
100
101 fn with_seed(&self, seed: u64) -> Self {
102 match self {
103 Algorithm::Dds(c) => Algorithm::Dds(c.with_seed(seed)),
104 Algorithm::Sce(c) => Algorithm::Sce(c.with_seed(seed)),
105 Algorithm::De(c) => Algorithm::De(c.with_seed(seed)),
106 Algorithm::LShade(c) => Algorithm::LShade(c.with_seed(seed)),
107 Algorithm::LSrtde(c) => Algorithm::LSrtde(c.with_seed(seed)),
108 Algorithm::Pso(c) => Algorithm::Pso(c.with_seed(seed)),
109 Algorithm::CmaEs(c) => Algorithm::CmaEs(c.with_seed(seed)),
110 }
111 }
112}
113
114pub(crate) fn sample(bounds: &[Bound], rng: &mut Rng) -> Vec<f64> {
116 bounds
117 .iter()
118 .map(|&(lo, hi)| rng.uniform_in(lo, hi))
119 .collect()
120}
121
122#[inline]
124pub(crate) fn clamp(x: f64, lo: f64, hi: f64) -> f64 {
125 x.max(lo).min(hi)
126}
127
128pub(crate) struct Evaluator<'a> {
131 problem: &'a dyn Problem,
132 term: &'a Termination,
133 pub evaluations: usize,
134 pub best: Solution,
135}
136
137impl<'a> Evaluator<'a> {
138 pub fn new(problem: &'a dyn Problem, term: &'a Termination, first: Solution) -> Self {
140 Evaluator {
141 problem,
142 term,
143 evaluations: 1,
144 best: first,
145 }
146 }
147
148 pub fn eval(&mut self, x: &[f64]) -> f64 {
151 let v = self.problem.objective(x);
152 self.evaluations += 1;
153 if v.is_finite() && v < self.best.value {
154 self.best = Solution {
155 x: x.to_vec(),
156 value: v,
157 };
158 }
159 v
160 }
161
162 #[inline]
164 pub fn done(&self) -> bool {
165 self.term
166 .reason(self.evaluations, self.best.value)
167 .is_some()
168 }
169
170 pub fn finish(self) -> Report {
172 let stop = self
173 .term
174 .reason(self.evaluations, self.best.value)
175 .unwrap_or(StopReason::BudgetExhausted);
176 Report {
177 solution: self.best,
178 stop,
179 evaluations: self.evaluations,
180 }
181 }
182}