RockyML  0.0.1
A High-Performance Scientific Computing Framework
pso.h
1 /*
2  Copyright (C) 2022 Amirabbas Asadi , All Rights Reserved
3  distributed under Apache-2.0 license
4 */
5 #ifndef ROCKY_ZAGROS_PSO_STRATEGY
6 #define ROCKY_ZAGROS_PSO_STRATEGY
7 #include <rocky/zagros/strategies/strategy.h>
8 
9 namespace rocky{
10 namespace zagros{
15 template<typename T_e, int T_dim>
16 class basic_pso: public search_strategy<T_e, T_dim>{
17 public:
18  typedef Eigen::Map<Eigen::Matrix<T_e, 1, T_dim, Eigen::RowMajor>> eigen_particle;
19  enum update_mode {use_particles, use_groups};
20 
21 protected:
22  // system
23  system<T_e>* problem_;
24  // main container
25  basic_scontainer<T_e, T_dim>* main_container_;
26  // particles velocity
27  basic_scontainer<T_e, T_dim>* particles_v_;
28  // best solutions for each particle
29  basic_scontainer<T_e, T_dim>* particles_best_;
30  // groups best solution
31  basic_scontainer<T_e, T_dim>* groups_best_;
32  // best solution in the current node
33  basic_scontainer<T_e, T_dim>* node_best_;
34  // best current cluster solution
35  basic_scontainer<T_e, T_dim>* cluster_best_;
36 
37  // intertial
38  T_e hyper_w_;
39 
40 public:
41  basic_pso(system<T_e>* problem,
42  basic_scontainer<T_e, T_dim>* main_container,
43  basic_scontainer<T_e, T_dim>* particles_v,
44  basic_scontainer<T_e, T_dim>* particles_best,
45  basic_scontainer<T_e, T_dim>* groups_best,
47  basic_scontainer<T_e, T_dim>* cluster_best){
48  this->problem_ = problem;
49  this->main_container_ = main_container;
50  this->particles_v_ = particles_v;
51  this->particles_best_ = particles_best;
52  this->groups_best_ = groups_best;
53  this->node_best_ = node_best;
54  this->cluster_best_ = cluster_best;
55  }
56  T_e rand_uniform(){
57  static std::uniform_real_distribution<T_e> dist(0.0, 1.0);
58  return dist(rocky::utils::random::prng());
59  }
60  // initialize particles velocity to zero
61  virtual void initialize_velocity(){
62  for(int p=0; p<main_container_->n_particles(); ++p){
63  std::fill(particles_v_->particles[p].begin(), particles_v_->particles[p].end(), 0.0);
64  }
65  }
66  // reset the memory containers
67  virtual void reset(){
68  this->initialize_velocity();
69  }
70  // [todo] evaluate and update best solution of each particle in parallel
71  virtual void update_particles_best(int rng_start, int rng_end){
72  this->main_container_->evaluate_and_update(this->problem_);
73  tbb::parallel_for(rng_start, rng_end, [this](int p){
74  T_e val = this->main_container_->values[p];
75  if (val < this->particles_best_->values[p]){
76  this->particles_best_->values[p] = val;
77  // copy the particle solution
78  std::copy(this->main_container_->particle(p),
79  this->main_container_->particle(p) + T_dim,
80  this->particles_best_->particle(p));
81  }
82  });
83  }
84  virtual void update_particles_best(int rng_start=0){
85  update_particles_best(rng_start, main_container_->n_particles());
86  }
87  // update best groups solutions
88  virtual void update_groups_best(int rng_start, int rng_end){
89  tbb::parallel_for(rng_start, rng_end, [this](int t){
90  auto rng = this->main_container_->group_range(t);
91  auto min_el = std::min_element(this->particles_best_->value(rng.first),
92  this->particles_best_->value(rng.second));
93  if (*min_el < this->groups_best_->values[t]){
94  int min_el_ind = static_cast<int>(min_el - this->particles_best_->value(0));
95  this->groups_best_->values[t] = *min_el;
96  std::copy(this->particles_best_->particle(min_el_ind),
97  this->particles_best_->particle(min_el_ind)+T_dim,
98  this->groups_best_->particle(t));
99  }
100 
101  });
102  }
103  virtual void update_groups_best(){
104  update_groups_best(0, this->main_container_->n_groups());
105  }
106  template<update_mode T_um=use_groups>
107  void update_node_best(){
108  if constexpr(T_um == use_groups){
109  auto min_el = std::min_element(this->groups_best_->values.begin(),
110  this->groups_best_->values.end());
111  if (*min_el < this->node_best_->values[0]){
112  int min_el_ind = static_cast<int>(min_el - this->groups_best_->values.begin());
113  std::copy(this->groups_best_->particle(min_el_ind),
114  this->groups_best_->particle(min_el_ind)+T_dim,
115  this->node_best_->particle(0));
116  node_best_->values[0] = *min_el;
117  }
118  }
119  }
120  void update_cluster_best(){
121  if (this->node_best_->values[0] < this->cluster_best_->values[0]){
122  std::copy(this->node_best_->particle(0),
123  this->node_best_->particle(0)+T_dim,
124  this->cluster_best_->particle(0));
125  this->cluster_best_->values[0] = this->node_best_->values[0];
126  }
127  }
133  virtual void update_particles_v() = 0;
139  virtual void update_particles_x(){
140  tbb::parallel_for(0, this->main_container_->n_particles(), [this](int p){
141  eigen_particle x(this->main_container_->particle(p));
142  eigen_particle v(this->particles_v_->particle(p));
143  x += v;
144  });
145  }
146 };
147 
148 
149 template<typename T_e, int T_dim>
150 class pso_l1_strategy: public basic_pso<T_e, T_dim>{
151 
152 typedef Eigen::Map<Eigen::Matrix<T_e, 1, T_dim, Eigen::RowMajor>> eigen_particle;
153 protected:
154  virtual void update_particles_v(){
155  tbb::parallel_for(0, this->main_container_->n_particles(), [this](int p){
156  int p_group = this->main_container_->particle_group(p);
157  eigen_particle x(this->main_container_->particle(p));
158  eigen_particle v(this->particles_v_->particle(p));
159  eigen_particle p_best(this->particles_best_->particle(p));
160  eigen_particle p_best_gr(this->groups_best_->particle(p_group));
161  v = v * this->hyper_w_ + (2.0 * this->rand_uniform() * (p_best - x))
162  + (2.0 * this->rand_uniform() * (p_best_gr - x));
163  });
164  }
165 public:
166  pso_l1_strategy(system<T_e>* problem,
167  basic_scontainer<T_e, T_dim>* main_container,
168  basic_scontainer<T_e, T_dim>* particles_v,
169  basic_scontainer<T_e, T_dim>* particles_best,
170  basic_scontainer<T_e, T_dim>* groups_best,
171  basic_scontainer<T_e, T_dim>* node_best,
172  basic_scontainer<T_e, T_dim>* cluster_best):basic_pso<T_e, T_dim>(problem, main_container, particles_v, particles_best, groups_best, node_best, cluster_best){
173  }
174  virtual void apply(){
175  this->hyper_w_ = this->rand_uniform();
176  this->update_particles_best();
177  this->update_groups_best();
178  this->update_node_best();
179  this->update_cluster_best();
180  this->update_particles_v();
181  this->update_particles_x();
182  }
183 }; // End of PSO L1
184 
185 
186 template<typename T_e, int T_dim>
187 class pso_l2_strategy: public basic_pso<T_e, T_dim>{
188 
189 typedef Eigen::Map<Eigen::Matrix<T_e, 1, T_dim, Eigen::RowMajor>> eigen_particle;
190 protected:
191  virtual void update_particles_v(){
192  tbb::parallel_for(0, this->main_container_->n_particles(), [this](int p){
193  int p_group = this->main_container_->particle_group(p);
194  eigen_particle x(this->main_container_->particle(p));
195  eigen_particle v(this->particles_v_->particle(p));
196  eigen_particle p_best(this->particles_best_->particle(p));
197  eigen_particle p_best_gr(this->groups_best_->particle(p_group));
198  eigen_particle p_best_n(this->node_best_->particle(0));
199  if(this->particles_best_->values[p] == this->groups_best_->values[p_group]){
200  v = v * this->hyper_w_ + (2.0 * this->rand_uniform() * (p_best - x))
201  + (2.0 * this->rand_uniform() * (p_best_n - x));
202  }else{
203  v = v * this->hyper_w_ + (2.0 * this->rand_uniform() * (p_best - x))
204  + (2.0 * this->rand_uniform() * (p_best_gr - x));
205  }
206  });
207  }
208 public:
209  pso_l2_strategy(system<T_e>* problem,
210  basic_scontainer<T_e, T_dim>* main_container,
211  basic_scontainer<T_e, T_dim>* particles_v,
212  basic_scontainer<T_e, T_dim>* particles_best,
213  basic_scontainer<T_e, T_dim>* groups_best,
214  basic_scontainer<T_e, T_dim>* node_best,
215  basic_scontainer<T_e, T_dim>* cluster_best):basic_pso<T_e, T_dim>(problem, main_container, particles_v, particles_best, groups_best, node_best, cluster_best){
216  }
217  virtual void apply(){
218  this->hyper_w_ = this->rand_uniform();
219  this->update_particles_best();
220  this->update_groups_best();
221  this->update_node_best();
222  this->update_cluster_best();
223  this->update_particles_v();
224  this->update_particles_x();
225  }
226 }; // End of PSO L2
227 
228 template<typename T_e, int T_dim>
229 class pso_l3_strategy: public basic_pso<T_e, T_dim>{
230 
231 typedef Eigen::Map<Eigen::Matrix<T_e, 1, T_dim, Eigen::RowMajor>> eigen_particle;
232 protected:
233  virtual void update_particles_v(){
234  tbb::parallel_for(0, this->main_container_->n_particles(), [this](int p){
235  int p_group = this->main_container_->particle_group(p);
236  eigen_particle x(this->main_container_->particle(p));
237  eigen_particle v(this->particles_v_->particle(p));
238  eigen_particle p_best(this->particles_best_->particle(p));
239  eigen_particle p_best_gr(this->groups_best_->particle(p_group));
240  eigen_particle p_best_c(this->cluster_best_->particle(0));
241  if(this->particles_best_->values[p] == this->groups_best_->values[p_group]){
242  v = v * this->hyper_w_ + (2.0 * this->rand_uniform() * (p_best - x))
243  + (2.0 * this->rand_uniform() * (p_best_c - x));
244  }else{
245  v = v * this->hyper_w_ + (2.0 * this->rand_uniform() * (p_best - x))
246  + (2.0 * this->rand_uniform() * (p_best_gr - x));
247  }
248  });
249  }
250 public:
251  pso_l3_strategy(system<T_e>* problem,
252  basic_scontainer<T_e, T_dim>* main_container,
253  basic_scontainer<T_e, T_dim>* particles_v,
254  basic_scontainer<T_e, T_dim>* particles_best,
255  basic_scontainer<T_e, T_dim>* groups_best,
256  basic_scontainer<T_e, T_dim>* node_best,
257  basic_scontainer<T_e, T_dim>* cluster_best):basic_pso<T_e, T_dim>(problem, main_container, particles_v, particles_best, groups_best, node_best, cluster_best){
258  }
259  virtual void apply(){
260  this->hyper_w_ = this->rand_uniform();
261  this->update_particles_best();
262  this->update_groups_best();
263  this->update_node_best();
264  this->update_cluster_best();
265  this->update_particles_v();
266  this->update_particles_x();
267  }
268 }; // End of PSO L3
269 
270 };
271 };
272 
273 
274 #endif
rocky::zagros::basic_scontainer::group_range
std::pair< int, int > group_range(int g) const
starting and endind point of a group
Definition: scontainer.h:98
rocky::zagros::basic_scontainer::value
T_e * value(int p)
pointer to the value of a particle
Definition: scontainer.h:110
rocky::zagros::search_strategy
Interface for evolution strategies.
Definition: strategy.h:42
rocky::zagros::basic_pso
Base class for Tribes PSO.
Definition: pso.h:16
rocky::zagros::pso_l2_strategy
Definition: pso.h:187
rocky::zagros::pso_l3_strategy::update_particles_v
virtual void update_particles_v()
update particles velocity in parallel
Definition: pso.h:233
rocky::zagros::basic_pso::update_particles_v
virtual void update_particles_v()=0
update particles velocity in parallel
rocky::zagros::basic_scontainer
a data container representing a scontainer
Definition: scontainer.h:31
rocky::zagros::system
Definition: system.h:20
rocky::zagros::pso_l1_strategy::update_particles_v
virtual void update_particles_v()
update particles velocity in parallel
Definition: pso.h:154
rocky::zagros::basic_scontainer::evaluate_and_update
void evaluate_and_update(system< T_e > *problem, int rng_start, int rng_end)
evaluate and update the particles within a range
Definition: scontainer.h:205
rocky::zagros::pso_l2_strategy::update_particles_v
virtual void update_particles_v()
update particles velocity in parallel
Definition: pso.h:191
rocky::zagros::pso_l3_strategy
Definition: pso.h:229
rocky::zagros::basic_scontainer::particle
T_e * particle(int p)
get the starting address of a specific particle
Definition: scontainer.h:71
rocky::zagros::basic_pso::update_particles_x
virtual void update_particles_x()
update particles position in parallel
Definition: pso.h:139
rocky::zagros::pso_l1_strategy
Definition: pso.h:150