Skip to main content

optde_parallel/
optde_parallel.rs

1use math_audio_optimisation::{
2    DEConfig, Mutation, ParallelConfig, Strategy, differential_evolution,
3};
4use ndarray::Array1;
5use std::time::Instant;
6
7fn main() {
8    // Rastrigin function with artificial compute delay to simulate expensive evaluations
9    let dimension = 10;
10    let rastrigin = move |x: &Array1<f64>| -> f64 {
11        // Add some compute-intensive work to make parallelization beneficial
12        let mut sum = 0.0;
13        for _ in 0..1000 {
14            for &xi in x.iter() {
15                sum += xi.sin().cos().exp().ln_1p();
16            }
17        }
18
19        // Actual Rastrigin function
20        let a = 10.0;
21        let n = x.len() as f64;
22        let result = a * n
23            + x.iter()
24                .map(|&xi| xi * xi - a * (2.0 * std::f64::consts::PI * xi).cos())
25                .sum::<f64>();
26        result + sum * 1e-10 // Add tiny contribution from expensive computation
27    };
28
29    let bounds: Vec<(f64, f64)> = vec![(-5.12, 5.12); dimension];
30
31    // Test sequential evaluation
32    println!("Testing Sequential Evaluation:");
33    let cfg_seq = DEConfig {
34        maxiter: 100,
35        popsize: 15,
36        strategy: Strategy::Best1Bin,
37        mutation: Mutation::Factor(0.8),
38        recombination: 0.9,
39        seed: Some(42),
40        disp: true,
41        ..Default::default() // parallel.enabled = false by default
42    };
43
44    let start_seq = Instant::now();
45    let report_seq =
46        differential_evolution(&rastrigin, &bounds, cfg_seq).expect("optimization failed");
47    let duration_seq = start_seq.elapsed();
48
49    println!("\nSequential Results:");
50    println!("  Success: {}", report_seq.success);
51    println!("  Best f: {:.6e}", report_seq.fun);
52    println!("  Iterations: {}", report_seq.nit);
53    println!("  Function evaluations: {}", report_seq.nfev);
54    println!("  Time: {:.3} seconds", duration_seq.as_secs_f64());
55
56    // Test parallel evaluation
57    println!("\n\nTesting Parallel Evaluation:");
58    let cfg_par = DEConfig {
59        maxiter: 100,
60        popsize: 15,
61        strategy: Strategy::Best1Bin,
62        mutation: Mutation::Factor(0.8),
63        recombination: 0.9,
64        seed: Some(42),
65        disp: true,
66        parallel: ParallelConfig {
67            enabled: true,
68            num_threads: None, // Use all available cores
69        },
70        ..Default::default()
71    };
72
73    let start_par = Instant::now();
74    let report_par =
75        differential_evolution(&rastrigin, &bounds, cfg_par).expect("optimization failed");
76    let duration_par = start_par.elapsed();
77
78    println!("\nParallel Results:");
79    println!("  Success: {}", report_par.success);
80    println!("  Best f: {:.6e}", report_par.fun);
81    println!("  Iterations: {}", report_par.nit);
82    println!("  Function evaluations: {}", report_par.nfev);
83    println!("  Time: {:.3} seconds", duration_par.as_secs_f64());
84
85    // Compare results
86    println!("\n\nComparison:");
87    println!(
88        "  Speedup: {:.2}x",
89        duration_seq.as_secs_f64() / duration_par.as_secs_f64()
90    );
91    println!(
92        "  Result difference: {:.6e}",
93        (report_seq.fun - report_par.fun).abs()
94    );
95
96    // Test with different thread counts
97    println!("\n\nTesting with different thread counts:");
98    for num_threads in [1, 2, 4, 8] {
99        let cfg_threads = DEConfig {
100            maxiter: 50,
101            popsize: 15,
102            strategy: Strategy::Best1Bin,
103            mutation: Mutation::Factor(0.8),
104            recombination: 0.9,
105            seed: Some(42),
106            disp: false,
107            parallel: ParallelConfig {
108                enabled: true,
109                num_threads: Some(num_threads),
110            },
111            ..Default::default()
112        };
113
114        let start = Instant::now();
115        let _ =
116            differential_evolution(&rastrigin, &bounds, cfg_threads).expect("optimization failed");
117        let duration = start.elapsed();
118
119        println!(
120            "  {} thread(s): {:.3} seconds",
121            num_threads,
122            duration.as_secs_f64()
123        );
124    }
125}