Skip to main content

math_audio_test_functions/functions/
perm_d_beta.rs

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