math_audio_test_functions/functions/
power_sum.rs1use ndarray::Array1;
4
5pub fn power_sum(x: &Array1<f64>) -> f64 {
9 let b = [8.0, 18.0, 44.0, 114.0]; let d = x.len().min(4);
11
12 let mut sum = 0.0;
13 for i in 1..=d {
14 let power_sum: f64 = x.iter().take(d).map(|&xj| xj.powf(i as f64)).sum();
15 sum += (power_sum - b[i - 1]).powi(2);
16 }
17 sum
18}
19#[cfg(test)]
20mod tests {
21 use super::*;
22
23 #[test]
24 fn test_power_sum_known_properties() {
25 use crate::{FunctionMetadata, get_function_metadata};
26 use ndarray::Array1;
27
28 let metadata = get_function_metadata();
30 let meta = metadata
31 .get("power_sum")
32 .expect("Function power_sum should have metadata");
33
34 for (minimum_coords, expected_value) in &meta.global_minima {
36 assert!(
37 minimum_coords.len() >= meta.bounds.len() || meta.bounds.len() == 1,
38 "Global minimum coordinates should match bounds dimensions"
39 );
40
41 for (i, &coord) in minimum_coords.iter().enumerate() {
42 if i < meta.bounds.len() {
43 let (lower, upper) = meta.bounds[i];
44 assert!(
45 coord >= lower && coord <= upper,
46 "Global minimum coordinate {} = {} should be within bounds [{} {}]",
47 i,
48 coord,
49 lower,
50 upper
51 );
52 }
53 }
54 }
55
56 let tolerance = 1e-6; for (minimum_coords, expected_value) in &meta.global_minima {
59 let x = Array1::from_vec(minimum_coords.clone());
60 let actual_value = power_sum(&x);
61
62 let error = (actual_value - expected_value).abs();
63 assert!(
64 error <= tolerance,
65 "Function value at global minimum {:?} should be {}, got {}, error: {}",
66 minimum_coords,
67 expected_value,
68 actual_value,
69 error
70 );
71 }
72
73 if !meta.global_minima.is_empty() {
75 let (first_minimum, _) = &meta.global_minima[0];
76 let x = Array1::from_vec(first_minimum.clone());
77 let result = power_sum(&x);
78
79 assert!(
80 result.is_finite(),
81 "Function should return finite values at global minimum"
82 );
83 assert!(
84 !result.is_nan(),
85 "Function should not return NaN at global minimum"
86 );
87 }
88 }
89}