Skip to main content

math_audio_differential_evolution/
metadata.rs

1//! Tests for metadata-driven optimization examples
2
3#[cfg(test)]
4mod tests {
5    use crate::{
6        differential_evolution, run_recorded_differential_evolution, DEConfig, DEConfigBuilder,
7        Mutation, Strategy,
8    };
9    use math_audio_test_functions::{get_function_bounds_2d, get_function_bounds_vec, rosenbrock};
10
11    /// Example test showing how to use metadata for bounds
12    #[test]
13    fn test_de_rosenbrock_with_metadata_bounds() {
14        // Use metadata bounds instead of hardcoded ones
15        let bounds = get_function_bounds_2d("rosenbrock", (-5.0, 5.0)); // fallback if not found
16
17        let mut config = DEConfig::default();
18        config.seed = Some(42);
19        config.maxiter = 500;
20        config.popsize = 40;
21        config.recombination = 0.9;
22        config.strategy = Strategy::RandToBest1Exp;
23
24        let result = differential_evolution(&rosenbrock, &bounds, config)
25            .expect("optimization should succeed");
26
27        // Rosenbrock function: Global minimum f(x) = 0 at x = (1, 1)
28        assert!(result.fun < 1e-3);
29
30        // Check that solution is close to expected optimum
31        assert!(
32            (result.x[0] - 1.0).abs() < 0.1,
33            "x[0] should be close to 1.0: {}",
34            result.x[0]
35        );
36        assert!(
37            (result.x[1] - 1.0).abs() < 0.1,
38            "x[1] should be close to 1.0: {}",
39            result.x[1]
40        );
41
42        println!("Used bounds: {:?}", bounds);
43        println!(
44            "Found solution: ({:.4}, {:.4}) with f = {:.6}",
45            result.x[0], result.x[1], result.fun
46        );
47    }
48
49    #[test]
50    fn test_de_rosenbrock_recorded_with_metadata() {
51        // Use metadata bounds for recorded optimization
52        let bounds = get_function_bounds_vec("rosenbrock", (-5.0, 5.0));
53        let config = DEConfigBuilder::new()
54            .seed(123)
55            .maxiter(500)
56            .popsize(40)
57            .strategy(Strategy::RandToBest1Exp)
58            .mutation(Mutation::Factor(0.7))
59            .recombination(0.9)
60            .build()
61            .expect("popsize must be >= 4");
62
63        // Run the recorded optimization (requires AUTOEQ_DIR to be set)
64        let result =
65            run_recorded_differential_evolution("rosenbrock_metadata", rosenbrock, &bounds, config);
66
67        match result {
68            Ok((report, _csv_path)) => {
69                assert!(report.fun < 1e-3);
70
71                // Check that solution is close to expected optimum (1, 1)
72                assert!(
73                    report.x[0] > 0.9 && report.x[0] < 1.1,
74                    "x[0] not close to 1: {}",
75                    report.x[0]
76                );
77                assert!(
78                    report.x[1] > 0.9 && report.x[1] < 1.1,
79                    "x[1] not close to 1: {}",
80                    report.x[1]
81                );
82
83                println!("Used bounds: {:?}", bounds);
84                println!(
85                    "Found solution: ({:.4}, {:.4}) with f = {:.6}",
86                    report.x[0], report.x[1], report.fun
87                );
88            }
89            Err(e) => {
90                panic!(
91                    "Test requires AUTOEQ_DIR to be set. Error: {}\nPlease run: export AUTOEQ_DIR=/path/to/autoeq",
92                    e
93                );
94            }
95        }
96    }
97}