use std::f64::consts::PI;
#[must_use]
pub fn sphere(x: &[f64]) -> f64 {
x.iter().map(|xi| xi * xi).sum()
}
#[must_use]
pub fn rosenbrock(x: &[f64]) -> f64 {
x.windows(2)
.map(|w| {
let a = w[1] - w[0] * w[0];
let b = 1.0 - w[0];
100.0 * a * a + b * b
})
.sum()
}
#[must_use]
pub fn rastrigin(x: &[f64]) -> f64 {
let n = x.len() as f64;
10.0 * n
+ x.iter()
.map(|xi| xi * xi - 10.0 * (2.0 * PI * xi).cos())
.sum::<f64>()
}
#[must_use]
pub fn ackley(x: &[f64]) -> f64 {
let n = x.len() as f64;
let sum_sq: f64 = x.iter().map(|xi| xi * xi).sum();
let sum_cos: f64 = x.iter().map(|xi| (2.0 * PI * xi).cos()).sum();
-20.0 * (-0.2 * (sum_sq / n).sqrt()).exp() - (sum_cos / n).exp() + 20.0 + std::f64::consts::E
}
#[must_use]
pub fn schwefel(x: &[f64]) -> f64 {
let n = x.len() as f64;
418.9829 * n - x.iter().map(|xi| xi * (xi.abs().sqrt()).sin()).sum::<f64>()
}
#[must_use]
pub fn griewank(x: &[f64]) -> f64 {
let sum: f64 = x.iter().map(|xi| xi * xi).sum::<f64>() / 4000.0;
let prod: f64 = x
.iter()
.enumerate()
.map(|(i, xi)| (xi / ((i + 1) as f64).sqrt()).cos())
.product();
sum - prod + 1.0
}
#[must_use]
pub fn levy(x: &[f64]) -> f64 {
let w: Vec<f64> = x.iter().map(|xi| 1.0 + (xi - 1.0) / 4.0).collect();
let n = w.len();
let term1 = (PI * w[0]).sin().powi(2);
let term2: f64 = w[..n - 1]
.iter()
.map(|wi| (wi - 1.0).powi(2) * (1.0 + 10.0 * (PI * wi + 1.0).sin().powi(2)))
.sum();
let term3 = (w[n - 1] - 1.0).powi(2) * (1.0 + (2.0 * PI * w[n - 1]).sin().powi(2));
term1 + term2 + term3
}
#[must_use]
pub fn michalewicz(x: &[f64]) -> f64 {
let m = 10.0;
-x.iter()
.enumerate()
.map(|(i, xi)| xi.sin() * ((i + 1) as f64 * xi * xi / PI).sin().powi(2 * m as i32))
.sum::<f64>()
}
#[must_use]
pub fn zakharov(x: &[f64]) -> f64 {
let sum1: f64 = x.iter().map(|xi| xi * xi).sum();
let sum2: f64 = x
.iter()
.enumerate()
.map(|(i, xi)| 0.5 * (i + 1) as f64 * xi)
.sum();
sum1 + sum2.powi(2) + sum2.powi(4)
}
#[must_use]
pub fn dixon_price(x: &[f64]) -> f64 {
let term1 = (x[0] - 1.0).powi(2);
let term2: f64 = x
.windows(2)
.enumerate()
.map(|(i, w)| (i + 2) as f64 * (2.0 * w[1] * w[1] - w[0]).powi(2))
.sum();
term1 + term2
}
#[derive(Debug, Clone)]
pub struct BenchmarkInfo {
pub name: &'static str,
pub id: u8,
pub multimodal: bool,
pub separable: bool,
pub bounds: (f64, f64),
pub optimum: f64,
}
#[must_use]
pub fn all_benchmarks() -> Vec<BenchmarkInfo> {
vec![
BenchmarkInfo {
name: "Sphere",
id: 1,
multimodal: false,
separable: true,
bounds: (-100.0, 100.0),
optimum: 0.0,
},
BenchmarkInfo {
name: "Rosenbrock",
id: 2,
multimodal: false,
separable: false,
bounds: (-30.0, 30.0),
optimum: 0.0,
},
BenchmarkInfo {
name: "Rastrigin",
id: 3,
multimodal: true,
separable: true,
bounds: (-5.12, 5.12),
optimum: 0.0,
},
BenchmarkInfo {
name: "Ackley",
id: 4,
multimodal: true,
separable: false,
bounds: (-32.0, 32.0),
optimum: 0.0,
},
BenchmarkInfo {
name: "Schwefel",
id: 5,
multimodal: true,
separable: true,
bounds: (-500.0, 500.0),
optimum: 0.0,
},
BenchmarkInfo {
name: "Griewank",
id: 6,
multimodal: true,
separable: false,
bounds: (-600.0, 600.0),
optimum: 0.0,
},
BenchmarkInfo {
name: "Levy",
id: 7,
multimodal: true,
separable: false,
bounds: (-10.0, 10.0),
optimum: 0.0,
},
BenchmarkInfo {
name: "Michalewicz",
id: 8,
multimodal: true,
separable: true,
bounds: (0.0, PI),
optimum: f64::NEG_INFINITY, },
BenchmarkInfo {
name: "Zakharov",
id: 9,
multimodal: false,
separable: false,
bounds: (-5.0, 10.0),
optimum: 0.0,
},
BenchmarkInfo {
name: "Dixon-Price",
id: 10,
multimodal: false,
separable: false,
bounds: (-10.0, 10.0),
optimum: 0.0,
},
]
}
#[cfg(test)]
#[path = "benchmarks_tests.rs"]
mod tests;