Samchon Framework for CPP  1.0.0
GeneticAlgorithm.hpp
1 #pragma once
2 #include <samchon/library/GAPopulation.hpp>
3 
4 #include <set>
5 #include <random>
6 #include <samchon/library/Math.hpp>
7 
8 namespace samchon
9 {
10 namespace library
11 {
65  template <typename GeneArray, typename Compare = std::less<GeneArray>, typename Gene = GeneArray::value_type>
67  {
68  public:
70 
71  private:
72  std::vector<Gene> candidates;
73 
77  bool unique;
78 
90  double mutationRate;
91 
95  size_t tournament;
96 
97  public:
107  GeneticAlgorithm(const std::vector<Gene> &candidates, bool unique, double mutationRate = 0.015, size_t tournament = 10)
108  {
109  this->candidates = candidates;
110  this->unique = unique;
111 
112  this->mutationRate = mutationRate;
113  this->tournament = tournament;
114  };
115 
124  GeneticAlgorithm(bool unique, double mutationRate = 0.015, size_t tournament = 10)
125  {
126  this->unique = unique;
127  this->mutationRate = mutationRate;
128  this->tournament = tournament;
129  };
130 
141  inline auto evolveGeneArray(std::shared_ptr<GeneArray> geneArray, size_t population, size_t generation) const -> std::shared_ptr<GeneArray>
142  {
143  std::shared_ptr<Population> myPopulation(new Population(geneArray, population));
144 
145  for (size_t i = 0; i < generation; i++)
146  myPopulation = evolvePopulation(myPopulation);
147 
148  return myPopulation->fitTest();
149  };
150 
157  auto evolvePopulation(std::shared_ptr<Population> population) const -> std::shared_ptr<Population>
158  {
159  size_t size = population->children.size();
160  std::shared_ptr<Population> evolved(new Population(size));
161 
162  //ELITICISM
163  evolved->children[0] = population->fitTest();
164 
165  #pragma omp parallel for
166  for (int i = 1; i < size; i++)
167  {
168  std::shared_ptr<GeneArray> &gene1 = selection(population);
169  std::shared_ptr<GeneArray> &gene2 = selection(population);
170 
171  std::shared_ptr<GeneArray> &child = crossover(gene1, gene2);
172  mutate(child);
173 
174  evolved->children[i] = child;
175  }
176 
177  /*#pragma omp parallel for
178  for (int i = 1; i < size; i++)
179  mutate(evolved->children[i]);*/
180 
181  return evolved;
182  };
183 
184  private:
215  auto selection(std::shared_ptr<Population> population) const -> std::shared_ptr<GeneArray>
216  {
217  size_t size = population->children.size();
218  Population tornament(size);
219 
220  for (size_t i = 0; i < size; i++)
221  {
222  size_t randomIndex = (size_t)(Math::random() * size);
223  if (randomIndex == size)
224  randomIndex--;
225 
226  tornament.children[i] = population->children[randomIndex];
227  }
228  return tornament.fitTest();
229  };
230 
247  auto crossover(std::shared_ptr<GeneArray> &parent1, std::shared_ptr<GeneArray> &parent2) const -> std::shared_ptr<GeneArray>
248  {
249  std::shared_ptr<GeneArray> geneArray(new GeneArray(*parent1));
250  size_t size = parent1->size();
251 
252  if (unique == false)
253  {
254  for (size_t i = 0; i < size; i++)
255  if (Math::random() > .5)
256  geneArray->at(i) = parent2->at(i);
257  }
258  else
259  {
260  std::set<GeneArray::value_type> ptrSet;
261  std::set<size_t> indexSet;
262 
263  size_t start = (size_t)(Math::random() * size);
264  size_t end = (size_t)(Math::random() * size);
265 
266  //INDEXING
267  for (size_t i = 0; i < size; i++)
268  if (start < i && i < end)
269  ptrSet.insert(parent1->at(i));
270  else
271  indexSet.insert(i);
272 
273  //INSERT PARENT_2
274  for (size_t i = 0; i < size; i++)
275  {
276  GeneArray::value_type &ptr = parent2->at(i);
277  if (ptrSet.find(ptr) != ptrSet.end())
278  continue;
279 
280  geneArray->at(*indexSet.begin()) = ptr;
281  indexSet.erase(indexSet.begin());
282  }
283  }
284  return geneArray;
285  };
286 
287  protected:
318  virtual void mutate(std::shared_ptr<GeneArray> geneArray) const
319  {
320  for (size_t i = 0; i < geneArray->size(); i++)
321  {
322  if (Math::random() > mutationRate)
323  continue;
324 
325  if (candidates.empty() == true)
326  {
327  // WHEN CANDIDATES ARE NOT SPECIFIED, JUST SHUFFLE SEQUENCE OF GENES
328  size_t j = (size_t)(Math::random() * geneArray->size());
329  std::swap(geneArray->at(i), geneArray->at(j));
330  }
331  else if (unique == false)
332  {
333  // PICK A CANDIDATE
334  geneArray->at(i) = candidates.at((size_t)(Math::random() * candidates.size()));
335  }
336  else // HAS CANDIDATES AND NEED TO BE UNIQUE
337  {
338  Gene item;
339  bool duplicated = true;
340 
341  // PICK ONE
342  while (duplicated == true)
343  {
344  item = candidates.at((size_t)(Math::random() * candidates.size()));
345 
346  duplicated = false;
347 
348  for (size_t j = 0; j < geneArray->size(); j++)
349  if (i != j && geneArray->at(i) == geneArray->at(j))
350  {
351  duplicated = true;
352  break;
353  }
354  }
355 
356  geneArray->at(i) = item;
357  }
358  }
359  };
360  };
361 };
362 };
static auto random() -> double
Get a random value.
Definition: Math.cpp:38
double mutationRate
Rate of mutate ocurrence.
auto fitTest() const -> std::shared_ptr< GeneArray >
Test fitness of each GeneArray in the population.
GeneticAlgorithm(bool unique, double mutationRate=0.015, size_t tournament=10)
Construct from parameters of Genetic Algorithm.
auto selection(std::shared_ptr< Population > population) const -> std::shared_ptr< GeneArray >
Select the best GeneArray in population from tournament.
A population of a generation in G.A.
A genetic algorithm class.
bool unique
Whether each element (Gene) is unique in their GeneArray.
virtual void mutate(std::shared_ptr< GeneArray > geneArray) const
Cause a mutation on the GeneArray.
std::vector< std::shared_ptr< GeneArray > > children
Genes representing the population.
auto crossover(std::shared_ptr< GeneArray > &parent1, std::shared_ptr< GeneArray > &parent2) const -> std::shared_ptr< GeneArray >
Create a new GeneArray by crossing over two GeneArray(s)
auto evolvePopulation(std::shared_ptr< Population > population) const -> std::shared_ptr< Population >
Evolve population, a mass of GeneArray(es)
GeneticAlgorithm(const std::vector< Gene > &candidates, bool unique, double mutationRate=0.015, size_t tournament=10)
Construct from parameters of Genetic Algorithm.
size_t tournament
Size of tournament in selection.
Top level namespace of products built from samchon.
Definition: ByteArray.hpp:7
auto evolveGeneArray(std::shared_ptr< GeneArray > geneArray, size_t population, size_t generation) const -> std::shared_ptr< GeneArray >
Evolve a GeneArray.