RockyML  0.0.1
A High-Performance Scientific Computing Framework
genetic.h
1 /*
2  Copyright (C) 2022 Amirabbas Asadi , All Rights Reserved
3  distributed under Apache-2.0 license
4 */
5 #ifndef ROCKY_ZAGROS_GENETIC_STRATEGY
6 #define ROCKY_ZAGROS_GENETIC_STRATEGY
7 #include <rocky/zagros/strategies/strategy.h>
8 #include <set>
9 #include <iterator>
10 
11 namespace rocky{
12 namespace zagros{
13 
18 template<typename T_e, int T_dim>
19 class mutation_strategy: public basic_strategy<T_e, T_dim>{};
20 
25 template<typename T_e, int T_dim>
26 class dimension_tweak_strategy: public mutation_strategy<T_e, T_dim>{
27 protected:
28  // system
29  system<T_e>* problem_;
30  // main container
31  basic_scontainer<T_e, T_dim>* target_container_;
32  // candidate container
33  basic_scontainer<T_e, T_dim>* candidates_;
34  // number of mutations
35  int n_mutations_;
36  // number of affected dimensions
37  int k_;
38 public:
40  this->problem_ = problem;
41  this->target_container_ = tgt_container;
42  this->candidates_ = cnd_container;
43  this->k_ = k;
44  this->n_mutations_ = cnd_container->n_particles();
45  }
46  virtual void tweak(int p_ind, int dim) = 0;
47  virtual void apply(){
48  tbb::parallel_for(0, n_mutations_, [this](int p){
49  int samples[1];
50  this->target_container_->sample_n_particles(samples, 1);
51  std::copy(this->target_container_->particle(samples[0]),
52  this->target_container_->particle(samples[0])+T_dim,
53  this->candidates_->particle(p));
54  // apply mutation on k dimensions
55  for(int d=0; d<k_; d++){
56  // choose a random dim
57  int dim = this->target_container_->sample_dim();
58  this->tweak(p, dim);
59  }
60  });
61  candidates_->evaluate_and_update(problem_);
62  target_container_->replace_with(candidates_);
63  }
64 };
65 
66 
71 template<typename T_e, int T_dim>
72 class gaussian_mutation: public dimension_tweak_strategy<T_e, T_dim>{
73 protected:
74  T_e mu_;
75  T_e sigma_;
76 public:
77  gaussian_mutation(system<T_e>* problem, basic_scontainer<T_e, T_dim>* tgt_container, basic_scontainer<T_e, T_dim>* cnd_container, int k=1, T_e mu=0.0, T_e sigma=0.5)
78  :dimension_tweak_strategy<T_e, T_dim>(problem, tgt_container, cnd_container, k){
79  this->mu_ = mu;
80  this->sigma_ = sigma;
81  }
82  // generate gaussian noise
83  T_e gaussian_noise(){
84  static std::normal_distribution<T_e> dist(mu_, sigma_);
85  auto z = dist(rocky::utils::random::prng());
86  return z;
87  }
88  virtual void tweak(int p_ind, int dim){
89  this->candidates_->particles[p_ind][dim] += gaussian_noise();
90  }
91 };
92 
97 template<typename T_e, int T_dim>
98 class crossover_strategy: public basic_strategy<T_e, T_dim>{};
99 
104 template<typename T_e, int T_dim>
105 class multipoint_crossover: public crossover_strategy<T_e, T_dim>{
106 protected:
107  // system
108  system<T_e>* problem_;
109  // main container
110  basic_scontainer<T_e, T_dim>* container_;
111  // condidates container
112  basic_scontainer<T_e, T_dim>* candidates_;
113  // number of crossovers
114  int n_crossovers_;
115  // maximum number of affected dimensions
116  int k_;
117 public:
119  this->k_ = k;
120  this->problem_ = problem;
121  this->container_ = container;
122  this->candidates_ = candidates;
123  this->n_crossovers_ = candidates->n_particles() / 2;
124  }
125  virtual void apply(){
126  tbb::parallel_for(0, n_crossovers_, [this](int p){
127  int parents[2];
128  this->container_->sample_n_particles(parents, 2);
129  // copy thee parents
130  for(int i=0; i<2; i++)
131  std::copy(this->container_->particle(parents[i]),
132  this->container_->particle(parents[i])+T_dim,
133  this->candidates_->particle(2*p+i));
134  // affected dims
135  std::set<int> dims;
136  for(int d=0; d<k_; d++)
137  dims.insert(this->container_->sample_dim());
138  // apply the crossover
139  for(auto dim: dims)
140  std::swap(this->candidates_->particles[parents[0]][dim],
141  this->candidates_->particles[parents[1]][dim]);
142  });
143  container_->replace_with(candidates_);
144  }
145 };
146 
147 
148 template<typename T_e, int T_dim>
150 protected:
151  // system
152  system<T_e>* problem_;
153  // main container
154  basic_scontainer<T_e, T_dim>* container_;
155  // main container
156  basic_scontainer<T_e, T_dim>* candidates_;
157  // length of the segment for crossover
158  int segment_length_;
159  // number of crossovers
160  int n_crossovers_;
161 public:
162  static_segment_crossover(system<T_e>* problem, basic_scontainer<T_e, T_dim>* container, basic_scontainer<T_e, T_dim>* cnd_container, int segment_length){
163  this->n_crossovers_ = cnd_container->n_particles() / 2;
164  this->segment_length_ = segment_length;
165  this->problem_ = problem;
166  this->container_ = container;
167  this->candidates_ = cnd_container;
168  }
169  virtual void apply(){
170  tbb::parallel_for(0, n_crossovers_, [this](auto ci){
171  // select two distinct parents
172  int parents[2];
173  this->container_->sample_n_particles(parents, 2);
174  // select a random point for cross over
175  std::uniform_int_distribution<> point_dist(0, T_dim - segment_length_ - 1);
176  int point = point_dist(rocky::utils::random::prng());
177  // produce two cantidates
178  for(int i=0; i<2; i++){
179  // copy the solution
180  std::copy(this->container_->particle(parents[i]),
181  this->container_->particle(parents[i])+T_dim,
182  this->candidates_->particle(2*ci+i));
183  // replace the segment
184  std::copy(this->container_->particle(parents[1-i])+point,
185  this->container_->particle(parents[1-i])+point+segment_length_,
186  this->candidates_->particle(2*ci+i)+point);
187  }
188  });
189  // evaluate the candidates
190  this->candidates_->evaluate_and_update(problem_);
191  this->container_->replace_with(this->candidates_);
192  }
193 };
194 
195 };
196 };
197 #endif
rocky::zagros::multipoint_crossover
Multipoint crossover.
Definition: genetic.h:105
rocky::zagros::mutation_strategy
Base class for genetic mutations.
Definition: genetic.h:19
rocky::zagros::dimension_tweak_strategy
apply a mutation to k dimensions
Definition: genetic.h:26
rocky::zagros::basic_scontainer::sample_n_particles
void sample_n_particles(int *indices, int n=1)
sample n distinct particles from a group efficient when n is small
Definition: scontainer.h:119
rocky::zagros::basic_scontainer::replace_with
void replace_with(basic_scontainer< T_e, T_dim > *cnt)
replace the best values from another container
Definition: scontainer.h:266
rocky::zagros::basic_scontainer::sample_dim
int sample_dim()
choose a dimension randomly
Definition: scontainer.h:167
rocky::zagros::basic_scontainer
a data container representing a scontainer
Definition: scontainer.h:31
rocky::zagros::system
Definition: system.h:20
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::basic_strategy
Interface for all strategies.
Definition: strategy.h:31
rocky::zagros::crossover_strategy
Base class for genetic crossovers.
Definition: genetic.h:98
rocky::zagros::basic_scontainer::particle
T_e * particle(int p)
get the starting address of a specific particle
Definition: scontainer.h:71
rocky::zagros::gaussian_mutation
Gaussian mutation.
Definition: genetic.h:72
rocky::zagros::static_segment_crossover
Definition: genetic.h:149