Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ exclude = [

[dependencies]
rand = "^0.8.4"
indicatif = "^0.16.2"
rand_chacha = "^0.3"
indicatif = "^0.18.4"
rayon = "^1.5.1"

# [profile.release]
Expand Down
38 changes: 21 additions & 17 deletions src/bin/e_lj.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use pso_rs::*;
use std::process;
const N_PARTICLES:usize = 20;

const N_PARTICLES: usize = 20;

fn main() {
let dimensions = vec![N_PARTICLES, 3];
Expand All @@ -26,11 +25,13 @@ fn main() {
lr,
bounds,
t_max,
parallelize: true,
..Config::default()
};
use std::time::Instant;
let before = Instant::now();
match pso_rs::run(config, e_lj, None) {
let e_lj = Box::new(Elj {});
match pso_rs::run(config, e_lj, None, None, None) {
Ok(pso) => {
println!("Elapsed time: {:.2?}", before.elapsed());
pso.write_f_to_file("./best_f_trajectory.txt")
Expand Down Expand Up @@ -62,7 +63,7 @@ fn l2(x_i: Particle, x_j: Particle, particle_dim: usize) -> f64 {
// calculated as the square root of the sum of the squared vector values
let mut sum: f64 = 0.0;
for i in 0..particle_dim {
sum += (x_i[i] - x_j[i]).powf(2.0);
sum += (x_i[i] - x_j[i]).value_f64().powf(2.0);
}
sum.sqrt()
}
Expand All @@ -74,23 +75,26 @@ fn v_ij(x_i: Particle, x_j: Particle, particle_dim: usize) -> f64 {
}

/// Get potential energy of a cluster of particles
fn e_lj(particle: &Particle, _flat_dim: usize, particle_dims: &Vec<usize>) -> f64 {
let mut sum = 0.0;
for i in 0..particle_dims[0] - 1 {
for j in (i + 1)..particle_dims[0] {
let true_i = i * particle_dims[1];
let true_j = j * particle_dims[1];
sum += v_ij(
particle[true_i..true_i + particle_dims[1]].to_vec(),
particle[true_j..true_j + particle_dims[1]].to_vec(),
particle_dims[1],
);
struct Elj;
impl ObjectiveFunction for Elj {
fn evaluate(&self, particle: &Particle, _flat_dim: usize, particle_dims: &[usize]) -> f64 {
let mut sum = 0.0;
for i in 0..particle_dims[0] - 1 {
for j in (i + 1)..particle_dims[0] {
let true_i = i * particle_dims[1];
let true_j = j * particle_dims[1];
sum += v_ij(
particle[true_i..true_i + particle_dims[1]].to_vec(),
particle[true_j..true_j + particle_dims[1]].to_vec(),
particle_dims[1],
);
}
}
4.0 * sum
}
4.0 * sum
}

fn reshape(particle: &Particle, particle_dims: &Vec<usize>) -> Vec<Vec<f64>> {
fn reshape(particle: &Particle, particle_dims: &[usize]) -> Vec<Vec<NumericKind>> {
// reshape particle
let mut reshaped_cluster = vec![];
let mut i = 0;
Expand Down
28 changes: 24 additions & 4 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,44 @@
use pso_rs::*;

const N_DIMENSIONS:usize = 3;
const N_DIMENSIONS: usize = 3;

fn main() {
let config = Config {
dimensions: vec![N_DIMENSIONS],
population_size: 100,
bounds: vec![(-10.0, 10.0); N_DIMENSIONS],
t_max: 1e7 as usize,
parallelize: true,
..Config::default()
};
use std::time::Instant;
let before = Instant::now();
let pso = pso_rs::run(config, sum_squares, Some(|f_best| f_best < 1e-4)).unwrap();
let sum_squares = Box::new(SumOfSquares {});
let pso: pso::PSO = pso_rs::run(
config,
sum_squares,
Some(|f| {
let mut r: Vec<NumericKind> = vec![];
for ff in f {
r.push(NumericKind::ValueF64(*ff));
}
r
}),
Some(|f_best| f_best < 1e-4),
Some(123456u64),
)
.unwrap();
println!("Elapsed time: {:.2?}", before.elapsed());
let model = pso.model;
println!("Found minimum: {:#?} ", model.get_f_best());
println!("Found minimizer: {:#?} ", model.get_x_best());
}

fn sum_squares(p: &Particle, _flat_dim: usize, dimensions: &Vec<usize>) -> f64 {
(0..dimensions[0]).map(|i| i as f64 * p[i].powf(2.0)).sum()
struct SumOfSquares;
impl ObjectiveFunction for SumOfSquares {
fn evaluate(&self, particle: &Particle, _flat_dim: usize, dimensions: &[usize]) -> f64 {
(0..dimensions[0])
.map(|i| i as f64 * particle[i].value_f64().powf(2.0))
.sum()
}
}
103 changes: 68 additions & 35 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@
//! 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)
//! struct ObjectiveObj;
//! impl ObjectiveFunction for ObjectiveObj {
//! fn evaluate(&self, p: &Particle, _flat_dim: usize, dimensions: &[usize]) -> f64 {
//! (0..dimensions[0] - 1).map(|i| {
//! 100.0 * ((p[i+1]-p[i]).value_f64().powf(2.0)).powf(2.0)
//! + (1.0-p[i].value_f64()).powf(2.0)
//! }).sum()
//! }
//! }
//!
//! // define a termination condition (optional)
//! fn terminate(f_best: f64) -> bool {
//! f_best - (0.0) < 1e-4
Expand All @@ -49,8 +47,10 @@
//!
//! let pso = pso_rs::run(
//! config,
//! objective_function,
//! Some(terminate)
//! Box::new(ObjectiveObj{}),
//! None,
//! Some(terminate),
//! None
//! ).unwrap();
//!
//! let model = pso.model;
Expand All @@ -63,18 +63,16 @@
//! use pso_rs::*;
//!
//! // define objective function (d-dimensional Rosenbrock)
//! fn objective_function(
//! p: &Particle,
//! _flat_dim: usize,
//! dimensions: &Vec<usize>
//! ) -> f64 {
//! struct ObjectiveObj;
//! impl ObjectiveFunction for ObjectiveObj {
//! fn evaluate(&self, p: &Particle, _flat_dim: usize, dimensions: &[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)
//! 100.0 * ((p[i+1]-p[i]).value_f64().powf(2.0)).powf(2.0)
//! + (1.0-p[i].value_f64()).powf(2.0)
//! }).sum()
//! }
//! }
//!
//!
//! let config = Config {
//! dimensions: vec![2],
//! bounds: vec![(-5.0, 10.0); 2],
Expand All @@ -84,7 +82,9 @@
//!
//! let mut pso = pso_rs::init(
//! config,
//! objective_function
//! Box::new(ObjectiveObj{}),
//! None,
//! None
//! ).unwrap();
//!
//! // run PSO with no termination condition
Expand All @@ -94,6 +94,31 @@
//! println!("Found minimum: {:#?} ", model.get_f_best());
//! println!("Minimizer: {:#?}", model.get_x_best());
//! ```
//! struct XSumSquares;
//! impl ObjectiveFunction for XSumSquares {
//! fn evaluate(&self, particle: &Particle, _flat_dim: usize, dimensions: &[usize]) -> f64 {
//! (0..dimensions[0]).map(|i| i as f64 * particle[i].powf(2.0)).sum()
//! };
//! }
//!
//! //example shows how to use lambda functions to model objective
//! fn main() {
//! let config = Config {
//! dimensions: vec![N_DIMENSIONS],
//! population_size: 100,
//! bounds: vec![(-10.0, 10.0); N_DIMENSIONS],
//! t_max: 1e7 as usize,
//! ..Config::default()
//! };
//! use std::time::Instant;
//! let before = Instant::now();
//!
//! let pso = pso_rs::run(config, Box::new(XSumSquares), None, Some(|f_best| f_best < 1e-4),Some(123456u64)).unwrap();
//! println!("Elapsed time: {:.2?}", before.elapsed());
//! let model = pso.model;
//! println!("Found minimum: {:#?} ", model.get_f_best());
//! println!("Found minimizer: {:#?} ", model.get_x_best());
//! }
//!
//! # Notes
//!
Expand All @@ -115,8 +140,8 @@
//!
//! fn reshape(
//! particle: &Particle,
//! particle_dims: &Vec<usize>
//! ) -> Vec<Vec<f64>> {
//! particle_dims: &[usize]
//! ) -> Vec<Vec<NumericKind>> {
//! let mut reshaped_cluster = vec![];
//! let mut i = 0;
//! for _ in 0..particle_dims[0] {
Expand All @@ -131,16 +156,19 @@
//! }
//!
//! // used in the objective function
//! fn objective_function(
//! p: &Particle,
//! struct ObjectiveObj;
//! impl ObjectiveFunction for ObjectiveObj {
//! fn evaluate(
//! &self,
//! particle: &Particle,
//! _flat_dim: usize,
//! dimensions: &Vec<usize>
//! dimensions: &[usize]
//! ) -> f64 {
//! let _reshaped_particle = reshape(p, dimensions);
//! let _reshaped_particle = reshape(particle, dimensions);
//! /* Do stuff */
//! 0.0
//! }
//!
//! }
//! let config = Config {
//! dimensions: vec![20, 3],
//! bounds: vec![(-2.5, 2.5); 3],
Expand All @@ -150,7 +178,9 @@
//!
//! let pso = pso_rs::run(
//! config,
//! objective_function,
//! Box::new(ObjectiveObj{}),
//! None,
//! None,
//! None
//! ).unwrap();
//!
Expand All @@ -167,7 +197,6 @@ pub mod pso;

pub use model::*;

use model::Model;
use pso::PSO;
use std::error::Error;

Expand All @@ -178,11 +207,13 @@ use std::error::Error;
/// Panics if any particle coefficient becomes NaN (usually because of bad parameterization, e.g. c1 + c2 < 4)
pub fn run(
config: Config,
obj_f: fn(&Particle, usize, &Vec<usize>) -> f64,
obj_f: Box<dyn ObjectiveFunction>,
cast_f: Option<CastFunctionT>,
terminate_f: Option<fn(f64) -> bool>,
seed: Option<u64>,
) -> Result<PSO, Box<dyn Error>> {
assert_config(&config)?;
let mut pso = init(config, obj_f).unwrap();
let mut pso = init(config, obj_f, cast_f, seed)?;
let term_condition = match terminate_f {
Some(terminate_f) => terminate_f,
None => |_| false,
Expand All @@ -196,19 +227,21 @@ pub fn run(
/// Useful for initializing an instance for running at a later time
pub fn init(
config: Config,
obj_f: fn(&Particle, usize, &Vec<usize>) -> f64,
obj_f: Box<dyn ObjectiveFunction>,
cast_f: Option<CastFunctionT>,
seed: Option<u64>,
) -> Result<PSO, &'static str> {
assert_config(&config)?;
let model = Model::new(config, obj_f);
let pso = PSO::new(model);
let model = Model::new(config, obj_f, cast_f, seed);
let pso = PSO::new(model, seed);
Ok(pso)
}

fn assert_config(config: &Config) -> Result<(), &'static str> {
if config.c1 + config.c2 < 4.0 {
return Err("c1 + c2 must be greater than 4");
}
if config.dimensions.len() == 0 {
if config.dimensions.is_empty() {
return Err("dimensions must be set");
}
if config.bounds.len() != config.dimensions[config.dimensions.len() - 1] {
Expand Down
Loading