metaheurustics/test_function/
beale.rs1use ndarray::Array1;
2use crate::algorithm::ObjectiveFunction;
3use crate::test_function::TestFunction;
4
5#[derive(Debug)]
9pub struct Beale;
10
11impl Beale {
12 pub fn new() -> Self {
14 Beale
15 }
16}
17
18impl ObjectiveFunction for Beale {
19 fn evaluate(&self, x: &Array1<f64>) -> f64 {
20 if x.len() != 2 {
21 panic!("Beale function is only defined for 2 dimensions");
22 }
23
24 let x1 = x[0];
25 let x2 = x[1];
26
27 let term1 = (1.5 - x1 + x1 * x2).powi(2);
28 let term2 = (2.25 - x1 + x1 * x2.powi(2)).powi(2);
29 let term3 = (2.625 - x1 + x1 * x2.powi(3)).powi(2);
30
31 term1 + term2 + term3
32 }
33
34 fn dimensions(&self) -> usize {
35 2
36 }
37
38 fn bounds(&self) -> (Vec<f64>, Vec<f64>) {
39 (vec![-4.5; 2], vec![4.5; 2])
40 }
41}
42
43impl TestFunction for Beale {
44 fn global_minimum(&self) -> f64 {
45 0.0
46 }
47
48 fn global_minimum_position(&self) -> Array1<f64> {
49 Array1::from_vec(vec![3.0, 0.5])
50 }
51
52 fn name(&self) -> &'static str {
53 "Beale"
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use approx::assert_abs_diff_eq;
61 use ndarray::Array1;
62
63 #[test]
64 fn test_beale_global_minimum() {
65 let beale = Beale::new();
66 let global_min_pos = beale.global_minimum_position();
67 let global_min = beale.evaluate(&global_min_pos);
68 assert_abs_diff_eq!(global_min, beale.global_minimum(), epsilon = 1e-6);
69 }
70
71 #[test]
72 fn test_beale_known_points() {
73 let beale = Beale::new();
74
75 let origin = Array1::zeros(2);
77 assert_abs_diff_eq!(beale.evaluate(&origin), 14.203125, epsilon = 1e-6);
78
79 let point1 = Array1::from_vec(vec![1.0, 1.0]);
81 assert_abs_diff_eq!(beale.evaluate(&point1), 14.203125, epsilon = 1e-6);
82
83 let point2 = Array1::from_vec(vec![2.0, 2.0]);
85 assert_abs_diff_eq!(beale.evaluate(&point2), 356.703125, epsilon = 1e-6);
86 }
87
88 #[test]
89 fn test_beale_bounds() {
90 let beale = Beale::new();
91 let (lower, upper) = beale.bounds();
92
93 assert_eq!(lower, vec![-4.5; 2]);
95 assert_eq!(upper, vec![4.5; 2]);
96
97 let lower_bound = Array1::from_vec(lower.clone());
99 let upper_bound = Array1::from_vec(upper.clone());
100
101 let _ = beale.evaluate(&lower_bound);
103 let _ = beale.evaluate(&upper_bound);
104 }
105
106 #[test]
107 fn test_beale_dimensions() {
108 let beale = Beale::new();
109 assert_eq!(beale.dimensions(), 2);
110 }
111
112 #[test]
113 #[should_panic(expected = "Beale function is only defined for 2 dimensions")]
114 fn test_beale_wrong_dimensions() {
115 let beale = Beale::new();
116 let wrong_dim = Array1::zeros(3);
117 beale.evaluate(&wrong_dim);
118 }
119
120 #[test]
121 fn test_beale_symmetry() {
122 let beale = Beale::new();
123 let point1 = Array1::from_vec(vec![1.0, 2.0]);
124 let point2 = Array1::from_vec(vec![1.0, -2.0]);
125
126 assert_ne!(beale.evaluate(&point1), beale.evaluate(&point2));
128 }
129}