Skip to main content

math_audio_test_functions/functions/
different_powers.rs

1//! Different Powers test function
2
3use ndarray::Array1;
4
5/// Different Powers function - unimodal with different scaling
6/// Global minimum: f(x) = 0 at x = (0, 0, ..., 0)
7/// Bounds: x_i in [-1, 1]
8pub fn different_powers(x: &Array1<f64>) -> f64 {
9    x.iter()
10        .enumerate()
11        .map(|(i, &xi)| xi.abs().powf((i + 2) as f64))
12        .sum()
13}
14#[cfg(test)]
15mod tests {
16    use super::*;
17
18    #[test]
19    fn test_different_powers_known_properties() {
20        use crate::{FunctionMetadata, get_function_metadata};
21        use ndarray::Array1;
22
23        // Get metadata for this function
24        let metadata = get_function_metadata();
25        let meta = metadata
26            .get("different_powers")
27            .expect("Function different_powers should have metadata");
28
29        // Test 1: Verify global minima are within bounds
30        for (minimum_coords, expected_value) in &meta.global_minima {
31            assert!(
32                minimum_coords.len() >= meta.bounds.len() || meta.bounds.len() == 1,
33                "Global minimum coordinates should match bounds dimensions"
34            );
35
36            for (i, &coord) in minimum_coords.iter().enumerate() {
37                if i < meta.bounds.len() {
38                    let (lower, upper) = meta.bounds[i];
39                    assert!(
40                        coord >= lower && coord <= upper,
41                        "Global minimum coordinate {} = {} should be within bounds [{} {}]",
42                        i,
43                        coord,
44                        lower,
45                        upper
46                    );
47                }
48            }
49        }
50
51        // Test 2: Verify function evaluates to expected values at global minima
52        let tolerance = 1e-6; // Reasonable tolerance for numerical precision
53        for (minimum_coords, expected_value) in &meta.global_minima {
54            let x = Array1::from_vec(minimum_coords.clone());
55            let actual_value = different_powers(&x);
56
57            let error = (actual_value - expected_value).abs();
58            assert!(
59                error <= tolerance,
60                "Function value at global minimum {:?} should be {}, got {}, error: {}",
61                minimum_coords,
62                expected_value,
63                actual_value,
64                error
65            );
66        }
67
68        // Test 3: Basic function properties
69        if !meta.global_minima.is_empty() {
70            let (first_minimum, _) = &meta.global_minima[0];
71            let x = Array1::from_vec(first_minimum.clone());
72            let result = different_powers(&x);
73
74            assert!(
75                result.is_finite(),
76                "Function should return finite values at global minimum"
77            );
78            assert!(
79                !result.is_nan(),
80                "Function should not return NaN at global minimum"
81            );
82        }
83    }
84}