1use eyre::WrapErr;
16
17use crate::{
18 component::ExecResult,
19 components::{boundary, initialization, mapping, swarm},
20 conditions::Condition,
21 configuration::Configuration,
22 identifier::{Global, Identifier},
23 lens::ValueOf,
24 logging::Logger,
25 problems::{LimitedVectorProblem, SingleObjectiveProblem},
26 state::common,
27 Component,
28};
29
30pub struct RealProblemParameters {
32 pub num_particles: u32,
33 pub start_weight: f64,
34 pub end_weight: f64,
35 pub c_one: f64,
36 pub c_two: f64,
37 pub v_max: f64,
38}
39
40pub fn real_pso<P>(
44 params: RealProblemParameters,
45 condition: Box<dyn Condition<P>>,
46) -> ExecResult<Configuration<P>>
47where
48 P: SingleObjectiveProblem + LimitedVectorProblem<Element = f64>,
49{
50 let RealProblemParameters {
51 num_particles,
52 start_weight,
53 end_weight,
54 c_one,
55 c_two,
56 v_max,
57 } = params;
58
59 Ok(Configuration::builder()
60 .do_(initialization::RandomSpread::new(num_particles))
61 .evaluate()
62 .update_best_individual()
63 .do_(pso::<P, Global>(
64 Parameters {
65 particle_init: swarm::ParticleSwarmInit::new(v_max)?,
66 particle_update: swarm::ParticleVelocitiesUpdate::new(
67 start_weight,
68 c_one,
69 c_two,
70 v_max,
71 )
72 .wrap_err("failed to construct particle velocities update")?,
73 constraints: boundary::Saturation::new(),
74 inertia_weight_update: Some(mapping::Linear::new(
75 start_weight,
76 end_weight,
77 ValueOf::<common::Progress<ValueOf<common::Iterations>>>::new(),
78 ValueOf::<swarm::InertiaWeight<swarm::ParticleVelocitiesUpdate>>::new(),
79 )),
80 state_update: swarm::ParticleSwarmUpdate::new(),
81 },
82 condition,
83 ))
84 .build())
85}
86
87pub struct Parameters<P> {
89 pub particle_init: Box<dyn Component<P>>,
90 pub particle_update: Box<dyn Component<P>>,
91 pub constraints: Box<dyn Component<P>>,
92 pub inertia_weight_update: Option<Box<dyn Component<P>>>,
93 pub state_update: Box<dyn Component<P>>,
94}
95
96pub fn pso<P, I>(params: Parameters<P>, condition: Box<dyn Condition<P>>) -> Box<dyn Component<P>>
98where
99 P: SingleObjectiveProblem,
100 I: Identifier,
101{
102 let Parameters {
103 particle_init,
104 particle_update,
105 constraints,
106 inertia_weight_update,
107 state_update,
108 } = params;
109
110 Configuration::builder()
111 .do_(particle_init)
112 .while_(condition, |builder| {
113 builder
114 .do_(particle_update)
115 .do_(constraints)
116 .evaluate_with::<I>()
117 .update_best_individual()
118 .do_if_some_(inertia_weight_update)
119 .do_(state_update)
120 .do_(Logger::new())
121 })
122 .build_component()
123}