Skip to content

Commit e81a49a

Browse files
committed
Fixed size input arrays in testfunctions (when necessary) and approx crate in tests
1 parent a0cfe16 commit e81a49a

25 files changed

+467
-297
lines changed

examples/observer/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ impl CostFunction for Himmelblau {
221221
type Output = f64;
222222

223223
fn cost(&self, param: &Self::Param) -> Result<Self::Output, Error> {
224-
Ok(himmelblau(param))
224+
Ok(himmelblau(&[param[0], param[1]]))
225225
}
226226
}
227227

examples/particleswarm/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl CostFunction for Himmelblau {
1616
type Output = f64;
1717

1818
fn cost(&self, param: &Self::Param) -> Result<Self::Output, Error> {
19-
Ok(himmelblau(param))
19+
Ok(himmelblau(&[param[0], param[1]]))
2020
}
2121
}
2222

examples/particleswarm_nalgebra/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl CostFunction for Himmelblau {
1717
type Output = f64;
1818

1919
fn cost(&self, param: &Self::Param) -> Result<Self::Output, Error> {
20-
Ok(himmelblau(param.data.as_vec()))
20+
Ok(himmelblau(&[param[0], param[1]]))
2121
}
2222
}
2323

tools/testfunctions/src/ackley.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ use std::iter::Sum;
3030
/// where `x_i \in [-32.768, 32.768]` and usually `a = 10`, `b = 0.2` and `c = 2*pi`
3131
///
3232
/// The global minimum is at `f(x_1, x_2, ..., x_n) = f(0, 0, ..., 0) = 0`.
33-
pub fn ackley<T: Float + FromPrimitive + Sum>(param: &[T]) -> T {
34-
ackley_param(
33+
pub fn ackley<T>(param: &[T]) -> T
34+
where
35+
T: Float + FromPrimitive + Sum,
36+
{
37+
ackley_abc(
3538
param,
3639
T::from_f64(20.0).unwrap(),
3740
T::from_f64(0.2).unwrap(),
@@ -42,7 +45,10 @@ pub fn ackley<T: Float + FromPrimitive + Sum>(param: &[T]) -> T {
4245
/// Ackley test function
4346
///
4447
/// The same as `ackley`; however, it allows to set the parameters a, b and c.
45-
pub fn ackley_param<T: Float + FromPrimitive + Sum>(param: &[T], a: T, b: T, c: T) -> T {
48+
pub fn ackley_abc<T>(param: &[T], a: T, b: T, c: T) -> T
49+
where
50+
T: Float + FromPrimitive + Sum,
51+
{
4652
let num1 = T::from_f64(1.0).unwrap();
4753
let n = T::from_usize(param.len()).unwrap();
4854
-a * (-b * ((num1 / n) * param.iter().map(|x| x.powi(2)).sum()).sqrt()).exp()
@@ -54,27 +60,31 @@ pub fn ackley_param<T: Float + FromPrimitive + Sum>(param: &[T], a: T, b: T, c:
5460
#[cfg(test)]
5561
mod tests {
5662
use super::*;
63+
use approx::assert_relative_eq;
5764
use std::{f32, f64};
5865

5966
#[test]
6067
fn test_ackley_optimum() {
6168
// There seem to be numerical problems which is why the epsilons are multiplied with a
6269
// factor. Not sure if this is acceptable...
63-
assert!(ackley(&[0.0_f32, 0.0_f32, 0.0_f32]).abs() < f32::EPSILON * 10_f32);
64-
assert!(ackley(&[0.0_f64, 0.0_f64, 0.0_f64]).abs() < f64::EPSILON * 3_f64);
70+
assert_relative_eq!(
71+
ackley(&[0.0_f32, 0.0_f32, 0.0_f32]),
72+
0.0,
73+
epsilon = f32::EPSILON * 10_f32
74+
);
75+
assert_relative_eq!(
76+
ackley(&[0.0_f64, 0.0_f64, 0.0_f64]),
77+
0.0,
78+
epsilon = f64::EPSILON * 3_f64
79+
);
6580
}
6681

6782
#[test]
6883
fn test_parameters() {
69-
assert!(
70-
ackley(&[0.0_f64, 0.0_f64, 0.0_f64]).abs()
71-
== ackley_param(
72-
&[0.0_f64, 0.0_f64, 0.0_f64],
73-
20.0,
74-
0.2,
75-
2.0 * f64::consts::PI
76-
)
77-
.abs()
84+
assert_relative_eq!(
85+
ackley(&[0.0_f64, 0.0_f64, 0.0_f64]),
86+
ackley_abc(&[0.0_f64, 0.0_f64, 0.0_f64], 20.0, 0.2, 2.0 * PI),
87+
epsilon = f64::EPSILON
7888
);
7989
}
8090
}

tools/testfunctions/src/beale.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ use num::{Float, FromPrimitive};
2828
/// where `x_i \in [-4.5, 4.5]`.
2929
///
3030
/// The global minimum is at `f(x_1, x_2) = f(3, 0.5) = 0`.
31-
pub fn beale<T: Float + FromPrimitive>(param: &[T]) -> T {
32-
assert!(param.len() == 2);
33-
let (x1, x2) = (param[0], param[1]);
31+
pub fn beale<T>(param: &[T; 2]) -> T
32+
where
33+
T: Float + FromPrimitive,
34+
{
35+
let [x1, x2] = *param;
3436
(T::from_f64(1.5).unwrap() - x1 + x1 * x2).powi(2)
3537
+ (T::from_f64(2.25).unwrap() - x1 + x1 * (x2.powi(2))).powi(2)
3638
+ (T::from_f64(2.625).unwrap() - x1 + x1 * (x2.powi(3))).powi(2)
@@ -39,17 +41,12 @@ pub fn beale<T: Float + FromPrimitive>(param: &[T]) -> T {
3941
#[cfg(test)]
4042
mod tests {
4143
use super::*;
44+
use approx::assert_relative_eq;
4245
use std::{f32, f64};
4346

4447
#[test]
4548
fn test_beale_optimum() {
46-
assert!(beale(&[3.0_f32, 0.5_f32]).abs() < f32::EPSILON);
47-
assert!(beale(&[3.0_f64, 0.5_f64]).abs() < f64::EPSILON);
48-
}
49-
50-
#[test]
51-
#[should_panic]
52-
fn test_beale_param_length() {
53-
beale(&[0.0_f32, -1.0_f32, 0.1_f32]);
49+
assert_relative_eq!(beale(&[3.0_f32, 0.5_f32]), 0.0, epsilon = f32::EPSILON);
50+
assert_relative_eq!(beale(&[3.0_f64, 0.5_f64]), 0.0, epsilon = f64::EPSILON);
5451
}
5552
}

tools/testfunctions/src/booth.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,24 @@ use num::{Float, FromPrimitive};
2626
/// where `x_i \in [-10, 10]`.
2727
///
2828
/// The global minimum is at `f(x_1, x_2) = f(1, 3) = 0`.
29-
pub fn booth<T: Float + FromPrimitive>(param: &[T]) -> T {
30-
assert!(param.len() == 2);
31-
let (x1, x2) = (param[0], param[1]);
29+
pub fn booth<T>(param: &[T; 2]) -> T
30+
where
31+
T: Float + FromPrimitive,
32+
{
33+
let [x1, x2] = *param;
3234
(x1 + T::from_f64(2.0).unwrap() * x2 - T::from_f64(7.0).unwrap()).powi(2)
3335
+ (T::from_f64(2.0).unwrap() * x1 + x2 - T::from_f64(5.0).unwrap()).powi(2)
3436
}
3537

3638
#[cfg(test)]
3739
mod tests {
3840
use super::*;
41+
use approx::assert_relative_eq;
3942
use std::{f32, f64};
4043

4144
#[test]
4245
fn test_booth_optimum() {
43-
assert!((booth(&[1_f32, 3_f32])).abs() < f32::EPSILON);
44-
assert!((booth(&[1_f64, 3_f64])).abs() < f64::EPSILON);
45-
}
46-
47-
#[test]
48-
#[should_panic]
49-
fn test_booth_param_length() {
50-
booth(&[0.0_f32, -1.0_f32, 0.1_f32]);
46+
assert_relative_eq!(booth(&[1_f32, 3_f32]), 0.0, epsilon = f32::EPSILON);
47+
assert_relative_eq!(booth(&[1_f64, 3_f64]), 0.0, epsilon = f64::EPSILON);
5148
}
5249
}

tools/testfunctions/src/bukin.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,26 @@ use num::{Float, FromPrimitive};
2626
/// where `x_1 \in [-15, -5]` and `x_2 \in [-3, 3]`.
2727
///
2828
/// The global minimum is at `f(x_1, x_2) = f(-10, 1) = 0`.
29-
pub fn bukin_n6<T: Float + FromPrimitive>(param: &[T]) -> T {
30-
assert!(param.len() == 2);
31-
let (x1, x2) = (param[0], param[1]);
32-
T::from_f64(100.0).unwrap() * (x2 - T::from_f64(0.01).unwrap() * x1.powi(2)).abs().sqrt()
33-
+ T::from_f64(0.01).unwrap() * (x1 + T::from_f64(10.0).unwrap()).abs()
29+
pub fn bukin_n6<T>(param: &[T; 2]) -> T
30+
where
31+
T: Float + FromPrimitive,
32+
{
33+
let [x1, x2] = *param;
34+
let n001 = T::from_f64(0.01).unwrap();
35+
let n10 = T::from_f64(10.0).unwrap();
36+
let n100 = T::from_f64(100.0).unwrap();
37+
n100 * (x2 - n001 * x1.powi(2)).abs().sqrt() + n001 * (x1 + n10).abs()
3438
}
3539

3640
#[cfg(test)]
3741
mod tests {
3842
use super::*;
43+
use approx::assert_relative_eq;
3944
use std::{f32, f64};
4045

4146
#[test]
4247
fn test_bukin_n6_optimum() {
43-
assert!((bukin_n6(&[-10_f32, 1_f32])).abs() < f32::EPSILON);
44-
assert!((bukin_n6(&[-10_f64, 1_f64])).abs() < f64::EPSILON);
45-
}
46-
47-
#[test]
48-
#[should_panic]
49-
fn test_bukin_n6_param_length() {
50-
bukin_n6(&[0.0_f32, -1.0_f32, 0.1_f32]);
48+
assert_relative_eq!(bukin_n6(&[-10_f32, 1_f32]), 0.0, epsilon = f32::EPSILON);
49+
assert_relative_eq!(bukin_n6(&[-10_f64, 1_f64]), 0.0, epsilon = f64::EPSILON);
5150
}
5251
}

tools/testfunctions/src/crossintray.rs

+55-31
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
2323
use std::f64::consts::PI;
2424

25+
use num::{Float, FromPrimitive};
26+
2527
/// Cross-in-tray test function
2628
///
2729
/// Defined as
@@ -36,52 +38,74 @@ use std::f64::consts::PI;
3638
/// * `f(x_1, x_2) = f(1.34941, -1.34941) = -2.06261`.
3739
/// * `f(x_1, x_2) = f(-1.34941, 1.34941) = -2.06261`.
3840
/// * `f(x_1, x_2) = f(-1.34941, -1.34941) = -2.06261`.
39-
pub fn cross_in_tray(param: &[f64]) -> f64 {
40-
assert!(param.len() == 2);
41-
let (x1, x2) = (param[0], param[1]);
42-
// let pi = T::from_f64(PI).unwrap();
43-
// T::from_f64(-0.0001).unwrap()
44-
// * ((x1.sin() * x2.sin()
45-
// * (T::from_f64(100.0).unwrap() - (x1.powi(2) + x2.powi(2)).sqrt() / pi)
46-
// .abs()
47-
// .exp())
48-
// .abs() + T::from_f64(1.0).unwrap())
49-
// .powf(T::from_f64(0.1).unwrap())
50-
-0.0001
51-
* ((x1.sin() * x2.sin() * (100.0 - (x1.powi(2) + x2.powi(2)).sqrt() / PI).abs().exp())
52-
.abs()
53-
+ 1.0)
54-
.powf(0.1)
41+
///
42+
/// Note: Even if the input parameters are f32, internal computations will be performed in f64.
43+
pub fn cross_in_tray<T>(param: &[T; 2]) -> T
44+
where
45+
T: Float + Into<f64> + FromPrimitive,
46+
{
47+
let x1: f64 = param[0].into();
48+
let x2: f64 = param[1].into();
49+
T::from_f64(
50+
-0.0001
51+
* ((x1.sin() * x2.sin() * (100.0 - (x1.powi(2) + x2.powi(2)).sqrt() / PI).abs().exp())
52+
.abs()
53+
+ 1.0)
54+
.powf(0.1),
55+
)
56+
.unwrap()
5557
}
5658

5759
#[cfg(test)]
5860
mod tests {
5961
use super::*;
62+
use approx::assert_relative_eq;
6063
use std::f32;
6164

6265
#[test]
6366
fn test_cross_in_tray_optimum() {
6467
// This isnt exactly a great way to test this. The function can only be computed with the
6568
// use of f64; however, I only have the minimum points available in f32, which is why I use
6669
// the f32 EPSILONs.
67-
assert!(
68-
(cross_in_tray(&[1.34941_f64, 1.34941_f64]) + 2.062611870).abs() < f32::EPSILON.into()
70+
assert_relative_eq!(
71+
cross_in_tray(&[1.34941_f64, 1.34941_f64]),
72+
-2.062611870,
73+
epsilon = f32::EPSILON.into()
6974
);
70-
assert!(
71-
(cross_in_tray(&[1.34941_f64, -1.34941_f64]) + 2.062611870).abs() < f32::EPSILON.into()
75+
assert_relative_eq!(
76+
cross_in_tray(&[1.34941_f64, -1.34941_f64]),
77+
-2.062611870,
78+
epsilon = f32::EPSILON.into()
7279
);
73-
assert!(
74-
(cross_in_tray(&[-1.34941_f64, 1.34941_f64]) + 2.062611870).abs() < f32::EPSILON.into()
80+
assert_relative_eq!(
81+
cross_in_tray(&[-1.34941_f64, 1.34941_f64]),
82+
-2.062611870,
83+
epsilon = f32::EPSILON.into()
7584
);
76-
assert!(
77-
(cross_in_tray(&[-1.34941_f64, -1.34941_f64]) + 2.062611870).abs()
78-
< f32::EPSILON.into()
85+
assert_relative_eq!(
86+
cross_in_tray(&[-1.34941_f64, -1.34941_f64]),
87+
-2.062611870,
88+
epsilon = f32::EPSILON.into()
89+
);
90+
assert_relative_eq!(
91+
cross_in_tray(&[1.34941_f32, 1.34941_f32]),
92+
-2.062611870,
93+
epsilon = f32::EPSILON.into()
94+
);
95+
assert_relative_eq!(
96+
cross_in_tray(&[1.34941_f32, -1.34941_f32]),
97+
-2.062611870,
98+
epsilon = f32::EPSILON.into()
99+
);
100+
assert_relative_eq!(
101+
cross_in_tray(&[-1.34941_f32, 1.34941_f32]),
102+
-2.062611870,
103+
epsilon = f32::EPSILON.into()
104+
);
105+
assert_relative_eq!(
106+
cross_in_tray(&[-1.34941_f32, -1.34941_f32]),
107+
-2.062611870,
108+
epsilon = f32::EPSILON.into()
79109
);
80-
}
81-
82-
#[test]
83-
#[should_panic]
84-
fn test_cross_in_tray_param_length() {
85-
cross_in_tray(&[0.0, -1.0, 0.1]);
86110
}
87111
}

tools/testfunctions/src/easom.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,24 @@ use std::f64::consts::PI;
2727
/// where `x_i \in [-100, 100]`.
2828
///
2929
/// The global minimum is at `f(x_1, x_2) = f(pi, pi) = -1`.
30-
pub fn easom<T: Float + FromPrimitive>(param: &[T]) -> T {
31-
assert!(param.len() == 2);
32-
let (x1, x2) = (param[0], param[1]);
30+
pub fn easom<T>(param: &[T; 2]) -> T
31+
where
32+
T: Float + FromPrimitive,
33+
{
34+
let [x1, x2] = *param;
3335
let pi = T::from_f64(PI).unwrap();
3436
-x1.cos() * x2.cos() * (-(x1 - pi).powi(2) - (x2 - pi).powi(2)).exp()
3537
}
3638

3739
#[cfg(test)]
3840
mod tests {
3941
use super::*;
40-
use std::{f32, f64};
42+
use approx::assert_relative_eq;
43+
use std::{f32, f32::consts::PI as PI32, f64, f64::consts::PI as PI64};
4144

4245
#[test]
4346
fn test_easom_optimum() {
44-
assert!((easom(&[f32::consts::PI, f32::consts::PI]) + 1.0_f32).abs() < f32::EPSILON);
45-
assert!((easom(&[f64::consts::PI, f64::consts::PI]) + 1.0_f64).abs() < f64::EPSILON);
46-
}
47-
48-
#[test]
49-
#[should_panic]
50-
fn test_easom_param_length() {
51-
easom(&[0.0_f32, -1.0_f32, 0.1_f32]);
47+
assert_relative_eq!(easom(&[PI32, PI32]), -1.0_f32, epsilon = f32::EPSILON);
48+
assert_relative_eq!(easom(&[PI64, PI64]), -1.0_f64, epsilon = f64::EPSILON);
5249
}
5350
}

0 commit comments

Comments
 (0)