Empirical
World.h
Go to the documentation of this file.
1 
26 #ifndef EMP_EVO_WORLD_H
27 #define EMP_EVO_WORLD_H
28 
29 #include <functional>
30 #include <map>
31 #include <unordered_map>
32 
33 #include "../base/Ptr.h"
34 #include "../base/vector.h"
35 #include "../control/Signal.h"
36 #include "../control/SignalControl.h"
37 #include "../data/DataFile.h"
38 #include "../data/DataManager.h"
39 #include "../data/Trait.h"
40 #include "../meta/reflection.h"
41 #include "../tools/map_utils.h"
42 #include "../tools/Random.h"
43 #include "../tools/Range.h"
44 #include "../tools/random_utils.h"
45 #include "../tools/string_utils.h"
46 
47 // World-specific includes.
48 #include "Systematics.h" // Track relationships among organisms.
49 #include "World_iterator.h" // Allow iteration through organisms in a world.
50 #include "World_reflect.h" // Handle needed reflection on incoming organism classes.
51 #include "World_select.h" // Include all built-in selection functions for World.
52 #include "World_structure.h" // Include additional function to setup world structure.
53 
54 namespace emp {
55 
92 
93  template <typename ORG>
94  class World {
95  friend class World_iterator< World<ORG> >;
96  public:
97  // --- Publicly available types ---
98  using this_t = World<ORG>;
99  using org_t = ORG;
100  using value_type = org_t;
104 
106 
108  using fun_calc_fitness_t = std::function<double(ORG&)>;
109 
111  using fun_calc_dist_t = std::function<double(ORG&,ORG&)>;
112 
114  using fun_do_mutations_t = std::function<size_t(ORG&,Random&)>;
115 
117  using fun_print_org_t = std::function<void(ORG&,std::ostream &)>;
118 
120  using fun_get_genome_t = std::function<const genome_t & (ORG &)>;
121 
123  using fun_find_inject_pos_t = std::function<WorldPosition(Ptr<ORG>)>;
124 
126  using fun_find_birth_pos_t = std::function<WorldPosition(Ptr<ORG>, WorldPosition)>;
127 
129  using fun_kill_org_t = std::function<WorldPosition()>;
130 
132  using fun_get_neighbor_t = std::function<WorldPosition(WorldPosition)>;
133 
134  protected:
135  // Internal state member variables
136  size_t update;
140  pop_t & pop;
141  size_t num_orgs;
143 
144  // Configuration settings
145  std::string name;
146  bool cache_on;
147  std::vector<size_t> pop_sizes;
150 
154 
157 
158  // Configurable functions. Function to...
167 
169  std::map<std::string, std::string> attributes;
170 
173  std::unordered_map<std::string, int> systematics_labels;
174 
175  // == Signals ==
176  SignalControl control; // Setup the world to control various signals.
177  // Trigger signal...
187 
189  EMP_CREATE_OPTIONAL_METHOD(SetupOrg, Setup);
190 
192  double GetCache(size_t id) const { return (id < fit_cache.size()) ? fit_cache[id] : 0.0; }
193 
195  void ClearCache(size_t id) { if (id < fit_cache.size()) fit_cache[id] = 0.0; }
196 
197  public:
203  World(std::string _name="", bool gen_random=true)
204  : update(0), random_ptr(nullptr), random_owner(false), pops(), pop(pops[0]), num_orgs(0)
205  , fit_cache()
206  , name(_name), cache_on(false), pop_sizes(1,0), phenotypes(), files()
207  , is_synchronous(false), is_space_structured(false), is_pheno_structured(false)
208  , fun_calc_fitness(), fun_do_mutations(), fun_print_org(), fun_get_genome()
209  , fun_find_inject_pos(), fun_find_birth_pos(), fun_kill_org(), fun_get_neighbor()
210  , attributes(), control()
211  , before_repro_sig(to_string(name,"::before-repro"), control)
212  , offspring_ready_sig(to_string(name,"::offspring-ready"), control)
213  , inject_ready_sig(to_string(name,"::inject-ready"), control)
214  , before_placement_sig(to_string(name,"::before-placement"), control)
215  , on_placement_sig(to_string(name,"::on-placement"), control)
216  , on_update_sig(to_string(name,"::on-update"), control)
217  , on_death_sig(to_string(name,"::on-death"), control)
218  , on_swap_sig(to_string(name,"::on-swap"), control)
219  , world_destruct_sig(to_string(name,"::wolrd-destruct"), control)
220  {
221  if (gen_random) NewRandom();
222  SetDefaultFitFun<this_t, ORG>(*this);
223  SetDefaultMutFun<this_t, ORG>(*this);
224  SetDefaultPrintFun<this_t, ORG>(*this);
225  SetDefaultGetGenomeFun<this_t, ORG>(*this);
226  SetPopStruct_Mixed(); // World default structure is well-mixed.
227  }
228  World(Random & rnd, std::string _name="") : World(_name,false) { random_ptr = &rnd; }
229 
230  ~World() {
231  world_destruct_sig.Trigger();
232  Clear();
233  if (random_owner) random_ptr.Delete();
234  for (Ptr<SystematicsBase<ORG> > s : systematics) {
235  s.Delete();
236  }
237  for (auto file : files) {
238  file.Delete();
239  }
240  }
241 
242  // --- Accessing Organisms or info ---
243 
245  size_t GetSize() const { return pop.size(); }
246 
248  size_t GetNumOrgs() const { return num_orgs; }
249 
251  size_t GetUpdate() const { return update; }
252 
254  size_t GetWidth() const { return pop_sizes[0]; }
255 
257  size_t GetHeight() const { return pop_sizes[1]; }
258 
260  const pop_t & GetFullPop() const { return pop; }
261 
263  const emp::TraitSet<ORG> & GetPhenotypes() const { return phenotypes; }
264 
267 
269  DataFile & GetFile(const std::string & filename) {
270  for (emp::Ptr<DataFile> file : files) {
271  if (file->GetFilename() == filename) return *file;
272  }
273  emp_assert(false, "Trying to lookup a file that does not exist.", filename);
274  }
275 
277  bool IsOccupied(WorldPosition pos) const { return pops.IsValid(pos) && pops(pos); }
278 
280  bool IsCacheOn() const { return cache_on; }
281 
284  bool IsSynchronous() const { return is_synchronous; }
285 
288  bool IsSpaceStructured() const { return is_space_structured; }
289 
292  bool IsPhenoStructured() const { return is_pheno_structured; }
293 
296  this_t & MarkSynchronous(bool in=true) { is_synchronous = in; return *this; }
297 
300  this_t & MarkSpaceStructured(bool in=true) { is_space_structured = in; return *this; }
301 
304  this_t & MarkPhenoStructured(bool in=true) { is_pheno_structured = in; return *this; }
305 
309  const ORG & operator[](size_t id) const {
310  emp_assert(pop[id] != nullptr, id); // Should not index to a null organism!
311  return *(pop[id]);
312  }
313 
316  ORG & GetOrg(size_t id) {
317  emp_assert(id < pop.size()); // Pop must be large enough.
318  emp_assert(pop[id] != nullptr, id); // Should not index to a null organism!
319  return *(pop[id]);
320  }
321 
324  ORG & GetOrg(size_t x, size_t y) { return GetOrg(x+y*GetWidth()); }
325 
328  const Ptr<ORG> GetOrgPtr(size_t id) const { return pop[id]; }
329 
332  ORG & GetNextOrg(size_t id) {
333  emp_assert(id < pops[1].size()); // Next pop must be large enough.
334  emp_assert(pops[1][id] != nullptr, id); // Should not index to a null organism!
335  return *(pops[1][id]);
336  }
337 
339  const genome_t & GetGenome(ORG & org) { return fun_get_genome(org); }
340 
342  const genome_t & GetGenomeAt(size_t id) { return fun_get_genome(GetOrg(id)); }
343 
348  emp_assert(systematics.size() > 0, "Cannot get systematics file. No systematics file to track.");
349  emp_assert(id < (int)systematics.size(), "Invalid systematics file requested.", id, systematics.size());
350  return systematics[id];
351  }
352 
356  Ptr<SystematicsBase<ORG> > GetSystematics(std::string label) {
357  emp_assert(Has(systematics_labels, label), "Invalid systematics manager label");
358 
359  return systematics[systematics_labels[label]];
360  }
361 
362 
363  void RemoveSystematics(int id) {
364  emp_assert(systematics.size() > 0, "Cannot remove systematics file. No systematics file to track.");
365  emp_assert(id < systematics.size(), "Invalid systematics file requested to be removed.", id, systematics.size());
366 
367  systematics[id].Delete();
368  systematics[id] = nullptr;
369 
370  for (auto el : systematics_labels) {
371  if (el.second == id) {
372  systematics_labels.erase(el.first);
373  }
374  }
375  }
376 
377  void RemoveSystematics(std::string label) {
378  emp_assert(Has(systematics_labels, label), "Invalid systematics manager label");
379 
380  systematics[systematics_labels[label]].Delete();
381  systematics[systematics_labels[label]] = nullptr;
382  systematics_labels.erase(label) ;
383  }
384 
385  template <typename ORG_INFO, typename DATA_STRUCT>
386  void AddSystematics(Ptr<Systematics<ORG, ORG_INFO, DATA_STRUCT> > s, std::string label="systematics") {
387  if (Has(systematics_labels, label)) {
388  label += to_string(systematics.size());
389  }
390  systematics_labels[label] = systematics.size();
391 
392  if (is_synchronous) {
393  s->SetTrackSynchronous(true);
394  }
395 
396  systematics.push_back(s);
397  }
398 
401 
402  // --- CONFIGURE ---
403 
406  void SetPopStruct_Grow(bool synchronous_gen=false);
407 
410  void SetPopStruct_Mixed(bool synchronous_gen=false);
411 
414  void SetPopStruct_Grid(size_t width, size_t height, bool synchronous_gen=false);
415 
419  void SetAutoMutate() {
420  OnOffspringReady( [this](ORG & org){ DoMutationsOrg(org); } );
421  }
422 
427  void SetAutoMutate(std::function<bool(size_t pos)> test_fun) {
428  OnBeforePlacement( [this,test_fun](ORG & org, size_t pos){ if (test_fun(pos)) DoMutationsOrg(org); } );
429  }
430 
432  // @ELD: Can probably be removed with new WorldPosition
433  void SetSynchronousSystematics(bool synchronous) {
434  for (Ptr<SystematicsBase<ORG> > s : systematics) {
435  s->SetTrackSynchronous(synchronous);
436  }
437  }
438 
440  // void AddPhenotype(const std::string & name, std::function<double(ORG &)> fun) {
441  // phenotypes.AddTrait(name, fun);
442  // }
443  template <typename... Ts>
444  void AddPhenotype(Ts &&... args) {
445  phenotypes.AddTrait(std::forward<Ts>(args)...);
446  }
447 
452  if (!data_nodes.HasNode("fitness")) {
453  DataMonitor<double> & node = data_nodes.New("fitness");
454 
455  // Collect fitnesses each update...
456  OnUpdate([this, &node](size_t){
457  node.Reset();
458  for (size_t i = 0; i < pop.size(); i++) {
459  if (IsOccupied(i)) node.AddDatum( CalcFitnessID(i) );
460  }
461  }
462  );
463  }
464  return &(data_nodes.Get("fitness"));
465  }
466 
467  // Returns a reference so that capturing it in a lambda to call on update
468  // is less confusing. It's possible we should change it to be consistent
469  // with GetFitnessDataNode, though.
470  Ptr<DataMonitor<double>> AddDataNode(const std::string & name) {
471  emp_assert(!data_nodes.HasNode(name));
472  return &(data_nodes.New(name));
473  }
474 
475  Ptr<DataMonitor<double>> GetDataNode(const std::string & name) {
476  return &(data_nodes.Get(name));
477  }
478 
480  DataFile & SetupFile(const std::string & filename);
481 
483  DataFile & SetupFitnessFile(const std::string & filename="fitness.csv", const bool & print_header=true);
484 
486  DataFile & SetupSystematicsFile(std::string label, const std::string & filename="systematics.csv", const bool & print_header=true);
487 
489  DataFile & SetupSystematicsFile(size_t id=0, const std::string & filename="systematics.csv", const bool & print_header=true);
490 
492  DataFile & SetupPopulationFile(const std::string & filename="population.csv", const bool & print_header=true);
493 
496  void SetFitFun(const fun_calc_fitness_t & fit_fun) { fun_calc_fitness = fit_fun; }
497 
500  void SetMutFun(const fun_do_mutations_t & mut_fun) { fun_do_mutations = mut_fun; }
501 
505  void SetPrintFun(const fun_print_org_t & print_fun) { fun_print_org = print_fun; }
506 
509  void SetGetGenomeFun(const fun_get_genome_t & _fun) { fun_get_genome = _fun; }
510 
513  void SetAddInjectFun(const fun_find_inject_pos_t & _fun) { fun_find_inject_pos = _fun; }
514 
518  void SetAddBirthFun(const fun_find_birth_pos_t & _fun) { fun_find_birth_pos = _fun; }
519 
522  void SetKillOrgFun(const fun_kill_org_t & _fun) { fun_kill_org = _fun; }
523 
526  void SetGetNeighborFun(const fun_get_neighbor_t & _fun) { fun_get_neighbor = _fun; }
527 
537  void SetSharedFitFun(const fun_calc_fitness_t & fit_fun, const fun_calc_dist_t & dist_fun,
538  double sharing_threshold, double alpha);
539 
540  // Deal with Signals
541 
544 
545 
550  SignalKey OnBeforeRepro(const std::function<void(size_t)> & fun) {
551  return before_repro_sig.AddAction(fun);
552  }
553 
559  SignalKey OnOffspringReady(const std::function<void(ORG &)> & fun) {
560  return offspring_ready_sig.AddAction(fun);
561  }
562 
567  SignalKey OnInjectReady(const std::function<void(ORG &)> & fun) {
568  return inject_ready_sig.AddAction(fun);
569  }
570 
576  SignalKey OnBeforePlacement(const std::function<void(ORG &,size_t)> & fun) {
577  return before_placement_sig.AddAction(fun);
578  }
579 
585  SignalKey OnPlacement(const std::function<void(size_t)> & fun) {
586  return on_placement_sig.AddAction(fun);
587  }
588 
593  SignalKey OnUpdate(const std::function<void(size_t)> & fun) {
594  return on_update_sig.AddAction(fun);
595  }
596 
601  SignalKey OnOrgDeath(const std::function<void(size_t)> & fun) {
602  return on_death_sig.AddAction(fun);
603  }
604 
609  SignalKey OnSwapOrgs(const std::function<void(WorldPosition,WorldPosition)> & fun) {
610  return on_swap_sig.AddAction(fun);
611  }
612 
617  SignalKey OnWorldDestruct(const std::function<void()> & fun) {
618  return world_destruct_sig.AddAction(fun);
619  }
620 
621  // --- MANAGE ATTRIBUTES ---
622 
625  bool HasAttribute(const std::string & name) const { return Has(attributes, name); }
626 
628  std::string GetAttribute(const std::string) const {
629  emp_assert( Has(attributes, name) );
630  return Find(attributes, name, "UNKNOWN");
631  }
632 
635  template <typename T>
636  void SetAttribute(const std::string & name, T && val) { attributes[name] = to_string(val); }
637 
638 
639  // --- UPDATE THE WORLD! ---
640 
646  void Update();
647 
650  template <typename... ARGS>
651  void Process(ARGS &&... args) { // Redirect to all orgs in the population!
652  for (Ptr<ORG> org : pop) { if (org) org->Process(args...); }
653  }
654 
657  template <typename... ARGS>
658  void ProcessID(size_t id, ARGS &&... args) { // Redirect to all orgs in the population!
659  if (pop[id]) pop[id]->Process(std::forward<ARGS>(args)...);
660  }
661 
663  void ResetHardware() {
664  for (Ptr<ORG> org : pop) { if (org) org->ResetHardware(); }
665  }
666 
667  // --- CALCULATE FITNESS ---
668 
670  double CalcFitnessOrg(ORG & org);
671 
673  double CalcFitnessID(size_t id);
674 
676  void CalcFitnessAll() const {
677  emp_assert(cache_on, "Trying to calculate fitness of all orgs without caching.");
678  for (size_t id = 0; id < pop.size(); id++) CalcFitnessID(id);
679  }
680 
682  void SetCache(bool _in=true) { cache_on = _in; }
683 
685  void ClearCache() { fit_cache.resize(0); }
686 
687 
688  // --- MUTATIONS! ---
689 
691  void DoMutationsOrg(ORG & org) {
692  emp_assert(fun_do_mutations); emp_assert(random_ptr);
693  fun_do_mutations(org, *random_ptr);
694  }
695 
697  void DoMutationsID(size_t id) {
698  emp_assert(pop[id]);
699  DoMutationsOrg(*(pop[id]));
700  }
701 
703  void DoMutations(size_t start_id=0) {
704  for (size_t id = start_id; id < pop.size(); id++) { if (pop[id]) DoMutationsID(id); }
705  }
706 
707  // --- MANIPULATE ORGS IN POPULATION ---
708 
710  void Clear();
711 
713  void Reset() { Clear(); update = 0; }
714 
716  void Swap(WorldPosition pos1, WorldPosition pos2) {
717  std::swap(pops(pos1), pops(pos2));
718  on_swap_sig.Trigger(pos1, pos2);
719  }
720 
723  void Resize(size_t new_size) {
724  for (size_t i = new_size; i < pop.size(); i++) RemoveOrgAt(i); // Remove orgs past new size.
725  pop.resize(new_size, nullptr); // Default new orgs to null.
726  }
727 
729  void Resize(size_t new_width, size_t new_height) {
730  Resize(new_width * new_height);
731  pop_sizes.resize(2);
732  pop_sizes[0] = new_width; pop_sizes[1] = new_height;
733  }
734 
736  void Resize(const emp::vector<size_t> & dims) {
737  Resize(emp::Product(dims));
738  pop_sizes = dims;
739  }
740 
743  void AddOrgAt(Ptr<ORG> new_org, WorldPosition pos, WorldPosition p_pos=WorldPosition());
744 
747  void RemoveOrgAt(WorldPosition pos);
748 
750  void Inject(const genome_t & mem, size_t copy_count=1);
751 
753  void InjectAt(const genome_t & mem, const WorldPosition pos);
754 
756  template <typename... ARGS> void InjectRandomOrg(ARGS &&... args);
757 
759  WorldPosition DoBirth(const genome_t & mem, size_t parent_pos, size_t copy_count=1);
760 
761  // Kill off organism at the specified position (same as RemoveOrgAt, but callable externally)
762  void DoDeath(const WorldPosition pos) { RemoveOrgAt(pos); }
763 
764  // Kill off an organism using internal kill method setup by population structure.
765  void DoDeath() { fun_kill_org(); }
766 
767  // --- RANDOM FUNCTIONS ---
768 
770  Random & GetRandom() { emp_assert(random_ptr); return *random_ptr; }
771 
773  void SetRandom(Random & r);
774 
776  void NewRandom(int seed=-1);
777 
779  size_t GetRandomCellID() { return GetRandom().GetUInt(pop.size()); }
780 
782  size_t GetRandomCellID(size_t min_id, size_t max_id) {
783  emp_assert(min_id < max_id && max_id <= pop.size());
784  return min_id + GetRandom().GetUInt(max_id - min_id);
785  }
786 
789 
791  size_t GetRandomOrgID();
792 
794  ORG & GetRandomOrg() { return *pop[GetRandomOrgID()]; }
795 
796  // --- POPULATION ANALYSIS ---
797 
799  emp::vector<size_t> FindCellIDs(const std::function<bool(ORG*)> & filter);
800 
801  // Simple techniques for using FindCellIDs()
802 
804  emp::vector<size_t> GetValidOrgIDs() { return FindCellIDs([](ORG*org){ return (bool) org; }); }
805 
807  emp::vector<size_t> GetEmptyPopIDs() { return FindCellIDs([](ORG*org){ return !org; }); }
808 
809 
810  // --- POPULATION MANIPULATIONS ---
811 
813  void DoBottleneck(const size_t new_size, bool choose_random=true);
814 
816  void SerialTransfer(const double keep_frac);
817 
818  // --- PRINTING ---
819 
821  void Print(std::ostream & os = std::cout, const std::string & empty="-", const std::string & spacer=" ");
822 
824  void PrintOrgCounts(std::ostream & os = std::cout);
825 
827  void PrintGrid(std::ostream& os=std::cout, const std::string & empty="-", const std::string & spacer=" ");
828 
829 
830  // --- FOR VECTOR COMPATIBILITY ---
831 
833  size_t size() const { return pop.size(); }
834 
836  void resize(size_t new_size) { Resize(new_size); }
837 
839  void clear() { Clear(); }
840 
842  iterator_t begin() { return iterator_t(this, 0); }
843 
845  iterator_t end() { return iterator_t(this, (int) pop.size()); }
846 
847  };
848 
849  // =============================================================
850  // === ===
851  // === Out-of-class member function definitions from above ===
852  // === ===
853  // =============================================================
854 
855  template <typename ORG>
857  emp_assert(new_org); // The new organism must exist.
858  emp_assert(pos.IsValid()); // Position must be legal.
859 
860  // If new organism is going into the active population, trigger signal before doing so.
861  if (pos.IsActive()) { before_placement_sig.Trigger(*new_org, pos.GetIndex()); }
862 
863  for (Ptr<SystematicsBase<ORG> > s : systematics) {
864  s->SetNextParent((int) p_pos.GetIndex());
865  }
866 
867  // Clear out any old organism at this position.
868  RemoveOrgAt(pos);
869 
870  pops.MakeValid(pos); // Make sure we have room for new organism
871  pops(pos) = new_org; // Put org into place.
872 
873  // Track org count
874  if (pos.IsActive()) ++num_orgs;
875 
876  // Track the new systematics info
877  for (Ptr<SystematicsBase<ORG> > s : systematics) {
878  s->AddOrg(*new_org, (int) pos.GetIndex(), (int) update, !pos.IsActive());
879  }
880 
881  // SetupOrg(*new_org, &callbacks, pos);
882  // If new organism is in the active population, trigger associated signal.
883  if (pos.IsActive()) { on_placement_sig.Trigger(pos.GetIndex()); }
884  }
885 
886  template<typename ORG>
888  size_t id = pos.GetIndex(); // Identify specific index.
889  pop_t & cur_pop = pops[pos.GetPopID()];
890  if (id >= cur_pop.size() || !cur_pop[id]) return; // Nothing to remove!
891  if (pos.IsActive()) on_death_sig.Trigger(id); // If active, signal that org is about to die.
892  cur_pop[id].Delete(); // Delete the organism...
893  cur_pop[id] = nullptr; // ...and reset the pointer to null
894 
895  if (pos.IsActive()) {
896  --num_orgs; // Track one fewer organisms in the population
897  if (cache_on) ClearCache(id); // Delete any cached info about this organism
898  for (Ptr<SystematicsBase<ORG> > s : systematics) {
899  s->RemoveOrg((int) pos.GetIndex()); // Notify systematics about organism removal
900  }
901  } else {
902  for (Ptr<SystematicsBase<ORG> > s : systematics) {
903  s->RemoveNextOrg((int) pos.GetIndex()); // Notify systematics about organism removal
904  }
905  }
906  }
907 
908  template<typename ORG>
909  void World<ORG>::SetPopStruct_Grow(bool synchronous_gen) {
910  pop_sizes.resize(0);
911  is_synchronous = synchronous_gen;
912  is_space_structured = false;
913  is_pheno_structured = false;
914 
915  // -- Setup functions --
916  // Append at end of population
917  fun_find_inject_pos = [this](Ptr<ORG> new_org) {
918  (void) new_org;
919  return pop.size();
920  };
921 
922  // Neighbors are anywhere in the same population.
923  fun_get_neighbor = [this](WorldPosition pos) { return pos.SetIndex(GetRandomCellID()); };
924 
925  // Kill random organisms and move end into vacant position to keep pop compact.
926  fun_kill_org = [this](){
927  const size_t last_id = pop.size() - 1;
928  Swap(GetRandomCellID(), last_id);
929  RemoveOrgAt(last_id);
930  pop.resize(last_id);
931  return last_id;
932  };
933 
934  if (synchronous_gen) {
935  // Append births into the next population.
936  fun_find_birth_pos = [this](Ptr<ORG> new_org, WorldPosition parent_pos) {
937  emp_assert(new_org); // New organism must exist.
938  return WorldPosition(pops[1].size(), 1); // Append it to the NEXT population
939  };
940 
941  SetAttribute("SynchronousGen", "True");
942  } else {
943  // Asynchronous: always append to current population.
944  fun_find_birth_pos = [this](Ptr<ORG> new_org, WorldPosition parent_pos) {
945  return WorldPosition(pop.size());
946  };
947  SetAttribute("SynchronousGen", "False");
948  }
949 
950  SetAttribute("PopStruct", "Grow");
951  SetSynchronousSystematics(synchronous_gen);
952  }
953 
954  template<typename ORG>
955  void World<ORG>::SetPopStruct_Mixed(bool synchronous_gen) {
956  pop_sizes.resize(0);
957  is_synchronous = synchronous_gen;
958  is_space_structured = false;
959  is_pheno_structured = false;
960 
961  // -- Setup functions --
962  // Append at end of population
963  fun_find_inject_pos = [this](Ptr<ORG> new_org) {
964  (void) new_org;
965  return pop.size();
966  };
967 
968  // Neighbors are anywhere in the same population.
969  fun_get_neighbor = [this](WorldPosition pos) { return pos.SetIndex(GetRandomCellID()); };
970 
971  // Kill random organisms and move end into vacant position to keep pop compact.
972  fun_kill_org = [this](){
973  const size_t kill_id = GetRandomCellID();
974  RemoveOrgAt(kill_id);
975  return kill_id;
976  };
977 
978  if (synchronous_gen) {
979  // Append births into the next population.
980  fun_find_birth_pos = [this](Ptr<ORG> new_org, WorldPosition parent_id) {
981  emp_assert(new_org); // New organism must exist.
982  return WorldPosition(pops[1].size(), 1); // Append it to the NEXT population
983  };
984 
985  SetAttribute("SynchronousGen", "True");
986  } else {
987  // Asynchronous: always go to a neigbor in current population.
988  fun_find_birth_pos = [this](Ptr<ORG> new_org, WorldPosition parent_id) {
989  return WorldPosition(fun_get_neighbor(parent_id)); // Place org in existing population.
990  };
991  SetAttribute("SynchronousGen", "False");
992  }
993 
994  SetAttribute("PopStruct", "Mixed");
995  SetSynchronousSystematics(synchronous_gen);
996  }
997 
998  template<typename ORG>
999  void World<ORG>::SetPopStruct_Grid(size_t width, size_t height, bool synchronous_gen) {
1000  Resize(width, height);
1001  is_synchronous = synchronous_gen;
1002  is_space_structured = true;
1003  is_pheno_structured = false;
1004 
1005  // -- Setup functions --
1006  // Inject a random position in grid
1007  fun_find_inject_pos = [this](Ptr<ORG> new_org) {
1008  (void) new_org;
1009  return WorldPosition(GetRandomCellID());
1010  };
1011 
1012  // neighbors are in 9-sized neighborhood.
1013  fun_get_neighbor = [this](WorldPosition pos) {
1014  emp_assert(random_ptr);
1015  emp_assert(pop_sizes.size() == 2);
1016  const size_t size_x = pop_sizes[0];
1017  const size_t size_y = pop_sizes[1];
1018  const size_t id = pos.GetIndex();
1019  const int offset = random_ptr->GetInt(9);
1020  const int rand_x = (int) (id%size_x) + offset%3 - 1;
1021  const int rand_y = (int) (id/size_x) + offset/3 - 1;
1022  const auto neighbor_id = emp::Mod(rand_x, (int) size_x) + emp::Mod(rand_y, (int) size_y) * (int)size_x;
1023  return pos.SetIndex(neighbor_id);
1024  };
1025 
1026  fun_kill_org = [this](){
1027  const size_t kill_id = GetRandomCellID();
1028  RemoveOrgAt(kill_id);
1029  return kill_id;
1030  };
1031 
1032  if (synchronous_gen) {
1033  // Place births in a neighboring position in the new grid.
1034  fun_find_birth_pos = [this](Ptr<ORG> new_org, WorldPosition parent_pos) {
1035  emp_assert(new_org); // New organism must exist.
1036  WorldPosition next_pos = fun_get_neighbor(parent_pos); // Place near parent.
1037  return next_pos.SetPopID(1); // Adjust position to next pop and place..
1038  };
1039  SetAttribute("SynchronousGen", "True");
1040  } else {
1041  // Asynchronous: always go to a neighbor in current population.
1042  fun_find_birth_pos = [this](Ptr<ORG> new_org, WorldPosition parent_pos) {
1043  return WorldPosition(fun_get_neighbor(parent_pos)); // Place org in existing population.
1044  };
1045  SetAttribute("SynchronousGen", "False");
1046  }
1047 
1048  SetAttribute("PopStruct", "Grid");
1049  SetSynchronousSystematics(synchronous_gen);
1050  }
1051 
1052  // Add a new data file constructed elsewhere.
1053  template<typename ORG>
1055  size_t id = files.size();
1056  files.push_back(file);
1057  return *files[id];
1058  }
1059 
1060 
1061  // Create a new, arbitrary file.
1062  template<typename ORG>
1063  DataFile & World<ORG>::SetupFile(const std::string & filename) {
1064  size_t id = files.size();
1065  files.emplace_back();
1066  files[id].New(filename);
1067  return *files[id];
1068  }
1069 
1070  // A data file (default="fitness.csv") that contains information about the population's fitness.
1071  template<typename ORG>
1072  DataFile & World<ORG>::SetupFitnessFile(const std::string & filename, const bool & print_header) {
1073  auto & file = SetupFile(filename);
1074  auto node = GetFitnessDataNode();
1075  file.AddVar(update, "update", "Update");
1076  file.AddMean(*node, "mean_fitness", "Average organism fitness in current population.");
1077  file.AddMin(*node, "min_fitness", "Minimum organism fitness in current population.");
1078  file.AddMax(*node, "max_fitness", "Maximum organism fitness in current population.");
1079  file.AddInferiority(*node, "inferiority", "Average fitness / maximum fitness in current population.");
1080  if (print_header) file.PrintHeaderKeys();
1081  return file;
1082  }
1083 
1084  // A data file (default="systematics.csv") that contains information about the population's
1085  // phylogeny and lineages.
1086  template<typename ORG>
1087  DataFile & World<ORG>::SetupSystematicsFile(std::string label, const std::string & filename, const bool & print_header) {
1088  emp_assert(Has(systematics_labels, label), "Invalid systematics tracker requested.", label);
1089  return SetupSystematicsFile(systematics_labels[label], filename, print_header);
1090  }
1091 
1092  // A data file (default="systematics.csv") that contains information about the population's
1093  // phylogeny and lineages.
1094  template<typename ORG>
1095  DataFile & World<ORG>::SetupSystematicsFile(size_t id, const std::string & filename, const bool & print_header) {
1096  emp_assert(systematics.size() > 0, "Cannot track systematics file. No systematics file to track.");
1097  emp_assert(id < systematics.size(), "Invalid systematics file requested to be tracked.");
1098  auto & file = SetupFile(filename);
1099  file.AddVar(update, "update", "Update");
1100  file.template AddFun<size_t>( [this, id](){ return systematics[id]->GetNumActive(); }, "num_taxa", "Number of unique taxonomic groups currently active." );
1101  file.template AddFun<size_t>( [this, id](){ return systematics[id]->GetTotalOrgs(); }, "total_orgs", "Number of organisms tracked." );
1102  file.template AddFun<double>( [this, id](){ return systematics[id]->GetAveDepth(); }, "ave_depth", "Average Phylogenetic Depth of Organisms." );
1103  file.template AddFun<size_t>( [this, id](){ return systematics[id]->GetNumRoots(); }, "num_roots", "Number of independent roots for phlogenies." );
1104  file.template AddFun<int>( [this, id](){ return systematics[id]->GetMRCADepth(); }, "mrca_depth", "Phylogenetic Depth of the Most Recent Common Ancestor (-1=none)." );
1105  file.template AddFun<double>( [this, id](){ return systematics[id]->CalcDiversity(); }, "diversity", "Genotypic Diversity (entropy of taxa in population)." );
1106 
1107  if (print_header) file.PrintHeaderKeys();
1108  return file;
1109  }
1110 
1111  // A data file (default="population.csv") contains information about the current population.
1112  template<typename ORG>
1113  DataFile & World<ORG>::SetupPopulationFile(const std::string & filename, const bool & print_header) {
1114  auto & file = SetupFile(filename);
1115  file.AddVar(update, "update", "Update");
1116  file.template AddFun<size_t>( [this](){ return GetNumOrgs(); }, "num_orgs", "Number of organisms currently living in the population." );
1117  if (print_header) file.PrintHeaderKeys();
1118  return file;
1119  }
1120 
1121  template<typename ORG>
1123  const fun_calc_dist_t & dist_fun,
1124  double sharing_threshold, double alpha)
1125  {
1126  fun_calc_fitness = [this, fit_fun, dist_fun, sharing_threshold, alpha](ORG & org) {
1127  double niche_count = 0;
1128  for (Ptr<ORG> org2 : pop) {
1129  if (!org2) continue;
1130  double dist = dist_fun(org, *org2);
1131  niche_count += std::max(1.0 - std::pow(dist/sharing_threshold, alpha), 0.0);
1132  }
1133  return fit_fun(org)/niche_count;
1134  };
1135  }
1136 
1137  // --- Updating the world! ---
1138 
1139  template<typename ORG>
1141  // 1. Send out an update signal for any external functions to trigger.
1142  on_update_sig.Trigger(update);
1143 
1144  // 2. If synchronous generations (i.e, pops[1] is not empty), move next population into
1145  // place as the current popoulation.
1146  if (pops[1].size()) {
1147  // Trigger signals for orgs in next pop before they are moved into the active pop.
1148  for (size_t i = 0; i < pops[1].size(); i++) {
1149  if (!pops[1][i]) continue;
1150  before_placement_sig.Trigger(*pops[1][i], i); // Trigger that org is about to be placed.
1151  }
1152 
1153  // Clear out current pop.
1154  for (size_t i = 0; i < pop.size(); i++) RemoveOrgAt(i);
1155  pop.resize(0);
1156  std::swap(pops[0], pops[1]); // Move next pop into place.
1157 
1158  // Update the active population.
1159  num_orgs = 0;
1160  for (size_t i = 0; i < pop.size(); i++) {
1161  if (!pop[i]) continue; // Ignore empty positions.
1162  ++num_orgs; // Keep count of number of organisms
1163  on_placement_sig.Trigger(i); // Trigger that organism has been placed.
1164  }
1165  }
1166 
1167  // 3. Handle systematics and any data files that need to be printed this update.
1168 
1169  // Tell systematics manager to swap next population and population
1170  for (Ptr<SystematicsBase<ORG>> s : systematics) {
1171  s->Update();
1172  }
1173 
1174  for (auto file : files) file->Update(update);
1175 
1176  // 4. Increment the current update number; i.e., count calls to Update().
1177  update++;
1178  }
1179 
1180  template<typename ORG>
1181  double World<ORG>::CalcFitnessOrg(ORG & org) {
1182  emp_assert(fun_calc_fitness);
1183  return fun_calc_fitness(org);
1184  }
1185 
1186  template<typename ORG>
1187  double World<ORG>::CalcFitnessID(size_t id) {
1188  if (!pop[id]) return 0.0;
1189  if (!cache_on) return CalcFitnessOrg(*pop[id]);
1190  double cur_fit = GetCache(id);
1191  if (cur_fit == 0.0 && pop[id]) { // If org is non-null, but no cached fitness, calculate it!
1192  if (id >= fit_cache.size()) fit_cache.resize(id+1, 0.0);
1193  cur_fit = CalcFitnessOrg(*pop[id]);
1194  fit_cache[id] = cur_fit;
1195  }
1196  return cur_fit;
1197  }
1198 
1199  // Delete all organisms.
1200  template<typename ORG>
1202  for (size_t pop_id = 0; pop_id < 2; pop_id++) {
1203  for (size_t i = 0; i < pops[pop_id].size(); i++) RemoveOrgAt(WorldPosition(i,pop_id));
1204  pops[pop_id].resize(0);
1205  }
1206  }
1207 
1208  template <typename ORG>
1209  void World<ORG>::Inject(const genome_t & mem, size_t copy_count) {
1210  for (size_t i = 0; i < copy_count; i++) {
1211  Ptr<ORG> new_org = NewPtr<ORG>(mem);
1212  inject_ready_sig.Trigger(*new_org);
1213  const WorldPosition pos = fun_find_inject_pos(new_org);
1214 
1215  if (pos.IsValid()) AddOrgAt(new_org, pos); // If placement position is valid, do so!
1216  else new_org.Delete(); // Otherwise delete the organism.
1217  }
1218  }
1219 
1220  template <typename ORG>
1221  void World<ORG>::InjectAt(const genome_t & mem, const WorldPosition pos) {
1222  emp_assert(pos.IsValid());
1223  Ptr<ORG> new_org = NewPtr<ORG>(mem);
1224  inject_ready_sig.Trigger(*new_org);
1225  AddOrgAt(new_org, pos);
1226  }
1227 
1228  template <typename ORG>
1229  template <typename... ARGS>
1230  void World<ORG>::InjectRandomOrg(ARGS &&... args) {
1231  emp_assert(random_ptr != nullptr && "InjectRandomOrg() requires active random_ptr");
1232  Ptr<ORG> new_org = NewPtr<ORG>(*random_ptr, std::forward<ARGS>(args)...);
1233  inject_ready_sig.Trigger(*new_org);
1234  const WorldPosition pos = fun_find_inject_pos(new_org);
1235 
1236  if (pos.IsValid()) AddOrgAt(new_org, pos); // If placement position is valid, do so!
1237  else new_org.Delete(); // Otherwise delete the organism.
1238  }
1239 
1240  // Give birth to (potentially) multiple offspring; return position of last placed.
1241  // Triggers 'before repro' signal on parent (once) and 'offspring ready' on each offspring.
1242  // Additional signal triggers occur in AddOrgAt.
1243  template <typename ORG>
1244  WorldPosition World<ORG>::DoBirth(const genome_t & mem, size_t parent_pos, size_t copy_count) {
1245  before_repro_sig.Trigger(parent_pos);
1246  WorldPosition pos; // Position of each offspring placed.
1247  for (size_t i = 0; i < copy_count; i++) { // Loop through offspring, adding each
1248  Ptr<ORG> new_org = NewPtr<ORG>(mem);
1249  offspring_ready_sig.Trigger(*new_org);
1250  pos = fun_find_birth_pos(new_org, parent_pos);
1251 
1252  if (pos.IsValid()) AddOrgAt(new_org, pos, parent_pos); // If placement pos is valid, do so!
1253  else new_org.Delete(); // Otherwise delete the organism.
1254  }
1255  return pos;
1256  }
1257 
1258  template<typename ORG>
1260  if (random_owner) random_ptr.Delete();
1261  random_ptr = &r;
1262  random_owner = false;
1263  }
1264 
1265  template<typename ORG>
1266  void World<ORG>::NewRandom(int seed) {
1267  if (random_owner) random_ptr.Delete();
1268  random_ptr.New(seed);
1269  random_owner = true;
1270  }
1271 
1272  // Get random *occupied* cell.
1273  template<typename ORG>
1275  emp_assert(num_orgs > 0); // Make sure it's possible to find an organism!
1276  size_t pos = random_ptr->GetUInt(0, pop.size());
1277  while (pop[pos] == nullptr) pos = random_ptr->GetUInt(0, pop.size());
1278  return pos;
1279  }
1280 
1281  // Find ALL cell IDs the return true in the filter.
1282  template<typename ORG>
1283  emp::vector<size_t> World<ORG>::FindCellIDs(const std::function<bool(ORG*)> & filter) {
1284  emp::vector<size_t> valid_IDs(0);
1285  for (size_t i = 0; i < pop.size(); i++) {
1286  if (filter(pop[i].Raw())) valid_IDs.push_back(i);
1287  }
1288  return valid_IDs;
1289  }
1290 
1291  // Run population through a bottleneck to (probably) shrink it.
1292  template<typename ORG>
1293  void World<ORG>::DoBottleneck(const size_t new_size, bool choose_random) {
1294  if (new_size >= num_orgs) return; // No bottleneck needed!
1295 
1296  if (is_space_structured || is_pheno_structured) {
1297  // @CAO: Need to implement bottlenecks for structured populations.
1298  emp_assert(false, "Not implemented yet.");
1299  } else {
1300  // If we are supposed to keep only random organisms, shuffle the beginning into place!
1301  if (choose_random) {
1302  for (size_t to = 0; to < new_size; to++) {
1303  const size_t from = random_ptr->GetUInt(to, pop.size());
1304  if (from == to) continue;
1305  Swap(to, from);
1306  }
1307  }
1308 
1309  // Clear out all of the organisms we are removing and shrink the population.
1310  for (size_t i = new_size; i < pop.size(); ++i) RemoveOrgAt(i);
1311  pop.resize(new_size);
1312  ClearCache();
1313  }
1314  }
1315 
1316  template<typename ORG>
1317  void World<ORG>::SerialTransfer(const double keep_frac) {
1318  emp_assert(keep_frac >= 0.0 && keep_frac <= 1.0, keep_frac);
1319 
1320  // For a structured population, test position-by-position.
1321  if (is_space_structured || is_pheno_structured) {
1322  // Loop over the current population to clear out anyone who fails to be transferred.
1323  const double remove_frac = 1.0 - keep_frac;
1324  for (size_t i = 0; i < pop.size(); ++i) {
1325  if (random_ptr->P(remove_frac)) {
1326  RemoveOrgAt(i);
1327  ClearCache(i);
1328  }
1329  }
1330  }
1331 
1332  // For an unstructured population, keep all living organisms at the beginning.
1333  else {
1334  size_t live_pos = 0;
1335  for (size_t test_pos = 0; test_pos < pop.size(); test_pos++) {
1336  // If this organism is kept, keep it compact with the others.
1337  if (random_ptr->P(keep_frac)) {
1338  Swap(live_pos, test_pos);
1339  live_pos++;
1340  }
1341 
1342  // This organism didn't make the cut; kill it.
1343  else RemoveOrgAt(test_pos);
1344  }
1345 
1346  // Reflect the new population size.
1347  pop.resize(live_pos);
1348  ClearCache();
1349  }
1350  }
1351 
1352  template<typename ORG>
1353  void World<ORG>::Print(std::ostream & os, const std::string & empty, const std::string & spacer) {
1354  for (Ptr<ORG> org : pop) {
1355  if (org) os << fun_print_org(*org, os);
1356  else os << empty;
1357  os << spacer;
1358  }
1359  }
1360 
1361  template<typename ORG>
1362  void World<ORG>::PrintOrgCounts(std::ostream & os) {
1363  std::map<ORG,size_t> org_counts;
1364  for (Ptr<ORG> org : pop) if (org) org_counts[*org] = 0; // Initialize needed entries
1365  for (Ptr<ORG> org : pop) if (org) org_counts[*org] += 1; // Count actual types.
1366  for (auto x : org_counts) {
1367  ORG cur_org = x.first;
1368  fun_print_org(cur_org, os);
1369  os << " : " << x.second << std::endl;
1370  }
1371  }
1372 
1373  template<typename ORG>
1374  void World<ORG>::PrintGrid(std::ostream& os,
1375  const std::string & empty, const std::string & spacer) {
1376  emp_assert(pop_sizes.size() == 2);
1377  const size_t size_x = pop_sizes[0];
1378  const size_t size_y = pop_sizes[1];
1379  for (size_t y=0; y < size_y; y++) {
1380  for (size_t x = 0; x < size_x; x++) {
1381  Ptr<ORG> org = GetOrgPtr(x+y*size_x);
1382  if (org) fun_print_org(*org, os);
1383  else os << empty;
1384  os << spacer;
1385  }
1386  os << std::endl;
1387  }
1388  }
1389 
1390 }
1391 
1392 #endif
void SetMutFun(const fun_do_mutations_t &mut_fun)
Definition: World.h:500
iterator_t begin()
[std::vector compatibility] Return iterator to first organism.
Definition: World.h:842
Ptr< DataMonitor< double > > GetFitnessDataNode()
Definition: World.h:451
Signal< void(ORG &, size_t)> before_placement_sig
...before placing any organism into target cell.
Definition: World.h:181
void NewRandom(int seed=-1)
Create a new random number generator (that World will manage)
Definition: World.h:1266
SignalKey tracks a specific function triggered by a signal. For now, its just a value pair...
Definition: Signal.h:30
fun_do_mutations_t fun_do_mutations
...mutate an organism.
Definition: World.h:160
fun_print_org_t fun_print_org
...print an organism.
Definition: World.h:161
void AddPhenotype(Ts &&...args)
Add a new phenotype measuring function.
Definition: World.h:444
Ptr< SystematicsBase< ORG > > GetSystematics(int id=0)
Definition: World.h:347
Functions for popular world structure methods.
Definition: Systematics.h:214
Definition: World_structure.h:29
Signal< void(size_t)> on_placement_sig
...after any organism is placed into world.
Definition: World.h:182
void SetPopStruct_Mixed(bool synchronous_gen=false)
Definition: World.h:955
void Resize(size_t new_width, size_t new_height)
Change the size of the world based on width and height.
Definition: World.h:729
const emp::TraitSet< ORG > & GetPhenotypes() const
What phenotypic traits is the population tracking?
Definition: World.h:263
std::function< WorldPosition(Ptr< ORG >, WorldPosition)> fun_find_birth_pos_t
Function type for adding a newly born organism into a world (returns birth position) ...
Definition: World.h:126
bool IsSpaceStructured() const
Definition: World.h:288
void resize(size_t new_size)
[std::vector compatibility] Update world size.
Definition: World.h:836
World_iterator< this_t > iterator_t
Type for this world&#39;s iterators.
Definition: World.h:102
size_t GetHeight() const
How many cells tall is the world? (assumes grids are active.)
Definition: World.h:257
std::string to_string(ALL_TYPES &&...all_values)
Definition: string_utils.h:511
void Process(ARGS &&...args)
Definition: World.h:651
double CalcFitnessOrg(ORG &org)
Use the configured fitness function on the specified organism.
Definition: World.h:1181
void RemoveSystematics(int id)
Definition: World.h:363
Signal< void()> world_destruct_sig
...in the World destructor.
Definition: World.h:186
std::function< WorldPosition(Ptr< ORG >)> fun_find_inject_pos_t
Function type for injecting organisms into a world (returns inject position)
Definition: World.h:123
fun_kill_org_t fun_kill_org
...kill an organism.
Definition: World.h:165
emp::TraitSet< ORG > phenotypes
What phenotypes are we tracking?
Definition: World.h:148
void Delete()
Definition: Ptr.h:737
void SetRandom(Random &r)
Setup a new random number generator created elsewhere.
Definition: World.h:1259
Random & GetRandom()
Return a reference to the random number generator currently being used by world.
Definition: World.h:770
DataFile & AddDataFile(emp::Ptr< DataFile > file)
Add an already-constructed datafile.
Definition: World.h:1054
WorldPosition DoBirth(const genome_t &mem, size_t parent_pos, size_t copy_count=1)
Place one or more copies of an offspring into population; return position of last placed...
Definition: World.h:1244
DataManagers handle sets of DataNode objects that all have the same tracking settings.
Definition: DataManager.h:25
fit_cache_t fit_cache
vector size == 0 when not caching; uncached values == 0.
Definition: World.h:142
void DoBottleneck(const size_t new_size, bool choose_random=true)
Run population through a bottleneck to (potentially) shrink it.
Definition: World.h:1293
void SetKillOrgFun(const fun_kill_org_t &_fun)
Definition: World.h:522
std::string name
Name of this world (for use in configuration.)
Definition: World.h:145
void SetSynchronousSystematics(bool synchronous)
Tell systematics managers that this world has synchronous generations.
Definition: World.h:433
uint32_t GetPopID() const
Definition: World_structure.h:45
node_t & New(const std::string &name)
Creates and adds a new DataNode, with the name specified in.
Definition: DataManager.h:48
uint32_t GetIndex() const
Definition: World_structure.h:44
DataFile & SetupPopulationFile(const std::string &filename="population.csv", const bool &print_header=true)
Setup a file to be printed that collects population information over time.
Definition: World.h:1113
A versatile and non-patterned pseudo-random-number generator (Mersenne Twister).
Definition: ce_random.h:52
fun_find_inject_pos_t fun_find_inject_pos
...find where to inject a new, external organism.
Definition: World.h:163
fun_find_birth_pos_t fun_find_birth_pos
...find where to add a new offspring organism.
Definition: World.h:164
void CalcFitnessAll() const
Calculate the fitness of all organisms, storing the results in the cache.
Definition: World.h:676
Handle reflection on organisms to setup reasonable defaults in World.
decltype(Org2Genome< ORG >(true)) find_genome_t
Definition: World_reflect.h:124
const genome_t & GetGenome(ORG &org)
Retrieve the genome corresponding to a specified organism.
Definition: World.h:339
bool IsSynchronous() const
Definition: World.h:284
void InjectAt(const genome_t &mem, const WorldPosition pos)
Inject an organism at a specific position.
Definition: World.h:1221
emp::vector< Ptr< SystematicsBase< ORG > > > systematics
Phylogeny and line-of-descent data collection.
Definition: World.h:172
void DoMutationsOrg(ORG &org)
Use mutation function on a single, specified organism.
Definition: World.h:691
SignalKey OnBeforePlacement(const std::function< void(ORG &, size_t)> &fun)
Definition: World.h:576
void push_back(PB_Ts &&...args)
Definition: vector.h:189
void MakeValid(WorldPosition pos)
Make sure position is valid; if not expand relevant vector.
Definition: World_structure.h:71
void SetGetNeighborFun(const fun_get_neighbor_t &_fun)
Definition: World.h:526
void ClearCache()
Remove all currently cached fitness values (useful with changing environments, etc.)
Definition: World.h:685
void SetAddInjectFun(const fun_find_inject_pos_t &_fun)
Definition: World.h:513
std::unordered_map< std::string, int > systematics_labels
Definition: World.h:173
DataManager< double, data::Current, data::Info, data::Range, data::Stats > data_nodes
Potential data nodes – these should be activated only if in use.
Definition: World.h:156
std::function< size_t(ORG &, Random &)> fun_do_mutations_t
Function type for a mutation operator on an organism.
Definition: World.h:114
void ResetHardware()
Reset the hardware for all organisms.
Definition: World.h:663
this_t & MarkSpaceStructured(bool in=true)
Definition: World.h:300
size_t update
How many times has Update() been called?
Definition: World.h:136
size_t num_orgs
How many organisms are actually in the population.
Definition: World.h:141
SignalKey OnInjectReady(const std::function< void(ORG &)> &fun)
Definition: World.h:567
void DoDeath(const WorldPosition pos)
Definition: World.h:762
Setup a World with a population of organisms that can evolve or deal with ecological effects...
Definition: World.h:94
std::vector< size_t > pop_sizes
Sizes of population dimensions (eg, 2 vals for grid)
Definition: World.h:147
fun_calc_fitness_t fun_calc_fitness
...evaluate fitness for provided organism.
Definition: World.h:159
void AddTrait(const std::string &name, const std::function< VALUE_T(target_t &)> &fun, EXTRA &&...extra)
Definition: Trait.h:145
size_t size() const
Definition: vector.h:151
WorldPosition GetRandomNeighborPos(WorldPosition pos)
Use the specified function to get a neighbor (if not set, assume well mixed).
Definition: World.h:788
void Inject(const genome_t &mem, size_t copy_count=1)
Inject an organism using the default injection scheme.
Definition: World.h:1209
void emplace_back(ARGS &&...args)
Definition: vector.h:219
std::function< WorldPosition(WorldPosition)> fun_get_neighbor_t
Function type for identifying an organism&#39;s random neighbor.
Definition: World.h:132
void DoDeath()
Definition: World.h:765
Definition: DataNode.h:648
ORG & GetOrg(size_t x, size_t y)
Definition: World.h:324
std::function< WorldPosition()> fun_kill_org_t
Function type for determining picking and killing an organism (returns newly empty position) ...
Definition: World.h:129
void Resize(size_t new_size)
Definition: World.h:723
WorldPosition & SetPopID(size_t _id)
Definition: World_structure.h:51
constexpr uint32_t GetUInt(const uint32_t max)
Definition: ce_random.h:191
T Product(const emp::vector< T > &v)
Multiply all of the contents of a vector.
Definition: vector_utils.h:86
Functions for popular selection methods applied to worlds.
bool IsActive() const
Definition: World_structure.h:47
std::function< double(ORG &, ORG &)> fun_calc_dist_t
Function type for calculating the distance between two organisms.
Definition: World.h:111
void SetPopStruct_Grid(size_t width, size_t height, bool synchronous_gen=false)
Definition: World.h:999
void Update()
Definition: World.h:1140
std::function< const genome_t &(ORG &)> fun_get_genome_t
Function type for retrieving a genome from an organism.
Definition: World.h:120
size_t size() const
[std::vector compatibility] How big is the world?
Definition: World.h:833
iterator_t end()
[std::vector compatibility] Return iterator just past last organism.
Definition: World.h:845
auto Find(const MAP_T &in_map, const KEY_T &key, const typename MAP_T::mapped_type &dval)
Definition: map_utils.h:29
void DoMutationsID(size_t id)
Use mutation function on the organism at the specified position in the population.
Definition: World.h:697
void SetPrintFun(const fun_print_org_t &print_fun)
Definition: World.h:505
size_t GetSize() const
How many organisms can fit in the world?
Definition: World.h:245
void Resize(const emp::vector< size_t > &dims)
Change the size of the world based on a vector of dimensions.
Definition: World.h:736
bool IsCacheOn() const
Are we currently caching fitness values?
Definition: World.h:280
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
constexpr int Mod(int in_val, int mod_val)
% is actually remainder; Mod is a proper modulus command that handles negative #&#39;s correctly ...
Definition: math.h:26
void SetSharedFitFun(const fun_calc_fitness_t &fit_fun, const fun_calc_dist_t &dist_fun, double sharing_threshold, double alpha)
Definition: World.h:1122
void resize(size_t new_size)
Definition: array.h:165
Definition: World_iterator.h:23
pop_t & pop
A shortcut to pops[0].
Definition: World.h:140
void Clear()
Remove all organisms from the world.
Definition: World.h:1201
Signal< void(ORG &)> inject_ready_sig
...when outside organism is ready to inject.
Definition: World.h:180
This file defines iterators for use with emp::World objects.
ORG & GetRandomOrg()
Get an organism from a random occupied cell.
Definition: World.h:794
void SetAddBirthFun(const fun_find_birth_pos_t &_fun)
Definition: World.h:518
bool cache_on
Should we be caching fitness values?
Definition: World.h:146
const genome_t & GetGenomeAt(size_t id)
Retrive the genome corresponding to the organism at the specified position.
Definition: World.h:342
bool random_owner
Did we create our own random number generator?
Definition: World.h:138
World(Random &rnd, std::string _name="")
Definition: World.h:228
void SetPopStruct_Grow(bool synchronous_gen=false)
Definition: World.h:909
A vector that can be indexed with a WorldPosition.
Definition: World_structure.h:58
void SetAttribute(const std::string &name, T &&val)
Definition: World.h:636
size_t GetUpdate() const
What update number is the world currently on? (assumes Update() is being used)
Definition: World.h:251
void clear()
[std::vector compatibility] Remove all organisms.
Definition: World.h:839
const ORG & operator[](size_t id) const
Definition: World.h:309
constexpr size_t size() const
Definition: array.h:137
bool Has(const MAP_T &in_map, const KEY_T &key)
Take any map type, and run find to determine if a key is present.
Definition: map_utils.h:21
bool IsValid(WorldPosition pos) const
Test if a position is currently valid.
Definition: World_structure.h:63
void Print(std::ostream &os=std::cout, const std::string &empty="-", const std::string &spacer=" ")
Print all organisms in the population using previously provided print function.
Definition: World.h:1353
SignalKey OnUpdate(const std::function< void(size_t)> &fun)
Definition: World.h:593
void resize(size_t new_size)
Definition: vector.h:161
void RemoveSystematics(std::string label)
Definition: World.h:377
void ClearCache(size_t id)
Clear the cache value at the specified position.
Definition: World.h:195
std::function< double(ORG &)> fun_calc_fitness_t
Function type for calculating fitness.
Definition: World.h:108
org_t value_type
Identical to org_t; vector compatibility.
Definition: World.h:100
DataFile & SetupFitnessFile(const std::string &filename="fitness.csv", const bool &print_header=true)
Setup a file to be printed that collects fitness information over time.
Definition: World.h:1072
SignalKey OnSwapOrgs(const std::function< void(WorldPosition, WorldPosition)> &fun)
Definition: World.h:609
const Ptr< ORG > GetOrgPtr(size_t id) const
Definition: World.h:328
void SerialTransfer(const double keep_frac)
Perform a Serial Transfer where a fixed percentage of current organisms are maintained.
Definition: World.h:1317
SignalKey OnOffspringReady(const std::function< void(ORG &)> &fun)
Definition: World.h:559
ORG & GetOrg(size_t id)
Definition: World.h:316
SignalKey OnBeforeRepro(const std::function< void(size_t)> &fun)
Definition: World.h:550
void SetAutoMutate()
Definition: World.h:419
WorldVector< Ptr< ORG > > pops
The set of active [0] and "next" [1] organisms in population.
Definition: World.h:139
std::string GetAttribute(const std::string) const
Get the value for an attribute that you know exists.
Definition: World.h:628
void SetGetGenomeFun(const fun_get_genome_t &_fun)
Definition: World.h:509
emp::vector< size_t > GetEmptyPopIDs()
Return IDs of all empty cells in the population.
Definition: World.h:807
SignalKey OnPlacement(const std::function< void(size_t)> &fun)
Definition: World.h:585
void DoMutations(size_t start_id=0)
Use mutation function on ALL organisms in the population.
Definition: World.h:703
void PrintOrgCounts(std::ostream &os=std::cout)
Print unique organisms and the number of copies of each that exist.
Definition: World.h:1362
bool IsPhenoStructured() const
Definition: World.h:292
std::map< std::string, std::string > attributes
Attributes are a dynamic way to track extra characteristics about a world.
Definition: World.h:169
Ptr< Random > random_ptr
Random object to use.
Definition: World.h:137
SignalControl & GetSignalControl()
Access signal controller used for this world directly.
Definition: World.h:543
If we are in emscripten, make sure to include the header.
Definition: array.h:37
A tool to track phylogenetic relationships among organisms. The systematics class tracks the relation...
Definition: Systematics.h:355
size_t GetRandomCellID()
Get the position a cell, at random.
Definition: World.h:779
Signal< void(WorldPosition, WorldPosition)> on_swap_sig
...after org positions are swapped
Definition: World.h:185
fun_get_neighbor_t fun_get_neighbor
...choose a random neighbor "near" specified id.
Definition: World.h:166
Definition: Ptr.h:711
Build a debug wrapper emp::vector around std::vector.
Definition: vector.h:42
~World()
Definition: World.h:230
void InjectRandomOrg(ARGS &&...args)
Inject a random organism (constructor must facilitate!)
Definition: World.h:1230
SignalKey OnWorldDestruct(const std::function< void()> &fun)
Definition: World.h:617
size_t GetWidth() const
How many cells wide is the world? (assumes grids are active.)
Definition: World.h:254
Signal< void(size_t)> on_death_sig
...immediately before any organism dies.
Definition: World.h:184
size_t GetRandomOrgID()
Get the id of a random occupied cell.
Definition: World.h:1274
void PrintGrid(std::ostream &os=std::cout, const std::string &empty="-", const std::string &spacer=" ")
Print the organisms layed out in a grid structure (assumes a grid population.)
Definition: World.h:1374
void Reset()
Methods to reset data.
Definition: DataNode.h:670
double CalcFitnessID(size_t id)
Use the configured fitness function on the organism at the specified position.
Definition: World.h:1187
#define emp_assert(...)
Definition: assert.h:199
World(std::string _name="", bool gen_random=true)
Definition: World.h:203
void ProcessID(size_t id, ARGS &&...args)
Definition: World.h:658
typename emp::find_genome_t< ORG > genome_t
Type of underlying genomes.
Definition: World.h:105
Definition: SignalControl.h:28
void SetAutoMutate(std::function< bool(size_t pos)> test_fun)
Definition: World.h:427
DataFile & GetFile(const std::string &filename)
Lookup a file by name.
Definition: World.h:269
bool HasAttribute(const std::string &name) const
Definition: World.h:625
emp::vector< emp::Ptr< DataFile > > files
Output files.
Definition: World.h:149
size_t GetNumOrgs() const
How many organisms are currently in the world?
Definition: World.h:248
iterator erase(ARGS &&...args)
Definition: vector.h:207
void New(T &&...args)
Definition: Ptr.h:735
SignalControl control
Definition: World.h:176
void SetFitFun(const fun_calc_fitness_t &fit_fun)
Definition: World.h:496
void RemoveOrgAt(WorldPosition pos)
Definition: World.h:887
Ptr< DataMonitor< double > > AddDataNode(const std::string &name)
Definition: World.h:470
void AddOrgAt(Ptr< ORG > new_org, WorldPosition pos, WorldPosition p_pos=WorldPosition())
Definition: World.h:856
const pop_t & GetFullPop() const
Get the full population to analyze externally.
Definition: World.h:260
Ptr< DataMonitor< double > > GetDataNode(const std::string &name)
Definition: World.h:475
bool IsValid() const
Definition: World_structure.h:48
Definition: DataFile.h:32
const node_t & Get(const std::string &name) const
Definition: DataManager.h:63
this_t & MarkPhenoStructured(bool in=true)
Definition: World.h:304
Ptr< SystematicsBase< ORG > > GetSystematics(std::string label)
Definition: World.h:356
Signal< void(size_t)> on_update_sig
...at the beginning of Update()
Definition: World.h:183
void AddSystematics(Ptr< Systematics< ORG, ORG_INFO, DATA_STRUCT > > s, std::string label="systematics")
Definition: World.h:386
Signal< void(size_t)> before_repro_sig
...before organism gives birth w/parent position.
Definition: World.h:178
fun_get_genome_t fun_get_genome
...determine the genome object of an organism.
Definition: World.h:162
fun_calc_fitness_t GetFitFun()
Get the fitness function currently in use.
Definition: World.h:400
std::function< void(ORG &, std::ostream &)> fun_print_org_t
Function type for printing an organism&#39;s info to an output stream.
Definition: World.h:117
ORG org_t
Type of organisms in this world.
Definition: World.h:99
emp::vector< size_t > GetValidOrgIDs()
Return IDs of all occupied cells in the population.
Definition: World.h:804
size_t GetRandomCellID(size_t min_id, size_t max_id)
Get the position a cell in a range, at random.
Definition: World.h:782
bool is_pheno_structured
Do we have a phenotypically structured population?
Definition: World.h:153
void Reset()
Clear all of the orgs and reset stats.
Definition: World.h:713
bool is_space_structured
Do we have a spatially structured population?
Definition: World.h:152
Signal< void(ORG &)> offspring_ready_sig
...when offspring organism is built.
Definition: World.h:179
Track genotypes, species, clades, or lineages of organisms in a world.
emp::vector< size_t > FindCellIDs(const std::function< bool(ORG *)> &filter)
Find ALL cell IDs that return true in the provided filter.
Definition: World.h:1283
void SetCache(bool _in=true)
Turn on (or off) fitness caching for individual organisms.
Definition: World.h:682
DataFile & SetupSystematicsFile(std::string label, const std::string &filename="systematics.csv", const bool &print_header=true)
Setup a file (by label) to be printed that collects systematics information over time.
Definition: World.h:1087
double GetCache(size_t id) const
Get the current cached value for the organism at the specified position.
Definition: World.h:192
bool IsOccupied(WorldPosition pos) const
Does the specified cell ID have an organism in it?
Definition: World.h:277
SignalKey OnOrgDeath(const std::function< void(size_t)> &fun)
Definition: World.h:601
this_t & MarkSynchronous(bool in=true)
Definition: World.h:296
ORG & GetNextOrg(size_t id)
Definition: World.h:332
bool is_synchronous
Does this world have synchronous generations?
Definition: World.h:151
bool HasNode(const std::string &name)
Definition: DataManager.h:43
void Swap(WorldPosition pos1, WorldPosition pos2)
Swap the positions of two organisms.
Definition: World.h:716
DataFile & SetupFile(const std::string &filename)
Setup an arbitrary file; no default filename available.
Definition: World.h:1063