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