Darwin Neuroevolution Framework
darwin.h
1 // Copyright 2018 The Darwin Neuroevolution Framework Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include "ann_utils.h"
18 #include "utils.h"
19 #include "modules.h"
20 #include "properties.h"
21 #include "stringify.h"
22 #include "universe.h"
23 
24 #include <third_party/json/json.h>
25 using nlohmann::json;
26 
27 #include <atomic>
28 #include <condition_variable>
29 #include <cstdint>
30 #include <functional>
31 #include <initializer_list>
32 #include <map>
33 #include <memory>
34 #include <mutex>
35 #include <optional>
36 #include <string>
37 #include <thread>
38 #include <utility>
39 #include <vector>
40 using namespace std;
41 
42 class QWidget;
43 
44 namespace darwin {
45 
47 enum class ComplexityHint {
48  Minimal,
49  Balanced,
50  Extra,
51 };
52 
53 inline auto customStringify(core::TypeTag<ComplexityHint>) {
54  static auto stringify = new core::StringifyKnownValues<ComplexityHint>{
55  { ComplexityHint::Minimal, "minimal" },
56  { ComplexityHint::Balanced, "balanced" },
57  { ComplexityHint::Extra, "extra" },
58  };
59  return stringify;
60 }
61 
69 class Brain {
70  public:
71  virtual ~Brain() = default;
72 
74  virtual void setInput(int index, float value) = 0;
75 
78  virtual float output(int index) const = 0;
79 
81  virtual void think() = 0;
82 
85  virtual void resetState() = 0;
86 };
87 
93 struct Genealogy {
96 
98  vector<int> parents;
99 
100  Genealogy() = default;
101 
102  Genealogy(const string& genetic_operator, initializer_list<int> parents)
103  : genetic_operator(genetic_operator), parents(parents) {}
104 
105  void reset() {
106  genetic_operator.clear();
107  parents.clear();
108  }
109 };
110 
126 class Genotype {
127  public:
129  float fitness = 0;
130 
133 
134  public:
135  virtual ~Genotype() = default;
136 
138  virtual unique_ptr<Brain> grow() const = 0;
139 
141  virtual unique_ptr<Genotype> clone() const = 0;
142 
144  virtual json save() const = 0;
145 
147  virtual void load(const json& json_obj) = 0;
148 
149  virtual void reset() {
150  fitness = 0;
151  genealogy.reset();
152  }
153 };
154 
162  public:
163  Population() = default;
164  virtual ~Population() = default;
165 
167  virtual size_t size() const = 0;
168 
170  virtual Genotype* genotype(size_t index) = 0;
171 
173  virtual const Genotype* genotype(size_t index) const = 0;
174 
181  virtual vector<size_t> rankingIndex() const = 0;
182 
184  virtual int generation() const = 0;
185 
187  virtual void createPrimordialGeneration(int population_size) = 0;
188 
196  virtual void createNextGeneration() = 0;
197 
199  Genotype* operator[](size_t index) { return genotype(index); }
200  const Genotype* operator[](size_t index) const { return genotype(index); }
201 };
202 
203 class Domain;
204 
207  public:
209  virtual unique_ptr<Population> create(const core::PropertySet& config,
210  const Domain& domain) = 0;
211 
213  virtual unique_ptr<core::PropertySet> defaultConfig(ComplexityHint hint) const = 0;
214 };
215 
229 class Domain : public core::NonCopyable {
230  public:
231  Domain() = default;
232  virtual ~Domain() = default;
233 
235  virtual size_t inputs() const = 0;
236 
238  virtual size_t outputs() const = 0;
239 
252  virtual bool evaluatePopulation(Population* population) const = 0;
253 
256  virtual unique_ptr<core::PropertySet> calibrateGenotype([
257  [maybe_unused]] const Genotype* genotype) const {
258  return nullptr;
259  }
260 };
261 
264  public:
266  virtual unique_ptr<Domain> create(const core::PropertySet& config) = 0;
267 
269  virtual unique_ptr<core::PropertySet> defaultConfig(ComplexityHint hint) const = 0;
270 };
271 
277  public:
279  virtual QWidget* newSandboxWindow() = 0;
280 };
281 
283 struct Registry {
286 
289 
292 };
293 
295 inline Registry* registry() {
296  static Registry instance;
297  return &instance;
298 }
299 
301 //
305  PROPERTY(population_size, int, 5000, "Population size");
306 
307  PROPERTY(population_name, string, "", "Population name");
308  PROPERTY(domain_name, string, "", "Domain name");
309 
310  PROPERTY(population_hint,
312  ComplexityHint::Balanced,
313  "Population complexity hint");
314 
315  PROPERTY(domain_hint,
317  ComplexityHint::Balanced,
318  "Domain complexity hint");
319 };
320 
329  public:
332  Experiment(const optional<string>& name,
333  const ExperimentSetup& setup,
334  const optional<db::RowId>& base_variation_id,
335  Universe* universe);
336 
338  Experiment(const DbExperiment* db_experiment, Universe* universe);
339 
341  const optional<string>& name() const { return name_; }
342 
344  const ExperimentSetup* setup() const { return &setup_; }
345 
347  PopulationFactory* populationFactory() const { return population_factory_; }
348 
350  DomainFactory* domainFactory() const { return domain_factory_; }
351 
353  DomainUiFactory* domainUiFactory() const { return domain_ui_factory_; }
354 
356  core::PropertySet* populationConfig() { return population_config_.get(); }
357  const core::PropertySet* populationConfig() const { return population_config_.get(); }
358 
360  core::PropertySet* domainConfig() { return domain_config_.get(); }
361  const core::PropertySet* domainConfig() const { return domain_config_.get(); }
362 
364  core::PropertySet* coreConfig() { return core_config_.get(); }
365  const core::PropertySet* coreConfig() const { return core_config_.get(); }
366 
368  Universe* universe() const { return universe_; }
369 
371  db::RowId dbExperimentId() const;
372 
374  db::RowId dbVariationId() const;
375 
382  void setModified(bool modified) { modified_ = modified; }
383 
386  void prepareForEvolution();
387 
389  void save();
390 
391  private:
392  void basicSetup(const optional<string>& name, const ExperimentSetup& setup);
393  void loadLatestVariation();
394 
395  private:
396  optional<string> name_;
397  ExperimentSetup setup_;
398 
399  // configurations
400  unique_ptr<core::PropertySet> population_config_;
401  unique_ptr<core::PropertySet> domain_config_;
402  unique_ptr<core::PropertySet> core_config_;
403 
404  // populations, domains factories
405  PopulationFactory* population_factory_ = nullptr;
406  DomainFactory* domain_factory_ = nullptr;
407  DomainUiFactory* domain_ui_factory_ = nullptr;
408 
409  // corresponding database objects
410  unique_ptr<DbExperiment> db_experiment_;
411  unique_ptr<DbExperimentVariation> db_variation_;
412 
413  // tracks the configuration modification state
414  bool modified_ = false;
415 
416  Universe* universe_ = nullptr;
417 };
418 
419 } // namespace darwin
Support for registering populations and domains.
Definition: registry.cpp:37
The interface to the Phenotype
Definition: darwin.h:69
Interface to a domain UI factory.
Definition: darwin.h:276
ComplexityHint
A generic hint for the initial population & domain setup.
Definition: darwin.h:47
A set of instances implementing common interface (primarily intended to support registering named fac...
Definition: modules.h:63
A population implementation encapsulates the fixed-size set of genotypes, together with the rules for...
Definition: darwin.h:161
best guess for the ideal performance/results trade-offs
An experiment configuration.
Definition: darwin.h:304
core::ImplementationsSet< DomainUiFactory > domains_ui
Registered domains UIs.
Definition: darwin.h:291
The persistent storage for all the experiments and variations.
Definition: universe.h:111
core::PropertySet * domainConfig()
Domain specific configuration.
Definition: darwin.h:360
STL namespace.
int64_t RowId
Represents the ID of a row in the database.
Definition: database.h:44
The available domains and populations.
Definition: darwin.h:283
const ExperimentSetup * setup() const
The experiment&#39;s setup values.
Definition: darwin.h:344
bare minimum, fast but poor results (mostly useful for testing)
DomainFactory * domainFactory() const
Accessor to the DomainFactory for the experiment&#39;s domain.
Definition: darwin.h:350
void setModified(bool modified)
Update the configuration modification flag.
Definition: darwin.h:382
core::PropertySet * populationConfig()
Population specific configuration.
Definition: darwin.h:356
Root of the polymorphic factories.
Definition: modules.h:92
Universe * universe() const
The associated Darwin Universe.
Definition: darwin.h:368
Models the genealogy information of a genotype.
Definition: darwin.h:93
Interface to the domain factory.
Definition: darwin.h:263
vector< int > parents
The rank indexes of the parents from the previous generation.
Definition: darwin.h:98
const optional< string > & name() const
The experiment&#39;s name.
Definition: darwin.h:341
might produce more sophisticated solutions, but very slow
Encapsulates the runtime experiment state.
Definition: darwin.h:328
The foundation for data structures supporting runtime reflection.
Definition: properties.h:388
DomainUiFactory * domainUiFactory() const
Accessor to the DomainUiFactory for the experiment&#39;s domain UI.
Definition: darwin.h:353
Key Darwin Neuroevolution Framework interfaces.
Classes derived from this are not copyable or movable.
Definition: utils.h:69
Genotype * operator[](size_t index)
Array subscript operator (required for pp::for_each)
Definition: darwin.h:199
core::ImplementationsSet< PopulationFactory > populations
Registered populations.
Definition: darwin.h:285
core::ImplementationsSet< DomainFactory > domains
Registered domains.
Definition: darwin.h:288
Interface to a domain implementation.
Definition: darwin.h:229
Genealogy genealogy
Genealogy information.
Definition: darwin.h:132
virtual unique_ptr< core::PropertySet > calibrateGenotype([[maybe_unused]] const Genotype *genotype) const
Optional: additional fitness metrics (normally not used in the population evaluation, ie a test set)
Definition: darwin.h:256
PopulationFactory * populationFactory() const
Accessor to the PopulationFactory for the experiment&#39;s population.
Definition: darwin.h:347
Handles types with a fixed, known set of values (enumerations for example)
Definition: stringify.h:85
core::PropertySet * coreConfig()
Core configuration values.
Definition: darwin.h:364
Universe representation of an experiment.
Definition: universe.h:44
string genetic_operator
Name of the genetic operator used to create the genotype from its parents.
Definition: darwin.h:95
const Stringify< T > * stringify()
Returns the stringifier for type T.
Definition: stringify.h:166
The interface to the population-specific "genetic material", the Genotype
Definition: darwin.h:126
Interface to a population factory.
Definition: darwin.h:206