IAtari
Genetic algorithm generating AI capable to play Atari2600 games.
fitness.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "message.hpp"
4 #include "master.hpp"
5 #include <boost/asio/spawn.hpp>
6 #include <boost/interprocess/sync/interprocess_semaphore.hpp>
7 #include <vector>
8 #include <memory>
9 #include <functional>
10 #include <atomic>
11 #include <thread>
12 #include <numeric>
13 
25 namespace genetic_algorithms
26 {
27  template <typename Res, typename Params>
34  std::function<Res(const std::list<Res>&)> accumulate;
35  std::vector<Params> params;
36  std::vector<std::list<Res>> results;
37  boost::interprocess::interprocess_semaphore ready;
38  boost::interprocess::interprocess_semaphore processed;
39  bool stop = false;
40  std::atomic<bool> last;
42  public:
50  distributed_fitness(std::function<Res(const std::list<Res>&)> accumulate);
51 
58  bool finished();
59 
68  std::vector<Params> get_parameters(boost::asio::yield_context yield);
69 
77  void set_results(std::vector<std::list<Res>> res,
78  boost::asio::yield_context yield);
79 
89  void run(int i, int nb_iterations,
90  const std::vector<Params>& population,
91  std::vector<Res>& results);
92  };
93 
94  template <typename Res, typename Params>
95  distributed_fitness<Res, Params>::distributed_fitness(std::function<Res(const std::list<Res>&)> accumulate)
96  : accumulate(accumulate),
97  ready(0), processed(0), last(false)
98  {
99  }
100 
101  template <typename Res, typename Params>
103  {
104  return stop;
105  }
106 
107  template <typename Res, typename Params>
108  std::vector<Params> distributed_fitness<Res, Params>::get_parameters(boost::asio::yield_context)
109  {
110  ready.wait();
111  return params;
112  }
113 
114  template <typename Res, typename Params>
115  void distributed_fitness<Res, Params>::set_results(std::vector<std::list<Res>> res,
116  boost::asio::yield_context)
117  {
118  results = res;
119  processed.post();
120  if (last) stop = true;
121  }
122 
123  template <typename Res, typename Params>
124  void distributed_fitness<Res, Params>::run(int i, int nb_iterations,
125  const std::vector<Params>& population,
126  std::vector<Res>& res)
127  {
128  params.clear(); //Clear the vector of agents
129  for (const auto& p : population) //Fill the vector of agents with the new population
130  {
131  params.emplace_back(p);
132  }
133  ready.post();
134  if (i == nb_iterations) last = true;
135  processed.wait();
136  for (unsigned int i = 0; i < results.size(); ++i) //Put mean of each agent results list in a vector
137  {
138  res[i] = accumulate(results[i]);
139  }
140  }
141 
142  template <typename Res, typename Params>
152  std::shared_ptr<distributed_fitness<Res, Params>> make_distributed_fitness(int port,
153  std::function<Res(const std::list<Res>&)> accumulate,
154  int nb_eval_by_parameter = 1, int nb_eval_by_slave = 1)
155  {
156  auto fitness = std::make_shared<distributed_fitness<Res, Params>>(accumulate); //Create an object distributed_fitness with accumulate as an attribute
157  std::thread t([=]{ master<Res, Params>(port, nb_eval_by_parameter, nb_eval_by_slave).run(fitness); }); //Create a thread with a master and run it
158  t.detach(); //Give independance to the thread
159  return fitness;
160  }
161 
167  namespace accumulate
168  {
169  template <typename T>
177  double mean_score(const std::list<T>& l)
178  {
179  return std::accumulate(l.begin(), l.end(), T{}, std::plus<T>()) / (double)l.size();
180  }
181  }
182 }
std::vector< std::list< Res > > results
Definition: fitness.hpp:36
void set_results(std::vector< std::list< Res >> res, boost::asio::yield_context yield)
Increments processed, set the results and stop the algorithm if last is true.
Definition: fitness.hpp:115
boost::interprocess::interprocess_semaphore processed
Definition: fitness.hpp:38
void run(Client client)
Start a coroutine handling incoming slave connection and a coroutine handling the tests.
Definition: master.hpp:219
std::vector< Params > params
Definition: fitness.hpp:35
Handle score computing and flow control of the algorithm.
Handle flow control of the algorithm.
Definition: fitness.hpp:33
Handle the master part.
std::atomic< bool > last
Definition: fitness.hpp:40
bool finished()
Get the value of stop, i.e. if the algorithm is finished or not.
Definition: fitness.hpp:102
std::function< Res(const std::list< Res > &)> accumulate
Definition: fitness.hpp:34
bool stop
Definition: fitness.hpp:39
boost::interprocess::interprocess_semaphore ready
Definition: fitness.hpp:37
double mean_score(const std::list< T > &l)
Compute the mean of a list of values.
Definition: fitness.hpp:177
std::vector< Params > get_parameters(boost::asio::yield_context yield)
Decrements ready and get the parameters of the genetic algorithm.
Definition: fitness.hpp:108
void run(int i, int nb_iterations, const std::vector< Params > &population, std::vector< Res > &results)
Manage a batch test of agents.
Definition: fitness.hpp:124
Handle serializable representations of agents.
Master part of the algorithm, handle server-side connection and redistribute evenly the tests to the ...
Definition: master.hpp:26
std::shared_ptr< distributed_fitness< Res, Params > > make_distributed_fitness(int port, std::function< Res(const std::list< Res > &)> accumulate, int nb_eval_by_parameter=1, int nb_eval_by_slave=1)
Creates a fitness tool and launches a master in a separate thread.
Definition: fitness.hpp:152
distributed_fitness(std::function< Res(const std::list< Res > &)> accumulate)
Standard Constructor. Initialize the accumulate function, set last to false and set ready and process...
Definition: fitness.hpp:95