#优化 #粒子 #群体 #进度条 #PSO #目标 #光线

pso-rs

在Rust中实现的一个简单易用的粒子群优化算法

17个版本 (10个稳定版)

2.2.4 2021年11月1日
2.2.3 2021年10月7日
2.2.2 2021年7月19日
1.2.0 2021年7月17日
0.1.0 2021年7月17日

#506算法

每月下载量:28

MIT 许可协议

30KB
391

pso-rs

在Rust中实现的一个简单易用的粒子群优化(PSO)算法。

Crates.io docs.rs Website License

适用于Rust 2021版

它使用rand包进行随机初始化,使用rayon包进行并行目标函数计算。它还包含indicatif包提供的进度条。以下是PSO运行时的截图,尝试最小化20分子集群中的Lennard-Jones势能

Screenshot

以下示例可以帮助您入门。要在自己的优化问题中使用它,您需要定义一个目标函数,就像在run函数中定义的那样,以及一个Config对象。请参阅说明部分以获取更多信息。

示例

运行PSO

use pso_rs::*;

// define objective function (d-dimensional Rosenbrock)
fn objective_function(
    p: &Particle,
    _flat_dim: usize,
    dimensions: &Vec<usize>
) -> f64 {
    (0..dimensions[0] - 1).map(|i| {
        100.0 * ((p[i+1]-p[i]).powf(2.0)).powf(2.0)
            + (1.0-p[i]).powf(2.0)
    }).sum()
}

// define a termination condition (optional)
fn terminate(f_best: f64) -> bool {
    f_best < 1e-4
}

let config = Config {
    // dimension shape of each particle
    dimensions: vec![2],
    // problem bounds in each dimension
    bounds: vec![(-5.0, 10.0); 2],
    // maximum no. of objective function computations
    t_max: 10000,
    // leave the rest of the params as default
    ..Config::default()
};

let pso = pso_rs::run(
    config,
    objective_function,
    Some(terminate)
).unwrap();

let model = pso.model;
println!("Model: {:?} ", model.get_f_best());

初始化PSO以供后续执行

use pso_rs::*;

// define objective function (d-dimensional Rosenbrock)
fn objective_function(
    p: &Particle,
    _flat_dim: usize,
    dimensions: &Vec<usize>
) -> f64 {
    (0..dimensions[0] - 1).map(|i| {
        100.0 * ((p[i+1]-p[i]).powf(2.0)).powf(2.0)
            + (1.0-p[i]).powf(2.0)
    }).sum()
}


let config = Config {
    dimensions: vec![2],
    bounds: vec![(-5.0, 10.0); 2],
    t_max: 10000,
    ..Config::default()
};

let mut pso = pso_rs::init(
    config,
    objective_function
).unwrap();

// run PSO with no termination condition
pso.run(|_| false);

let model = pso.model;
println!("Model: {:?} ", model.get_f_best());

说明

性能

此实现使用扁平向量(Vec<f64>)来表示任何d维问题(请参阅优化问题维度部分)。这意味着向量具有O(1)的访问时间,并且可以像静态数组一样进行缓存,以实现快速访问。

每个粒子的目标函数计算都是并行进行的,因为对于任何非平凡问题,这都需要昂贵的计算。在未来,完整的群体将能够并行运行,并可选择通过传递消息来通信它们找到的最佳位置。

优化问题维度

尽管您可以为粒子指定任何形状和大小,只要每个项是f64,但pso_rs将每个粒子表示为扁平向量:Vec<f64>

这意味着,例如,为了在三维空间中找到20个分子的聚类,使其Lennard-Jones势能最小化,您可以定义dimensions为(20, 3)。如果您愿意,也可以创建一个自定义的reshape函数,如下所示,用于分子聚类

use pso_rs::*;

fn reshape(
    particle: &Particle,
    particle_dims: &Vec<usize>
) -> Vec<Vec<f64>> {
    let mut reshaped_cluster = vec![];
    let mut i = 0;
    for _ in 0..particle_dims[0] {
        let mut reshaped_molecule = vec![];
        for _ in 0..particle_dims[1] {
            reshaped_molecule.push(particle[i]);
            i += 1;
        }
        reshaped_cluster.push(reshaped_molecule);
    }
    reshaped_cluster
}

// used in the objective function
fn objective_function(
    p: &Particle,
    _flat_dim: usize,
    dimensions: &Vec<usize>
) -> f64 {
    let _reshaped_particle = reshape(p, dimensions);
    /* Do stuff */
    0.0
}

let config = Config {
    dimensions: vec![20, 3],
    bounds: vec![(-2.5, 2.5); 3],
    t_max: 1,
    ..Config::default()
};

let pso = pso_rs::run(
    config,
    objective_function,
    None
).unwrap();

// somewhere in main(), after running PSO as in the example:
println!(
    "Best found minimizer: {:#?} ",
    reshape(&pso.model.get_x_best(),
        &pso.model.config.dimensions)
);

元信息

Christos A. Zonios – @czonios – c.zonios (at) uoi (dot) gr

在MIT许可下分发。更多信息请见LICENSE

https://github.com/czonios/pso-rs

贡献

  1. 分叉它 (https://github.com/czonios/pso-rs/fork)
  2. 创建您的功能分支 (git checkout -b feature/fooBar)
  3. 运行测试 (tests)
  4. 提交您的更改 (git commit -am 'Add some fooBar')
  5. 推送到分支 (git push origin feature/fooBar)
  6. 创建一个新的Pull Request

测试

cargo test
cargo test --doc

在开发新功能时,有一个优化问题可能会对快速反馈很有用。您可以使用以下示例优化问题之一(在src/bin目录中找到)

# Rosenbrock function (3 dimensional)
cargo run --bin=main
# For profiling use --release flag
# You can change the number of dimensions in the file 
# src/bin/main.rs
cargo run --release --bin=main

# Lennard-Jones potential for a N-particle system (N=20)
cargo run --bin=e_lj
cargo run --release --bin=e_lj

依赖项

~5–13MB
~146K SLoC