optde_basic/
optde_basic.rs1use math_audio_optimisation::{
2 CallbackAction, Crossover, DEConfig, Mutation, PolishConfig, Strategy, differential_evolution,
3};
4use ndarray::Array1;
5use std::sync::Arc;
6
7fn main() {
8 let ackley = |x: &Array1<f64>| {
10 let x0 = x[0];
11 let x1 = x[1];
12 let s = 0.5 * (x0 * x0 + x1 * x1);
13 let c = 0.5
14 * ((2.0 * std::f64::consts::PI * x0).cos() + (2.0 * std::f64::consts::PI * x1).cos());
15 -20.0 * (-0.2 * s.sqrt()).exp() - c.exp() + 20.0 + std::f64::consts::E
16 };
17
18 let bounds = [(-5.0, 5.0), (-5.0, 5.0)];
19
20 let mut cfg = DEConfig {
21 maxiter: 300,
22 popsize: 20,
23 strategy: Strategy::Best1Bin,
24 crossover: Crossover::Exponential, mutation: Mutation::Range { min: 0.5, max: 1.0 }, recombination: 0.9,
27 seed: Some(42),
28 ..Default::default()
29 };
30
31 cfg.penalty_ineq.push((
34 Arc::new(|x: &Array1<f64>| x[0] * x[0] + x[1] * x[1] - 9.0),
35 1e3,
36 ));
37
38 let mut iter_log = 0usize;
40 cfg.callback = Some(Box::new(move |inter| {
41 if iter_log.is_multiple_of(25) {
42 eprintln!(
43 "iter {:4} best_f={:.6e} conv(stdE)={:.3e}",
44 inter.iter, inter.fun, inter.convergence
45 );
46 }
47 iter_log += 1;
48 if inter.convergence < 1e-6 {
49 CallbackAction::Stop
50 } else {
51 CallbackAction::Continue
52 }
53 }));
54
55 cfg.polish = Some(PolishConfig {
57 enabled: true,
58 algo: "neldermead".into(),
59 maxeval: 400,
60 });
61
62 let report = differential_evolution(&ackley, &bounds, cfg).expect("optimization failed");
63
64 println!(
65 "success={} message=\"{}\"\nbest f={:.6e}\nbest x={:?}",
66 report.success, report.message, report.fun, report.x
67 );
68}