#优化 #粒子群

pos_pso

粒子群优化器

7个版本

0.1.6 2020年6月19日
0.1.5 2020年6月17日
0.1.4 2020年5月12日
0.1.0 2020年4月13日

5 in #优化器

每月 21 次下载

MIT 许可证

48KB
1K SLoC

POS_PSO

纯Rust实现的具有高度可配置性的粒子群优化器

可以轻松地在多个线程上最小化成本函数

  • 可以使用独立群体并行运行多个优化
  • 或者群体可以定期共享搜索空间中的最佳已知位置,使用协作群体

运动动力学松散基于Matlab的粒子群算法

优化器采用以下头部的闭包作为成本函数

move |x: &[f64]| -> f64 {}
  • 输入的切片数组表示N维优化空间中的一个点
  • 返回的成本用于在搜索空间中导航以定位最小值
  • 目前仅支持f64,但未来的更新可能允许更通用的成本函数

一些入门示例

单线程示例(单个群体)

  • 使用默认的独立群体配置(这是一个好起点,但您可能希望根据您的用例定义自己的配置)
  • 搜索空间边界和最大速度仍然必须在JobConfig对象中定义
  • 单群体可能是高端英特尔处理器的最快性能选项
extern crate pos_pso;
use pos_pso::{PSO, PSOConfig, JobConfig};

fn main() {
    let num_variables = 5;

    // Define a cost function to minimize:

    //data captured by closure
    let mins = vec![1.0, 2.0, 3.0, 4.0, 5.0];
    let coeffs = vec![0.25; num_variables];

    //cost function closure must take a &[f64] and return f64
    let cost_function = move |point: &[f64]| -> f64 {
        let mut sum = 0.0;
        for i in 0..num_variables {
            sum += (point[i] - mins[i]).powi(2) * coeffs[i];
        }
        sum
    };

    // Create a PSO Configuration:
    let pso_config = PSOConfig::new(
        1,          // 1 swarm used in optimization
        256,        // 256 particles are spawned
        10,         // console is updated every 10 itterations
        true        // optimizer is verbose (will provide more detailed information to console)
    );


    // Create a PSO:
    let pso = PSO::new(pso_config);


    // Create a Job Configuration:
    let job_config = JobConfig::new(
        num_variables, 
        vec![[-15.0, 15.0]; num_variables],  // [upper, lower] bounds for each variable
        vec![1.125; num_variables],          // max velocity for each variable
        100,                                 // run for 100 itterations
        0.0000001,                           // exit cost (optimization will stop when a cost of 0.0000001 is reached)
    );


    // Minimize cost function:

    //use minimize_independant to optimize with the default independant-swarm configuration
    //the next example will show how to use collaborative-swarms
    let min = pso.minimize_independant(job_config, cost_function);

    println!("Minimum of: {}, With value: {:?}", min.0, min.1);
}

多线程示例*使用4个协作群体,每个群体中粒子更少

  • 使用运动系数和记录共享周期定义自定义群体配置
  • 这可能是高端AMD处理器的最快性能选项
