5 releases

0.2.0 Jul 6, 2020
0.1.3 Jul 4, 2020
0.1.2 Jul 3, 2020
0.1.1 Jul 2, 2020
0.1.0 Jun 30, 2020

#1518 in Algorithms

MIT license

65KB
1.5K SLoC

PSO

Easy and Efficient Particle Swarm Optimizer in Rust

Features

  • Efficient Multi-Threaded optimization
  • Simple API with many optional parameters to configure
  • Minimizes an N dimensional objective function defined as a closure
  • Lots of fanciness under the hood to avoid local minima traps

Examples

Simple

// set up a PSO with 8 default swarms
let pso = PSO::default(8, false);

// set up the stop condition and search space with a JobConfig
let mut jc = JobConfig::new(5); // search a 5 variable space
jc.exit_cost(10e-10); // stop optimizing when the objective cost reaches 10e-10
jc.variable_bound([-5.0, 5.0]); // constrain the 5D search space to (-5, 5) along all dimensions

// create a simple objective function
let obj = |x_vec: &[f64]| -> f64 { x_vec.iter().map(|x| x.powi(2)).sum::<f64>() };

// search for the minimum
let min = pso.run_job_fn(jc, obj);

assert!(min.0 < 10e-9);
for x in min.1 {
    assert!(x.abs() < 0.001);
}

Advanced

// define a swarm configuration
let mut sc = SwarmConfig::new();
sc.synergic_behavior(0.4, 100); // collaborate with other swarms every 100 iterations using a global-coefficient of 0.4
sc.motion_coefficients(0.5, 0.6, 1.0); // use custom motion coefficients
sc.num_particles(256); // put 256 particles in each swarm

// set up a PSO with 8 swarms using the above SwarmConfig
let pso = PSO::from_swarm_config(8, false, &sc);

// set up the stop condition and search space with a JobConfig
let mut jc = JobConfig::new(5);
jc.max_iter_and_exit_cost(10000, 10e-10); // stop after the first of these conditions is met
jc.variable_bounds(vec![
    // define a custom upper and lower bound on each dimension
    [-10.0, 10.0],
    [-8.0, 8.0],
    [-6.0, 6.0],
    [-4.0, 4.0],
    [-2.0, 2.0],
]);
jc.update_console(100); // update the console with the current minimum every 100 iterations

// create a simple objective function using some external data
let mins = [1.0; 5];
let obj = move |x_vec: &[f64]| -> f64 {
    x_vec
        .iter()
        .enumerate()
        .map(|(i, x)| (x - mins[i]).powi(2))
        .sum::<f64>()
};

// search for the minimum
let min = pso.run_job_fn(jc, obj);

assert!(min.0 < 10e-9);
for (i, x) in min.1.iter().enumerate() {
    assert!((x - mins[i]).abs() < 0.001);
}

Dependencies

~3–4MB
~74K SLoC