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