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
30KB
391 行
pso-rs
在Rust中实现的一个简单易用的粒子群优化(PSO)算法。
适用于Rust 2021版
它使用rand
包进行随机初始化,使用rayon
包进行并行目标函数计算。它还包含indicatif
包提供的进度条。以下是PSO运行时的截图,尝试最小化20分子集群中的Lennard-Jones势能
以下示例可以帮助您入门。要在自己的优化问题中使用它,您需要定义一个目标函数,就像在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
贡献
- 分叉它 (https://github.com/czonios/pso-rs/fork)
- 创建您的功能分支 (
git checkout -b feature/fooBar
) - 运行测试 (tests)
- 提交您的更改 (
git commit -am 'Add some fooBar'
) - 推送到分支 (
git push origin feature/fooBar
) - 创建一个新的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