use ndarray::Array1;
pub fn hartman_6d(x: &Array1<f64>) -> f64 {
let a = [
[10.0, 3.0, 17.0, 3.5, 1.7, 8.0],
[0.05, 10.0, 17.0, 0.1, 8.0, 14.0],
[3.0, 3.5, 1.7, 10.0, 17.0, 8.0],
[17.0, 8.0, 0.05, 10.0, 0.1, 14.0],
];
let c = [1.0, 1.2, 3.0, 3.2];
let p = [
[0.1312, 0.1696, 0.5569, 0.0124, 0.8283, 0.5886],
[0.2329, 0.4135, 0.8307, 0.3736, 0.1004, 0.9991],
[0.2348, 0.1451, 0.3522, 0.2883, 0.3047, 0.6650],
[0.4047, 0.8828, 0.8732, 0.5743, 0.1091, 0.0381],
];
-c.iter()
.enumerate()
.map(|(i, &ci)| {
let inner_sum = a[i]
.iter()
.zip(p[i].iter())
.enumerate()
.map(|(j, (&aij, &pij))| aij * (x[j] - pij).powi(2))
.sum::<f64>();
ci * (-inner_sum).exp()
})
.sum::<f64>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_minimum_is_close_to_reference_value() {
let x = Array1::from(vec![
0.20169, 0.150011, 0.476874, 0.275332, 0.311652, 0.6573,
]);
let value = hartman_6d(&x);
assert!((value - -3.32237).abs() < 1e-4, "got {value}");
}
#[test]
fn finite_inside_unit_box() {
let x = Array1::from(vec![0.5; 6]);
assert!(hartman_6d(&x).is_finite());
}
}