Grail (C++)  1.4.0
A multi-platform, modular, universal engine for embedding advanced AI in games.
EAOptimizer.hh
1 // Copyright QED Software 2023.
2 
3 #ifndef GRAIL_EA_OPTIMIZER_H
4 #define GRAIL_EA_OPTIMIZER_H
5 
6 #include "Crossover.hh"
7 #include "Individual.hh"
8 #include "Mutation.hh"
9 #include "Selection.hh"
10 
11 #include <functional>
12 #include <fstream>
13 #include <sstream>
14 #include <memory>
15 #include <iostream>
16 #include <memory>
17 #include <random>
18 #include <vector>
19 
20 namespace grail
21 {
22 namespace evolution
23 {
24  struct Mutation;
25  struct Crossover;
26  class Selection;
27  class Individual;
28 
32  enum class ElitismType
33  {
36  NONE,
39  FITNESS_RANKING,
43  ROULETTE
44  };
45 
49  class EAOptimizer final
50  {
51  public:
61  EAOptimizer(std::vector<std::unique_ptr<Individual>>& initialPopulation,
62  size_t maxEpochCount,
63  std::unique_ptr<Crossover> crossover = std::make_unique<Crossover>(),
64  std::unique_ptr<Mutation> mutation = std::make_unique<Mutation>(),
65  std::unique_ptr<Selection> selection = std::make_unique<Selection>(),
66  std::mt19937_64::result_type seed = std::random_device{}());
67 
72  void RunInteractive(std::function<void(Individual& individualToEvaluate)> onEvaluateNeeded,
73  std::function<void(void)> onFinished = nullptr,
74  std::function<void(void)> onNewEpoch = nullptr);
79  size_t GetPopulationSize() const;
80 
82  std::vector<std::unique_ptr<Individual>> GetPopulation() const;
83 
88  void SetElitism(double rate, ElitismType type);
89 
91  double GetElitismRate() const;
92 
94  ElitismType GetElitismType() const;
95 
99  float CalculatePopulationDiversity() const;
100 
105 
110 
114  const Individual& GetBestIndividual() const;
115 
117  size_t GetEpochNumber() const;
118 
120  size_t GetMaxEpochCount() const;
121 
125  Crossover& GetCrossover() const;
126 
130  Mutation& GetMutation() const;
131 
135  Selection& GetSelection() const;
136 
140  void SerializeState(const std::string& filename) const;
141 
146  bool DeserializeState(const std::string& filename);
147 
151  friend std::ostream& operator<<(std::ostream& out, const EAOptimizer& eaOptimizer);
152 
153  private:
154  template<class T>
155  void DeserializeSimpleValue(std::ifstream& fileStream, T& value)
156  {
157  std::string line;
158  std::getline(fileStream, line);
159  std::istringstream stringStreamLine(line);
160  stringStreamLine >> std::skipws >> line >> value;
161  }
162 
163  void AddPopulation(std::vector<std::unique_ptr<Individual>>& destination,
164  std::vector<std::unique_ptr<Individual>>& source) const;
165  void SelectPopulation();
166  void CrossoverPopulation();
167  void MutatePopulation();
168 
169  float CalculateAverageDiversity(const std::vector<std::unique_ptr<Individual>>& population) const;
170  size_t CalculateIdenticalFront(const std::vector<std::unique_ptr<Individual>>& population) const;
171 
172  private:
173  Individual* FindFirstNotUpdated(const std::vector<std::unique_ptr<Individual>>& population) const;
174 
175  std::vector<std::unique_ptr<Individual>> corePopulation{};
176  std::vector<std::unique_ptr<Individual>> emptyPopulation{};
177 
178  size_t epochNumber = 0;
179  size_t maxEpoch = 1;
180  size_t populationCount = 0;
181  bool evaluationInProgress = false;
182 
183  double elitismRate = 0.2;
184  ElitismType elitismType = ElitismType::ROULETTE;
185 
186  std::unique_ptr<Crossover> crossover;
187  std::unique_ptr<Mutation> mutation;
188  std::unique_ptr<Selection> selection;
189 
190  std::mt19937_64 randGen;
191  };
192 }
193 }
194 #endif // GRAIL_EA_OPTIMIZER_H
grail::evolution::EAOptimizer::GetMutation
Mutation & GetMutation() const
GetMutation - gets the mutation instance that is used by this evolutionary algorithm.
Definition: EAOptimizer.cpp:185
grail::evolution::Crossover
The Crossover structure that encapsulates the crossover operation and its configuration in evolutiona...
Definition: Crossover.hh:40
grail::evolution::EAOptimizer::GetPopulation
std::vector< std::unique_ptr< Individual > > GetPopulation() const
Definition: EAOptimizer.cpp:111
grail::evolution::EAOptimizer::GetElitismRate
double GetElitismRate() const
Definition: EAOptimizer.cpp:131
grail::evolution::EAOptimizer::GetSelection
Selection & GetSelection() const
GetSelection - gets the selection instance that is used by this evolutionary algorithm.
Definition: EAOptimizer.cpp:190
grail::evolution::EAOptimizer::SerializeState
void SerializeState(const std::string &filename) const
Serializes the inner state of the evolutionary algorithm, including the current population....
Definition: EAOptimizer.cpp:195
grail::evolution::EAOptimizer::GetElitismType
ElitismType GetElitismType() const
Definition: EAOptimizer.cpp:136
grail::evolution::EAOptimizer::GetCrossover
Crossover & GetCrossover() const
GetCrossover - gets the crossover instance that is used by this evolutionary algorithm.
Definition: EAOptimizer.cpp:180
grail::evolution::EAOptimizer::GetBestIndividual
const Individual & GetBestIndividual() const
GetBestIndividual - gets the individual with the highest fitness value from the population.
Definition: EAOptimizer.cpp:156
grail::evolution::EAOptimizer::CalculatePopulationIdenticalFrontRatio
float CalculatePopulationIdenticalFrontRatio() const
Returns the number of the most frequent identical individuals divided by the population size.
Definition: EAOptimizer.cpp:151
grail::evolution::Individual
Represents an individual for evolutionary algorithms (EA). It stores the encoding consisting of opti...
Definition: Individual.hh:23
grail::evolution::EAOptimizer::CalculatePopulationIdenticalFrontCount
size_t CalculatePopulationIdenticalFrontCount() const
Finds the most frequent individuals (which are identical to each other) and returns the number of the...
Definition: EAOptimizer.cpp:146
grail::evolution::EAOptimizer::RunInteractive
void RunInteractive(std::function< void(Individual &individualToEvaluate)> onEvaluateNeeded, std::function< void(void)> onFinished=nullptr, std::function< void(void)> onNewEpoch=nullptr)
Advances the computations of the evolutionary algorithm (EA). This is the main method to run it....
Definition: EAOptimizer.cpp:49
grail::evolution::EAOptimizer::CalculatePopulationDiversity
float CalculatePopulationDiversity() const
Returns the diversity ratio as a number [0,1]. The lower the value, the population is more homogeneou...
Definition: EAOptimizer.cpp:141
grail::evolution::Mutation
The Mutation structure that encapsulates the mutation operation and its configuration in evolutionary...
Definition: Mutation.hh:20
grail::evolution::EAOptimizer::DeserializeState
bool DeserializeState(const std::string &filename)
Loads a previously serialized state of the evolutionary algorithm. You can, for instance,...
Definition: EAOptimizer.cpp:223
grail::evolution::EAOptimizer::GetPopulationSize
size_t GetPopulationSize() const
PopulationSize - returns the number of individuals in the current population.
Definition: EAOptimizer.cpp:106
grail::evolution::EAOptimizer::SetElitism
void SetElitism(double rate, ElitismType type)
SetElitism - sets how many individuals advance to the next generation in an unmodified form and how t...
Definition: EAOptimizer.cpp:125
grail::evolution::Selection
The Selection class encapsulates the selection operation, i.e., how individuals are selected from the...
Definition: Selection.hh:19
grail::evolution::EAOptimizer::GetEpochNumber
size_t GetEpochNumber() const
Definition: EAOptimizer.cpp:170
grail::evolution::EAOptimizer::EAOptimizer
EAOptimizer(std::vector< std::unique_ptr< Individual >> &initialPopulation, size_t maxEpochCount, std::unique_ptr< Crossover > crossover=std::make_unique< Crossover >(), std::unique_ptr< Mutation > mutation=std::make_unique< Mutation >(), std::unique_ptr< Selection > selection=std::make_unique< Selection >(), std::mt19937_64::result_type seed=std::random_device{}())
The EA algorithm will maintain the size of the initial population after the selection phase.
Definition: EAOptimizer.cpp:19
grail::evolution::EAOptimizer::GetMaxEpochCount
size_t GetMaxEpochCount() const
Definition: EAOptimizer.cpp:175
grail::evolution::EAOptimizer
A class that serves as the main interface for evolutionary algorithms in Grail.
Definition: EAOptimizer.hh:49
grail::evolution::EAOptimizer::operator<<
friend std::ostream & operator<<(std::ostream &out, const EAOptimizer &eaOptimizer)
Appends to stream the serialized state of the evolutionary algorithm including the whole population a...
Definition: EAOptimizer.cpp:271