SOT
genetic_algorithm.h
1 
8 #ifndef SOT_GENETIC_ALGORITHM_H
9 #define SOT_GENETIC_ALGORITHM_H
10 
11 #include "experimental_design.h"
12 #include "common.h"
13 #include "utils.h"
14 #include <thread>
15 #include <mutex>
16 
18 namespace sot {
19 
21 
33  protected:
34  std::shared_ptr<Problem> mData;
35  std::shared_ptr<ExpDesign> mExpDes;
36  double mSigma = 0.2;
37  int mTournamentSize = 5;
38  double mpCross = 0.9;
39  double mpMutation;
40  int mDim;
46  std::string mName = "Genetic Algorithm";
47  bool mRandomInit;
49  int mEvalCount = 0;
50  std::mutex mMutex;
52 
57  void evalBatch(const mat &batch, vec &funVals) {
58  mMutex.lock();
59  int myEval = mEvalCount;
60  mEvalCount++;
61  mMutex.unlock();
62 
63  while(myEval < batch.n_cols) {
64  vec x = batch.col(myEval);
65  funVals[myEval] = mData->eval(x);
66 
67  mMutex.lock();
68  myEval = mEvalCount;
69  mEvalCount++;
70  mMutex.unlock();
71  }
72  }
73  public:
75 
80  GeneticAlgorithm(std::shared_ptr<Problem>& data, int numIndividuals, int numGenerations) {
81  mData = std::shared_ptr<Problem>(data);
82  mDim = data->dim();
83  mNumVariables = mDim;
84  mpMutation = 1.0/mDim;
85  mNumIndividuals = numIndividuals;
86  mNumGenerations = numGenerations;
87  mRandomInit = true;
88  mxLow = data->lBounds();
89  mxUp= data->uBounds();
90  mNumThreads = 1;
91  }
93 
99  GeneticAlgorithm(std::shared_ptr<Problem>& data, int numIndividuals, int numGenerations, int numThreads) :
100  GeneticAlgorithm(data, numIndividuals, numGenerations)
101  {
102  mNumThreads = numThreads;
103  }
105 
113  GeneticAlgorithm(std::shared_ptr<Problem>& data, std::shared_ptr<ExpDesign>& expDes,
114  int numIndividuals, int numGenerations) : GeneticAlgorithm(data, numIndividuals, numGenerations) {
115  mExpDes = std::shared_ptr<ExpDesign>(expDes);
116  if(expDes->numPoints() != mNumIndividuals) {
117  throw std::logic_error("Experimental design doesn't match the population size");
118  }
119  if(expDes->dim() != mNumVariables) {
120  throw std::logic_error("Experimental design has incorrect dimensionality");
121  }
122  mRandomInit = false;
123  }
125 
132  GeneticAlgorithm(std::shared_ptr<Problem>& data, std::shared_ptr<ExpDesign>& expDes,
133  int numIndividuals, int numGenerations, int numThreads) :
134  GeneticAlgorithm(data, expDes, numIndividuals, numGenerations)
135  {
136  mNumThreads = numThreads;
137  }
138 
140 
144  std::vector<std::thread> threads(mNumThreads);
145  Result res(mNumIndividuals * mNumGenerations, mDim);
146 
147  mat population;
148  mat newPopulation = arma::zeros<mat>(mNumVariables, mNumIndividuals);
149  if (mRandomInit) {
150  population.randu(mNumVariables, mNumIndividuals);
151  }
152  else{
153  population = mExpDes->generatePoints();
154  }
155  population = fromUnitBox(population, mxLow, mxUp);
156 
157  // Evaluate all individuals
158  vec functionValues = arma::zeros(mNumIndividuals);
159  if(mNumThreads > 1) {
160  mEvalCount = 0;
161  for(int i=0; i < mNumThreads; i++) {
162  threads[i] = std::thread(&sot::GeneticAlgorithm::evalBatch, this,
163  std::ref(population), std::ref(functionValues));
164  }
165 
166  for(int i=0; i < mNumThreads; i++) {
167  threads[i].join();
168  }
169  }
170  else {
171  functionValues = mData->evals(population);
172  }
173 
174  //Save the best individual
175  arma::uword ind;
176  functionValues.min(ind);
177  vec bestIndividual = population.col(ind);
178  double bestValue = functionValues(ind);
179 
180  for(int gen = 0; gen < mNumGenerations - 1; gen++) {
181 
183  arma::imat tournament = arma::randi<arma::imat>(mTournamentSize, mNumIndividuals,
184  arma::distr_param(0, mNumIndividuals - 1));
185  for(int i = 0; i < mNumIndividuals/2; i++) {
186  double minval1 = std::numeric_limits<double>::max();
187  double minval2 = std::numeric_limits<double>::max();
188  int ind1 = randi(mNumIndividuals - 1);
189  int ind2 = randi(mNumIndividuals - 1);
190  for(int j=0; j < mTournamentSize; j++) {
191  if (functionValues(tournament(j, 2*i)) < minval1) {
192  minval1 = functionValues(tournament(j, 2*i));
193  ind1 = tournament(j, 2*i);
194  }
195  if (functionValues(tournament(j, 2*i + 1)) < minval2) {
196  minval2 = functionValues(tournament(j, 2*i + 1));
197  ind2 = tournament(j, 2*i + 1);
198  }
199  }
200  double alpha = rand();
201  if( rand() < mpCross) {
202  newPopulation.col(2*i) = alpha * population.col(ind1) + (1 - alpha) * population.col(ind2);
203  newPopulation.col(2*i + 1) = alpha * population.col(ind2) + (1 - alpha) * population.col(ind1);
204  }
205  else {
206  newPopulation.col(2*i) = population.col(ind1);
207  newPopulation.col(2*i + 1) = population.col(ind2);
208  }
209  }
210 
211  // Mutation
212  for(int i=0; i < mNumIndividuals; i++) {
213  for(int j=0; j<mNumVariables; j++) {
214  if(rand() < mpMutation) {
215  newPopulation(j, i) += (mxUp(j) - mxLow(j)) * mSigma * randn();
216  if(newPopulation(j,i) > mxUp(j)) {
217  newPopulation(j,i) = fmax(2*mxUp(j) - newPopulation(j,i), mxLow(j));
218  }
219  else if(newPopulation(j,i) < mxLow(j)) {
220  newPopulation(j,i) = fmin(2*mxLow(j) - newPopulation(j,i), mxUp(j));
221  }
222  }
223  }
224  }
225 
226  // Elitism
227  newPopulation.col(mNumIndividuals - 1) = bestIndividual;
228 
229  // Evaluate all individuals
230  if(mNumThreads > 1) {
231  mEvalCount = 0;
232  for(int i=0; i < mNumThreads; i++) {
233  threads[i] = std::thread(&sot::GeneticAlgorithm::evalBatch, this,
234  std::ref(newPopulation), std::ref(functionValues));
235  }
236 
237  for(int i=0; i < mNumThreads; i++) {
238  threads[i].join();
239  }
240  }
241  else {
242  functionValues = mData->evals(newPopulation);
243  }
244 
245  // Save the results
246  for(int i=0; i < mNumIndividuals; i++) {
247  vec x = newPopulation.col(i);
248  res.addEval(x, functionValues(i));
249  }
250 
251  //Save the best individual
252  arma::uword ind;
253  functionValues.min(ind);
254  bestIndividual = newPopulation.col(ind);
255  bestValue = functionValues(ind);
256 
257  // Kill the old population
258  population = newPopulation;
259  }
260 
261  return res;
262  }
263  };
264 }
265 
266 #endif
Optimization result class.
Definition: utils.h:138
GeneticAlgorithm(std::shared_ptr< Problem > &data, int numIndividuals, int numGenerations, int numThreads)
Constructor.
Definition: genetic_algorithm.h:99
GeneticAlgorithm(std::shared_ptr< Problem > &data, int numIndividuals, int numGenerations)
Constructor.
Definition: genetic_algorithm.h:80
arma::vec vec
Default (column) vector class.
Definition: common.h:17
vec mxUp
Definition: genetic_algorithm.h:42
void evalBatch(const mat &batch, vec &funVals)
Evalaute a batch of points in parallel.
Definition: genetic_algorithm.h:57
vec mxLow
Definition: genetic_algorithm.h:41
double mpCross
Definition: genetic_algorithm.h:38
int mEvalCount
Definition: genetic_algorithm.h:49
GeneticAlgorithm(std::shared_ptr< Problem > &data, std::shared_ptr< ExpDesign > &expDes, int numIndividuals, int numGenerations)
Constructor.
Definition: genetic_algorithm.h:113
double rand()
Generate a U[0,1] realization.
Definition: utils.h:386
double randi(int i)
Generate a random integer.
Definition: utils.h:364
Genetic Algorithm.
Definition: genetic_algorithm.h:32
std::shared_ptr< Problem > mData
Definition: genetic_algorithm.h:34
double mpMutation
Definition: genetic_algorithm.h:39
GeneticAlgorithm(std::shared_ptr< Problem > &data, std::shared_ptr< ExpDesign > &expDes, int numIndividuals, int numGenerations, int numThreads)
Constructor.
Definition: genetic_algorithm.h:132
int mDim
Definition: genetic_algorithm.h:40
int mNumIndividuals
Definition: genetic_algorithm.h:44
int mTournamentSize
Definition: genetic_algorithm.h:37
vec fromUnitBox(const vec &x, const vec &xLow, const vec &xUp)
Map one point from the unit box to another hypercube.
Definition: utils.h:94
double randn()
Generate a N(0,1) realization.
Definition: utils.h:375
Result run()
Runs the optimization algorithm.
Definition: genetic_algorithm.h:143
void addEval(const vec &x, double funVal)
Method for adding a finished evaluation.
Definition: utils.h:227
SOT namespace.
Definition: sot.h:27
double mSigma
Definition: genetic_algorithm.h:36
arma::mat mat
Default matrix class.
Definition: common.h:16
std::shared_ptr< ExpDesign > mExpDes
Definition: genetic_algorithm.h:35
int mNumThreads
Definition: genetic_algorithm.h:48
std::mutex mMutex
Definition: genetic_algorithm.h:50
int mNumGenerations
Definition: genetic_algorithm.h:45
std::string mName
Definition: genetic_algorithm.h:46
int mNumVariables
Definition: genetic_algorithm.h:43
bool mRandomInit
Definition: genetic_algorithm.h:47