Skip to main content

optde_linear_constraints/
optde_linear_constraints.rs

1use math_audio_optimisation::{
2    Crossover, DEConfigBuilder, LinearConstraintHelper, Mutation, Strategy, differential_evolution,
3};
4use ndarray::{Array1, Array2};
5use std::str::FromStr;
6
7fn main() {
8    // Objective: sphere in 2D
9    let sphere = |x: &Array1<f64>| x.iter().map(|v| v * v).sum::<f64>();
10
11    // Bounds
12    let bounds = [(-5.0, 5.0), (-5.0, 5.0)];
13
14    // Linear constraint example: lb <= A x <= ub
15    // 1) x0 + x1 <= 1.0
16    // 2) 0.2 <= x0 - x1 <= 0.4
17    let a = Array2::from_shape_vec((2, 2), vec![1.0, 1.0, 1.0, -1.0]).unwrap();
18    let lb = Array1::from(vec![-f64::INFINITY, 0.2]);
19    let ub = Array1::from(vec![1.0, 0.4]);
20    let lc = LinearConstraintHelper { a, lb, ub };
21
22    // Strategy parsing from string (mirrors SciPy names)
23    let strategy = Strategy::from_str("randtobest1exp").unwrap_or(Strategy::RandToBest1Exp);
24
25    // Build config using the fluent builder
26    let mut cfg = DEConfigBuilder::new()
27        .seed(123)
28        .maxiter(600)
29        .popsize(30)
30        .strategy(strategy)
31        .recombination(0.9)
32        .mutation(Mutation::Range { min: 0.4, max: 1.0 })
33        .crossover(Crossover::Exponential)
34        .build()
35        .expect("popsize must be >= 4");
36
37    // Apply linear constraints with a penalty weight
38    lc.apply_to(&mut cfg, 1e3);
39
40    let rep = differential_evolution(&sphere, &bounds, cfg).expect("optimization failed");
41    println!(
42        "success={} message=\"{}\"\nbest f={:.6e}\nbest x={:?}",
43        rep.success, rep.message, rep.fun, rep.x
44    );
45}