turboswarm_core/benchmarks/
functions.rs1#[derive(Debug, Clone)]
5pub struct Benchmark {
6 pub name: &'static str,
8 pub bound: f64,
10 pub optimum_value: f64,
12}
13
14pub fn sphere(x: &[f64]) -> f64 {
16 x.iter().map(|&xi| xi * xi).sum()
17}
18
19pub fn rastrigin(x: &[f64]) -> f64 {
22 let n = x.len() as f64;
23 10.0 * n
24 + x.iter()
25 .map(|&xi| xi * xi - 10.0 * (2.0 * std::f64::consts::PI * xi).cos())
26 .sum::<f64>()
27}
28
29pub fn rosenbrock(x: &[f64]) -> f64 {
32 x.windows(2)
33 .map(|w| {
34 let (xi, xj) = (w[0], w[1]);
35 100.0 * (xj - xi * xi).powi(2) + (1.0 - xi).powi(2)
36 })
37 .sum()
38}
39
40pub fn ackley(x: &[f64]) -> f64 {
44 let n = x.len() as f64;
45 let sum_sq: f64 = x.iter().map(|&xi| xi * xi).sum();
46 let sum_cos: f64 = x
47 .iter()
48 .map(|&xi| (2.0 * std::f64::consts::PI * xi).cos())
49 .sum();
50 -20.0 * (-0.2 * (sum_sq / n).sqrt()).exp() - (sum_cos / n).exp() + 20.0 + std::f64::consts::E
51}
52
53pub fn griewank(x: &[f64]) -> f64 {
57 let sum: f64 = x.iter().map(|&xi| xi * xi).sum::<f64>() / 4000.0;
58 let prod: f64 = x
59 .iter()
60 .enumerate()
61 .map(|(i, &xi)| (xi / ((i + 1) as f64).sqrt()).cos())
62 .product();
63 1.0 + sum - prod
64}
65
66pub fn schwefel(x: &[f64]) -> f64 {
71 let n = x.len() as f64;
72 418.982_887_272_433_8 * n - x.iter().map(|&xi| xi * xi.abs().sqrt().sin()).sum::<f64>()
73}
74
75pub fn bent_cigar(x: &[f64]) -> f64 {
87 if x.is_empty() {
88 return 0.0;
89 }
90 x[0] * x[0] + 1e6 * x[1..].iter().map(|&xi| xi * xi).sum::<f64>()
91}
92
93pub fn discus(x: &[f64]) -> f64 {
97 if x.is_empty() {
98 return 0.0;
99 }
100 1e6 * x[0] * x[0] + x[1..].iter().map(|&xi| xi * xi).sum::<f64>()
101}
102
103pub fn elliptic(x: &[f64]) -> f64 {
107 let n = x.len();
108 if n <= 1 {
109 return x.first().map_or(0.0, |&v| v * v);
110 }
111 x.iter()
112 .enumerate()
113 .map(|(i, &xi)| 1e6_f64.powf(i as f64 / (n - 1) as f64) * xi * xi)
114 .sum()
115}
116
117pub fn zakharov(x: &[f64]) -> f64 {
121 let sum_sq: f64 = x.iter().map(|&xi| xi * xi).sum();
122 let sum_half: f64 = x
123 .iter()
124 .enumerate()
125 .map(|(i, &xi)| 0.5 * (i + 1) as f64 * xi)
126 .sum();
127 sum_sq + sum_half.powi(2) + sum_half.powi(4)
128}
129
130pub fn levy(x: &[f64]) -> f64 {
133 if x.is_empty() {
134 return 0.0;
135 }
136 let pi = std::f64::consts::PI;
137 let w: Vec<f64> = x.iter().map(|&xi| 1.0 + (xi - 1.0) / 4.0).collect();
138 let n = w.len();
139 let term1 = (pi * w[0]).sin().powi(2);
140 let term_mid: f64 = w[..n - 1]
141 .iter()
142 .map(|&wi| (wi - 1.0).powi(2) * (1.0 + 10.0 * (pi * wi + 1.0).sin().powi(2)))
143 .sum();
144 let term_last = (w[n - 1] - 1.0).powi(2) * (1.0 + (2.0 * pi * w[n - 1]).sin().powi(2));
145 term1 + term_mid + term_last
146}
147
148pub fn expanded_schaffer(x: &[f64]) -> f64 {
152 fn g(a: f64, b: f64) -> f64 {
153 let s = a * a + b * b;
154 0.5 + (s.sqrt().sin().powi(2) - 0.5) / (1.0 + 0.001 * s).powi(2)
155 }
156 let n = x.len();
157 if n == 0 {
158 return 0.0;
159 }
160 if n == 1 {
161 return g(x[0], x[0]);
162 }
163 (0..n).map(|i| g(x[i], x[(i + 1) % n])).sum()
164}
165
166pub const SPHERE: Benchmark = Benchmark {
168 name: "sphere",
169 bound: 5.12,
170 optimum_value: 0.0,
171};
172pub const RASTRIGIN: Benchmark = Benchmark {
173 name: "rastrigin",
174 bound: 5.12,
175 optimum_value: 0.0,
176};
177pub const ROSENBROCK: Benchmark = Benchmark {
178 name: "rosenbrock",
179 bound: 2.048,
180 optimum_value: 0.0,
181};
182
183pub const ACKLEY: Benchmark = Benchmark {
185 name: "ackley",
186 bound: 32.768,
187 optimum_value: 0.0,
188};
189pub const GRIEWANK: Benchmark = Benchmark {
190 name: "griewank",
191 bound: 600.0,
192 optimum_value: 0.0,
193};
194pub const SCHWEFEL: Benchmark = Benchmark {
195 name: "schwefel",
196 bound: 500.0,
197 optimum_value: 0.0,
198};
199
200pub const BENT_CIGAR: Benchmark = Benchmark {
202 name: "bent_cigar",
203 bound: 100.0,
204 optimum_value: 0.0,
205};
206pub const DISCUS: Benchmark = Benchmark {
207 name: "discus",
208 bound: 100.0,
209 optimum_value: 0.0,
210};
211pub const ELLIPTIC: Benchmark = Benchmark {
212 name: "elliptic",
213 bound: 100.0,
214 optimum_value: 0.0,
215};
216pub const ZAKHAROV: Benchmark = Benchmark {
217 name: "zakharov",
218 bound: 10.0,
219 optimum_value: 0.0,
220};
221pub const LEVY: Benchmark = Benchmark {
222 name: "levy",
223 bound: 10.0,
224 optimum_value: 0.0,
225};
226pub const EXPANDED_SCHAFFER: Benchmark = Benchmark {
227 name: "expanded_schaffer",
228 bound: 100.0,
229 optimum_value: 0.0,
230};
231
232pub const ALL: &[Benchmark] = &[
236 SPHERE,
237 RASTRIGIN,
238 ROSENBROCK,
239 ACKLEY,
240 GRIEWANK,
241 SCHWEFEL,
242 BENT_CIGAR,
243 DISCUS,
244 ELLIPTIC,
245 ZAKHAROV,
246 LEVY,
247 EXPANDED_SCHAFFER,
248];
249
250pub fn meta(name: &str) -> Option<&'static Benchmark> {
252 ALL.iter().find(|b| b.name == name)
253}