-
Notifications
You must be signed in to change notification settings - Fork 1
/
pso.rs
115 lines (107 loc) · 4.4 KB
/
pso.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! Implementation of PSO algorithm
pub mod builder;
pub mod particle;
pub mod probe;
pub mod swarm;
pub mod termination_condition;
pub mod util;
use crate::pso::probe::stdout_probe::StdoutProbe;
use crate::pso::probe::Probe;
use crate::pso::swarm::Swarm;
use crate::pso::termination_condition::{GenerationLimit, TerminationCondition};
use crate::test_functions::rosenbrock;
/// Struct wrapping all configuration parameters of PSO algorithm.
/// # Parameters:
/// - dimensions - number of dimension of optimized function's domain
/// - lower_bound - lower bound of search area in every dimension of the domain
/// - upper_bound - upper bound of search area in every dimension of the domain
/// - particle_count - number of particles to use in optimization (number of particles will be maintained throughout the algorithm's run)
/// - inertia_weight - specifies how much particles retain their speed from previous iteration (0 - no speed retention, 1 - no slowdown)
/// - cognitive_coefficient - specifies how much particles are attracted their own best positions
/// - social_coefficient - specifies how much particles are attracted to entire swarm's best position
/// - function - function to be optimized
/// - termination_condition - used for determining stopping point of the algorithm
/// - probe - used for displaying results / progress of the algorithm
/// # Example coefficient values:
/// - inertia_weight: 0.5
/// - cognitive_coefficient: 1.0
/// - social_coefficient: 3.0
pub struct PSOAlgorithmCfg {
dimensions: usize,
lower_bound: f64,
upper_bound: f64,
particle_count: usize,
inertia_weight: f64,
cognitive_coefficient: f64,
social_coefficient: f64,
function: fn(&Vec<f64>) -> f64,
termination_condition: Box<dyn TerminationCondition>,
probe: Box<dyn Probe>,
}
impl Default for PSOAlgorithmCfg {
fn default() -> Self {
PSOAlgorithmCfg {
dimensions: 2,
lower_bound: -10.0,
upper_bound: 10.0,
particle_count: 30,
inertia_weight: 0.5,
cognitive_coefficient: 1.0,
social_coefficient: 3.0,
function: rosenbrock,
termination_condition: Box::new(GenerationLimit::new(500)),
probe: Box::new(StdoutProbe::new()),
}
}
}
/// Struct used for running PSO algorithm
/// # Usage example:
/// ```rust
/// # use ecrs::pso::{builder::PSOAlgorithmBuilder, self};
/// let iterations = 50; // use more reasonable number here
/// let stdout_probe = Box::new(pso::probe::stdout_probe::StdoutProbe::new());
/// let csv_probe = Box::new(pso::probe::csv_probe::CsvProbe::new("pso_example.csv"));
/// let json_probe = Box::new(pso::probe::json_probe::JsonProbe::new("pso_example.json"));
/// let probes: Vec<Box<dyn pso::probe::Probe>> = vec![stdout_probe, csv_probe, json_probe];
/// let aggregated_probe = Box::new(pso::probe::aggregated_probe::AggregatedProbe::from_probes(probes));
/// let probing_policy = Box::new(pso::probe::probing_policy::GenerationInterval::new(50));
/// let policy_driven_probe = Box::new(pso::probe::policy_driven_probe::PolicyDrivenProbe::new(aggregated_probe, probing_policy));
/// let mut algorithm = PSOAlgorithmBuilder::new()
/// .set_dimensions(3)
/// .set_generation_limit(iterations)
/// .set_probe(policy_driven_probe)
/// .build();
/// algorithm.run();
/// ```
pub struct PSOAlgorithm {
config: PSOAlgorithmCfg,
swarm: Swarm,
}
impl PSOAlgorithm {
pub fn new(config: PSOAlgorithmCfg) -> Self {
let swarm = Swarm::generate(
config.particle_count,
config.dimensions,
config.lower_bound,
config.upper_bound,
config.function,
);
PSOAlgorithm { config, swarm }
}
pub fn run(&mut self) {
self.config.probe.on_begin(&self.swarm);
let mut iteration = 0;
while !self.config.termination_condition.is_met(iteration, &self.swarm) {
iteration += 1;
self.swarm.update_velocities(
&self.config.inertia_weight,
&self.config.cognitive_coefficient,
&self.config.social_coefficient,
);
self.swarm.update_positions(self.config.function);
self.swarm.update_best_position(self.config.function);
self.config.probe.on_new_generation(&self.swarm, iteration);
}
self.config.probe.on_end(&self.swarm, iteration);
}
}