use crate::configuration::ProblemSolving;
#[derive(Debug, Clone)]
pub enum PsoInertia {
Constant(f64),
LinearDecay {
w_start: f64,
w_end: f64,
},
}
#[derive(Debug, Clone)]
pub enum PsoTopology {
Global,
Ring {
neighborhood_size: usize,
},
}
#[derive(Debug, Clone)]
pub struct PsoConfiguration {
pub population_size: usize,
pub max_generations: usize,
pub problem_solving: ProblemSolving,
pub fitness_target: Option<f64>,
pub inertia: PsoInertia,
pub c1: f64,
pub c2: f64,
pub topology: PsoTopology,
pub fitness_cache_size: Option<usize>,
}
impl Default for PsoConfiguration {
fn default() -> Self {
Self {
population_size: 30,
max_generations: 1000,
problem_solving: ProblemSolving::Minimization,
fitness_target: None,
inertia: PsoInertia::LinearDecay {
w_start: 0.9,
w_end: 0.4,
},
c1: 2.0,
c2: 2.0,
topology: PsoTopology::Global,
fitness_cache_size: None,
}
}
}
impl PsoConfiguration {
pub fn with_population_size(mut self, n: usize) -> Self {
self.population_size = n;
self
}
pub fn with_max_generations(mut self, n: usize) -> Self {
self.max_generations = n;
self
}
pub fn with_problem_solving(mut self, ps: ProblemSolving) -> Self {
self.problem_solving = ps;
self
}
pub fn with_fitness_target(mut self, t: f64) -> Self {
self.fitness_target = Some(t);
self
}
pub fn with_inertia(mut self, inertia: PsoInertia) -> Self {
self.inertia = inertia;
self
}
pub fn with_c1(mut self, v: f64) -> Self {
self.c1 = v;
self
}
pub fn with_c2(mut self, v: f64) -> Self {
self.c2 = v;
self
}
pub fn with_topology(mut self, topology: PsoTopology) -> Self {
self.topology = topology;
self
}
pub fn with_fitness_cache_size(mut self, size: usize) -> Self {
self.fitness_cache_size = Some(size);
self
}
}
pub(crate) fn inertia_weight(inertia: &PsoInertia, gen: usize, max_generations: usize) -> f64 {
match inertia {
PsoInertia::Constant(w) => *w,
PsoInertia::LinearDecay { w_start, w_end } => {
if max_generations <= 1 {
*w_end
} else {
w_start + (w_end - w_start) * (gen as f64) / ((max_generations - 1) as f64)
}
}
}
}