let num_variables = 5;

    // Define a cost function to minimize:

    //data captured by closure
    let mins = vec![1.0, 2.0, 3.0, 4.0, 5.0];
    let coeffs = vec![0.25; num_variables];

    //cost function closure must take a &[f64] and return f64
    let cost_function = move |point: &[f64]| -> f64 {
        let mut sum = 0.0;
        for i in 0..num_variables {
            sum += (point[i] - mins[i]).powi(2) * coeffs[i];
        }
        sum
    };

    // Create a PSO Configuration:
    let pso_config = PSOConfig::new(
        4,          // 4 swarms (each spawned on their own thread)
        64,         // 64 particles per swarm
        10,         // console is updated every 10 itterations
        true        // optimizer is verbose (will provide more detailed information to console)
    );


    // Create a PSO:
    let pso = PSO::new(pso_config);

    
    // Create a Job Configuration:
    let job_config = JobConfig::new(
        num_variables, 
        vec![[-15.0, 15.0]; num_variables],  // [upper, lower] bounds for each variable
        vec![1.125; num_variables],          // max velocity for each variable
        100,                                 // run for 100 itterations
        0.0000001,                           // exit cost (swarms will stop when a cost of 0.0000001 is reached)
    );


    // Create a custom Swarm Configuration:

    //collaborative swarms will share information with eachother about best known locations in the search space
    let swarm_config = SwarmConfig::new_collaborative(
        1.45,       // local weigth:    how much particles care about their best known location
        1.6,        // tribal weight:   how much particles care about their swarms best known location
        1.25,       // global weight:   how much particles care about the overall best known location
        0.4,        // inertial coefficient:    component of a particles velocity that contributes to its next velocity
        1.25,       // inertial growth factor:  how much inertia grows and shrinks throughout optimization
        0.125,      // wall bounce factor:      component of velocity that is saved when particle goes out of bounds
        10,         // tribal-global collab period:   swarms share best known location every 10 itterations
    );


    // Minimize cost function:

    //use minimize to optimize with a custom SwarmConfig
    let min = pso.minimize(job_config, swarm_config, cost_function);

    println!("Minimum of: {}, With value: {:?}", min.0, min.1);

高级示例

  • 使用8个独立群体以不同的群体参数最小化相同的成本函数
  • 此示例展示了如何使用SwarmConfigDistribution,其中群体行为系数是从用户定义的分布中采样的
  • 所有8个群体在单独的线程上并行运行(在所有线程完成后返回最低成本和最佳位置)
extern crate pos_pso;
use pos_pso::{PSO, PSOConfig, JobConfig, SwarmConfigDistribution, ParamDist};

fn main() {
    let num_variables = 5;

    // Define a cost function to minimize:

    //data captured by closure
    let mins = vec![1.0, 2.0, 3.0, 4.0, 5.0];
    let coeffs = vec![0.25; num_variables];

    //cost function closure must take a &[f64] and return f64
    let cost_function = move |point: &[f64]| -> f64 {
        let mut sum = 0.0;
        for i in 0..num_variables {
            sum += (point[i] - mins[i]).powi(2) * coeffs[i];
        }
        sum
    };


    // Create a PSO Configuration:
    let pso_config = PSOConfig::new(
        8,          // 8 swarms (each spawned on their own thread)
        128,        // 128 particles per swarm
        10,         // console is updated by each thread every 10 itterations
        true        // optimizer is verbose (will provide more detailed information to console)
    );


    // Create a PSO:
    let pso = PSO::new(pso_config);


    // Create a Job Configuration:
    let job_config = JobConfig::new(
        num_variables, 
        vec![[-15.0, 15.0]; num_variables],  // [upper, lower] bounds for each variable
        vec![1.125; num_variables],          // max velocity for each variable
        100,                                 // run for 100 itterations
        0.0000001,                           // exit cost (swarms will stop when a cost of 0.0000001 is reached)
    );


    // Create a Swarm Configuration Distribution:

    //the optimizer will sample a new swarm configuration for each swarm
    //this is usefull for automatically creating a range of swarm behaviors
    //in this case we are using new_independant, so all 8 optimizations will run seperately in parallel
    let swarm_config = SwarmConfigDistribution::new_independant(
        ParamDist::Fixed(1.45),                 // local: fixed value of 1.45
        ParamDist::Range([1.65, 0.25]),         // tribal: random value: 1.65 +/- 25% 
        ParamDist::Fixed(0.4),                  // momentum: fixed value of 0.4
        ParamDist::Range([1.25, 0.05]),         // momentum growth factor: random value: 1.25 +/- 5%
        ParamDist::Fixed(0.0125),               // wall bounce factor: fixed value of 0.0125
    );


    // Minimize cost function:

    //use minimize_distributed to accept SwarmConfigDistribution
    let min = pso.minimize_distributed(job_config, swarm_config, cost_function);

    println!("Minimum of: {}, With value: {:?}", min.0, min.1);

}

依赖项

~1.3–2MB
~36K SLoC