Empirical
World_structure.h
Go to the documentation of this file.
1 
10 #ifndef EMP_EVO_WORLD_STRUCTURE_H
11 #define EMP_EVO_WORLD_STRUCTURE_H
12 
13 #include "../base/assert.h"
14 #include "../base/vector.h"
15 #include "../data/Trait.h"
16 #include "../tools/Random.h"
17 #include "../tools/vector_utils.h"
18 
19 namespace emp {
20 
21  template <typename ORG> class World;
22 
26  //
27  // Developer NOTE: For efficiency, internal class members are uint32_t, but to prevent compiler
28  // warnings, size_t values are accepted; asserts ensure safe conversions.
29  class WorldPosition {
30  private:
31  uint32_t index;
32  uint32_t pop_id;
33 
34  public:
35  static constexpr size_t invalid_id = (uint32_t) -1;
36 
37  WorldPosition() : index(invalid_id), pop_id(invalid_id) { ; }
38  WorldPosition(size_t _id, size_t _pop_id=0) : index((uint32_t) _id), pop_id((uint32_t) _pop_id) {
39  emp_assert(_id <= invalid_id);
40  emp_assert(_pop_id <= invalid_id);
41  }
42  WorldPosition(const WorldPosition &) = default;
43 
44  uint32_t GetIndex() const { return index; }
45  uint32_t GetPopID() const { return pop_id; }
46 
47  bool IsActive() const { return pop_id == 0; }
48  bool IsValid() const { return index != invalid_id; }
49 
50  WorldPosition & SetActive(bool _active=true) { pop_id = 0; return *this; }
51  WorldPosition & SetPopID(size_t _id) { emp_assert(_id <= invalid_id); pop_id = (uint32_t) _id; return *this; }
52  WorldPosition & SetIndex(size_t _id) { emp_assert(_id <= invalid_id); index = (uint32_t) _id; return *this; }
53  WorldPosition & MarkInvalid() { index = invalid_id; pop_id = invalid_id; return *this; }
54  };
55 
57  template <typename T>
58  class WorldVector : public emp::array<emp::vector<T>, 2> {
59  public:
60  using base_t = emp::array<emp::vector<T>, 2>;
61 
63  bool IsValid(WorldPosition pos) const {
64  const size_t pop_id = pos.GetPopID();
65  const size_t id = pos.GetIndex();
66  emp_assert(pop_id < 2);
67  return id < base_t::operator[](pop_id).size();
68  }
69 
72  const size_t pop_id = pos.GetPopID();
73  const size_t id = pos.GetIndex();
74  emp_assert(pop_id < 2);
75  if (id >= base_t::operator[](pop_id).size()) {
76  base_t::operator[](pop_id).resize(id+1);
77  }
78  }
79 
81  const size_t pop_id = pos.GetPopID();
82  const size_t id = pos.GetIndex();
83  return base_t::operator[](pop_id)[id];
84  }
85  const T & operator()(WorldPosition pos) const {
86  const size_t pop_id = pos.GetPopID();
87  const size_t id = pos.GetIndex();
88  return base_t::operator[](pop_id)[id];
89  }
90  };
91 
95  template <typename ORG>
96  void SetPools(World<ORG> & world, size_t num_pools,
97  size_t pool_size, bool synchronous_gen=false) {
98  world.Resize(pool_size, num_pools);
99  world.MarkSynchronous(synchronous_gen);
100  world.MarkSpaceStructured(true).MarkPhenoStructured(false);
101 
102  // -- Setup functions --
103  // Inject in an empty pool -or- randomly if none empty
104  world.SetAddInjectFun( [&world,pool_size](Ptr<ORG> new_org) {
105  for (size_t id = 0; id < world.GetSize(); id += pool_size) {
106  if (world.IsOccupied(id) == false) return WorldPosition(id);
107  }
108  return WorldPosition(world.GetRandomCellID());
109  });
110 
111  // Neighbors are everyone in the same pool.
112  world.SetGetNeighborFun( [&world,pool_size](WorldPosition pos) {
113  const size_t pool_start = (pos.GetIndex() / pool_size) * pool_size;
114  return pos.SetIndex(pool_start + world.GetRandom().GetUInt(pool_size));
115  });
116 
117  world.SetKillOrgFun( [&world](){
118  const size_t kill_id = world.GetRandomCellID();
119  world.RemoveOrgAt(kill_id);
120  return kill_id;
121  });
122 
123  if (synchronous_gen) {
124  // Place births in the next open spot in the new pool (or randomly if full!)
125  world.SetAddBirthFun( [&world,pool_size](Ptr<ORG> new_org, WorldPosition parent_pos) {
126  emp_assert(new_org); // New organism must exist.
127  const size_t parent_id = parent_pos.GetIndex();
128  const size_t pool_id = parent_id / pool_size;
129  const size_t start_id = pool_id * pool_size;
130  for (size_t id = start_id; id < start_id+pool_size; id++) {
131  if (world.IsOccupied(WorldPosition(id,1)) == false) { // Search for an open position...
132  return WorldPosition(id, 1);
133  }
134  }
135  WorldPosition pos = world.GetRandomNeighborPos(parent_pos); // Placed near parent, in next pop.
136  return pos.SetPopID(1);
137  });
138  world.SetAttribute("SynchronousGen", "True");
139  } else {
140  // Asynchronous: always go to a neighbor in current population.
141  world.SetAddBirthFun( [&world](Ptr<ORG> new_org, WorldPosition parent_pos) {
142  auto pos = world.GetRandomNeighborPos(parent_pos);
143  return pos; // Place org in existing population.
144  });
145  world.SetAttribute("SynchronousGen", "False");
146  }
147 
148  world.SetAttribute("PopStruct", "Pools");
149  world.SetSynchronousSystematics(synchronous_gen);
150  }
151 
152 
163  template <typename ORG>
164  void SetMapElites(World<ORG> & world, TraitSet<ORG> traits,
165  const emp::vector<size_t> & trait_counts) {
166  world.Resize(trait_counts); // World sizes are based on counts of traits options.
167  world.MarkSynchronous(false);
168  world.MarkSpaceStructured(false).MarkPhenoStructured(true);
169 
170  // -- Setup functions --
171  // Inject into the appropriate positon based on phenotype. Note that an inject will fail
172  // if a more fit organism is already in place; you must run clear first if you want to
173  // ensure placement.
174  world.SetAddInjectFun( [&world,traits,trait_counts](Ptr<ORG> new_org) {
175  // Determine tha position that this phenotype fits in.
176  double org_fitness = world.CalcFitnessOrg(*new_org);
177  size_t id = traits.EvalBin(*new_org, trait_counts);
178  double cur_fitness = world.CalcFitnessID(id);
179 
180  if (cur_fitness > org_fitness) return WorldPosition(); // Return invalid position!
181  return WorldPosition(id);
182  });
183 
184  // Map-Elites does not have a concept of neighbors.
185  world.SetGetNeighborFun( [](WorldPosition pos) { emp_assert(false); return pos; });
186 
187  // Map-Elites doesn't have a real meaning for killing organisms, so do so randomly.
188  world.SetKillOrgFun( [&world](){
189  const size_t kill_id = world.GetRandomCellID();
190  world.RemoveOrgAt(kill_id);
191  return kill_id;
192  });
193 
194  // Birth is effectively the same as inject.
195  world.SetAddBirthFun( [&world,traits,trait_counts](Ptr<ORG> new_org, WorldPosition parent_pos) {
196  (void) parent_pos; // Parent position is not needed for MAP Elites.
197  // Determine tha position that this phenotype fits in.
198  double org_fitness = world.CalcFitnessOrg(*new_org);
199  size_t id = traits.EvalBin(*new_org, trait_counts);
200  double cur_fitness = world.CalcFitnessID(id);
201 
202  if (cur_fitness > org_fitness) return WorldPosition(); // Return invalid position!
203  return WorldPosition(id);
204  });
205 
206  world.SetAttribute("SynchronousGen", "False");
207  world.SetAttribute("PopStruct", "MapElites");
208  world.SetSynchronousSystematics(false);
209  }
210 
213  template <typename ORG>
214  void SetMapElites(World<ORG> & world, TraitSet<ORG> traits) {
215  emp::vector<size_t> trait_counts;
216  emp_assert(traits.GetSize() > 0);
217 
218  // If there's only a single trait, it should get the full population.
219  if (traits.GetSize() == 1) {
220  trait_counts.push_back(world.GetSize());
221  SetMapElites(world, traits, trait_counts);
222  return;
223  }
224  const size_t num_traits = traits.GetSize();
225  size_t trait_size = 1;
226  while (Pow(trait_size+1, num_traits) < world.GetSize()) trait_size++;
227  trait_counts.resize(num_traits, trait_size);
228  SetMapElites(world, traits, trait_counts);
229  }
230 
233  template <typename ORG>
234  void SetMapElites(World<ORG> & world, const emp::vector<size_t> & trait_counts) {
235  SetMapElites(world, world.GetPhenotypes(), trait_counts);
236  }
237 
240  template <typename ORG>
241  void SetMapElites(World<ORG> & world) { SetMapElites(world, world.GetPhenotypes()); }
242 
243 
244 
250 
258 
260  // Note: Assuming that once a position is filled it will never be empty again.
261  template <typename ORG>
263  static constexpr size_t ID_NONE = (size_t) -1;
264 
267 
273 
274  bool is_setup;
275  size_t num_trait_bins;
276  size_t num_total_bins;
279 
280  World_MinDistInfo(World<ORG> & in_world, const TraitSet<ORG> & in_traits)
281  : nearest_id(), distance(), world(in_world), traits(in_traits)
282  , min_vals(traits.GetSize(), std::numeric_limits<double>::max())
283  , max_vals(traits.GetSize(), std::numeric_limits<double>::min())
284  , bin_width(traits.GetSize(), 0.00001)
285  , is_setup(false), num_trait_bins(0), num_total_bins(0), bin_ids(), org_bins()
286  { ; }
287 
288  double CalcDist(size_t id1, size_t id2) {
289  emp::vector<double> offsets = traits.CalcOffsets(world.GetOrg(id1), world.GetOrg(id2));
290  double dist = 0.0;
291  for (double offset : offsets) dist += offset * offset;
292  return dist;
293  }
294 
295  // Helper function for testing an organism against everything in a specified bin.
296  void Refresh_AgainstBin(size_t refresh_id, size_t target_bin) {
297  emp_assert(target_bin < bin_ids.size(), target_bin, bin_ids.size());
298  for (size_t id2 : bin_ids[target_bin]) {
299  if (id2 == refresh_id) continue;
300  const double cur_dist = CalcDist(id2, refresh_id);
301  if (cur_dist < distance[refresh_id]) {
302  distance[refresh_id] = cur_dist;
303  nearest_id[refresh_id] = id2;
304  }
305  if (cur_dist < distance[id2]) {
306  distance[id2] = cur_dist;
307  nearest_id[id2] = refresh_id;
308  }
309  }
310  }
311 
312  // Find the closest connection to a position again; update neighbors as well!
313  void Refresh(size_t refresh_id, size_t start_id = 0) {
314  emp_assert(refresh_id < world.GetSize()); // Make sure ID is legal.
315  nearest_id[refresh_id] = ID_NONE;
316  distance[refresh_id] = std::numeric_limits<double>::max();
317 
318  // First compare against everything else in the current bin.
319  size_t bin_id = org_bins[refresh_id];
320  Refresh_AgainstBin(refresh_id, bin_id);
321 
322  // Then check all neighbor bins. Ignoring diagnols for now since they could be expensive...
323  // (though technically we need them...)
324  size_t trait_offset = 1;
325  for (size_t trait_id = 0; trait_id < traits.GetSize(); trait_id++) {
326  size_t prev_bin_id = bin_id - trait_offset;
327  if (prev_bin_id < num_total_bins) {
328  Refresh_AgainstBin(refresh_id, prev_bin_id);
329  }
330  size_t next_bin_id = bin_id + trait_offset;
331  if (next_bin_id < num_total_bins) {
332  Refresh_AgainstBin(refresh_id, next_bin_id);
333  }
334  trait_offset *= num_trait_bins;
335  }
336 
337  }
338 
340  size_t CalcBin(size_t id) {
341  static emp::vector<double> t_vals;
342  t_vals = traits.EvalValues(world.GetOrg(id));
343  size_t scale = 1;
344  size_t bin_id = (size_t) -1;
345  for (size_t i = 0; i < traits.GetSize(); i++) {
346  const size_t cur_bin = (size_t) ((t_vals[i] - min_vals[i]) / bin_width[i]);
347  emp_assert(cur_bin < num_total_bins);
348  bin_id += cur_bin * scale;
349  scale *= num_trait_bins;
350  }
351  emp_assert(bin_id < num_total_bins, bin_id, num_total_bins, scale);
352  return bin_id;
353  }
354 
356  void ResetBins() {
357  bin_ids.resize(num_total_bins);
358  for (auto & bin : bin_ids) bin.clear();
359  for (size_t trait_id = 0; trait_id < traits.GetSize(); trait_id++) {
360  bin_width[trait_id] = (max_vals[trait_id] - min_vals[trait_id]) / (double) num_trait_bins;
361  }
362  org_bins.resize(world.GetSize());
363  for (size_t org_id = 0; org_id < world.GetSize(); org_id++) {
364  size_t cur_bin = CalcBin(org_id);
365  org_bins[org_id] = cur_bin;
366  bin_ids[cur_bin].insert(org_id);
367  }
368  }
369 
370  void Setup() {
371  const size_t num_orgs = world.GetSize();
372  emp_assert(num_orgs >= 2); // Must have at least 2 orgs in the population to setup.
373  const size_t num_traits = traits.GetSize();
374  emp_assert(num_traits >= 1); // We must have at least one dimension!
375 
376  nearest_id.resize(num_orgs);
377  distance.resize(num_orgs);
378 
379  // How many bins should each trait be divided into?
380  num_trait_bins = (size_t) (std::pow(num_orgs, 1.0 / (double)num_traits) + 0.5);
381  num_total_bins = (size_t) (std::pow(num_trait_bins, num_traits) + 0.5);
382  ResetBins();
383 
384  // Setup (Refresh) all distances.
385  for (size_t id = 0; id < num_orgs; id++) { Refresh(id, id+1); }
386  is_setup = true;
387  }
388 
389  void Clear() {
390  nearest_id.resize(0);
391  distance.resize(0);
392  is_setup = false;
393  }
394 
397  size_t FindKill() {
398  if (!is_setup) Setup(); // The first time we run out of space and need to kill, setup structure!
399 
400  emp_assert(distance.size() > 0); // After setup, we should always have distances stored.
401 
402  const size_t min_id = emp::FindMinIndex(distance);
403  emp_assert(min_id >= 0 && min_id < world.GetSize(), min_id);
404  emp_assert(nearest_id[min_id] >= 0 && nearest_id[min_id] < world.GetSize(),
405  min_id, distance[min_id], nearest_id[min_id], distance.size());
406  if (world.CalcFitnessID(min_id) < world.CalcFitnessID(nearest_id[min_id])) return min_id;
407  else return nearest_id[min_id];
408  }
409 
411  size_t GetBirthPos(size_t world_size) {
412  // If there's room in the world for one more, get the next empty position.
413  if (world.GetSize() < world_size) { return world.GetSize(); }
414  // Otherwise, determine whom to kill return their position to be used.
415  return FindKill();
416  }
417 
419  void Update(size_t pos) {
421  bool update_chart = false;
422  emp::vector<double> cur_vals = traits.EvalValues(world.GetOrg(pos));
423  for (size_t i = 0; i < cur_vals.size(); i++) {
424  if (cur_vals[i] <= min_vals[i]) {
425  min_vals[i] = cur_vals[i] - bin_width[i]/2.0;
426  update_chart = true;
427  }
428  if (cur_vals[i] >= max_vals[i]) {
429  max_vals[i] = cur_vals[i] + bin_width[i]/2.0;
430  update_chart = true;
431  }
432  }
433 
434  // Until min-dist tracking structure is setup, don't worry about maintaining.
435  if (!is_setup) return;
436  emp_assert(pos < world.GetSize());
437 
439  bin_ids[org_bins[pos]].erase(pos);
440 
442  if (update_chart == true) {
443  ResetBins();
444  org_bins[pos] = CalcBin(pos);
445  bin_ids[org_bins[pos]].insert(pos);
446 
447  // Rescaled bins might skew distances. Refresh everyone!
448  for (size_t id = 0; id < world.GetSize(); id++) {
449  Refresh(id);
450  }
451  emp_assert(org_bins[pos] != (size_t) -1);
452  }
453 
455  else {
456  org_bins[pos] = CalcBin(pos);
457  bin_ids[org_bins[pos]].insert(pos);
458  for (size_t id = 0; id < world.GetSize(); id++) {
459  if (nearest_id[id] == pos) Refresh(id);
460  }
461  Refresh(pos);
462  emp_assert(org_bins[pos] != (size_t) -1);
463  }
464 
465  emp_assert(OK());
466  }
467 
469  bool OK() {
470  // These tests only matter BEFORE Setup() is run.
471  emp_assert(is_setup || nearest_id.size() == 0);
472  emp_assert(is_setup || distance.size() == 0);
473 
474  // Tests for AFTER Setup() is run.
475 
476  if (is_setup) {
477  const size_t num_orgs = world.GetSize();
478  emp_assert(nearest_id.size() == num_orgs);
479  emp_assert(distance.size() == num_orgs);
480  for (size_t i = 0; i < num_orgs; i++) {
481  emp_assert(org_bins[i] < num_total_bins, i, org_bins[i], num_total_bins,
482  world.GetNumOrgs());
483  }
484  size_t org_count = 0;
485  for (size_t i = 0; i < num_total_bins; i++) {
486  org_count += bin_ids[i].size();
487  for (size_t org_id : bin_ids[i]) {
488  (void) org_id;
489  emp_assert(org_bins[org_id] == i);
490  }
491  }
492  emp_assert(org_count == num_orgs, org_count, num_orgs, world.GetNumOrgs());
493  }
494 
495  return true;
496  }
497  };
498 
500  template <typename ORG>
501  void SetDiverseElites(World<ORG> & world, TraitSet<ORG> traits, size_t world_size) {
502  world.MarkSynchronous(false);
503  world.MarkSpaceStructured(false).MarkPhenoStructured(true);
504 
505  // Build a pointer to the current information (and make sure it's deleted later)
506  Ptr<World_MinDistInfo<ORG>> info_ptr = NewPtr<World_MinDistInfo<ORG>>(world, traits);
507  world.OnWorldDestruct([info_ptr]() mutable { info_ptr.Delete(); });
508 
509  // Make sure to update info whenever a new org is placed into the population.
510  world.OnPlacement( [info_ptr](size_t pos) mutable { info_ptr->Update(pos); } );
511 
512  // -- Setup functions --
513  // Inject into the appropriate positon based on phenotype. Note that an inject will fail
514  // if a more fit organism is already in place; you must run clear first if you want to
515  // ensure placement.
516  world.SetAddInjectFun( [&world, traits, world_size, info_ptr](Ptr<ORG> new_org) {
517  size_t pos = info_ptr->GetBirthPos(world_size);
518  return WorldPosition(pos);
519  });
520 
521  // Diverse Elites does not have a concept of neighbors.
522  // @CAO Or should we return closest individual, which we already save?
523  world.SetGetNeighborFun( [](WorldPosition pos) { emp_assert(false); return pos; });
524 
525  // Find the two closest organisms and kill the lower fit one. (Killing sparsely...)
526  // Must unsetup population for next birth to work.
527  world.SetKillOrgFun( [&world, info_ptr](){
528  const size_t last_id = world.GetSize() - 1;
529  world.Swap(info_ptr->FindKill(), last_id);
530  info_ptr->is_setup = false;
531  world.RemoveOrgAt(last_id);
532  world.Resize(last_id);
533  return last_id;
534  });
535 
536  // Birth is effectively the same as inject.
537  world.SetAddBirthFun( [&world, traits, world_size, info_ptr](Ptr<ORG> new_org, WorldPosition parent_pos) {
538  (void) parent_pos;
539  size_t pos = info_ptr->GetBirthPos(world_size);
540  return WorldPosition(pos);
541  });
542 
543  world.SetAttribute("SynchronousGen", "False");
544  world.SetAttribute("PopStruct", "DiverseElites");
545  world.SetSynchronousSystematics(false);
546  }
547 
549  template <typename ORG>
550  void SetDiverseElites(World<ORG> & world, size_t world_size) {
551  SetDiverseElites(world, world.GetPhenotypes(), world_size);
552  }
553 }
554 
555 #endif
void Clear()
Definition: World_structure.h:389
iterator insert(ARGS &&...args)
Definition: vector.h:201
Definition: array.h:42
T & operator()(WorldPosition pos)
Definition: World_structure.h:80
bool OK()
A debug function to make sure the internal state is all valid.
Definition: World_structure.h:469
Definition: World_structure.h:29
WorldPosition & SetIndex(size_t _id)
Definition: World_structure.h:52
const emp::TraitSet< ORG > & GetPhenotypes() const
What phenotypic traits is the population tracking?
Definition: World.h:263
double CalcFitnessOrg(ORG &org)
Use the configured fitness function on the specified organism.
Definition: World.h:1181
bool is_setup
Have we initialized the internal data stucture?
Definition: World_structure.h:274
void Delete()
Definition: Ptr.h:737
emp::vector< double > EvalValues(target_t &target) const
Definition: Trait.h:160
void ResetBins()
Reset all of the bins in the multidimensional grid for nearest-neighbor analysis. ...
Definition: World_structure.h:356
Random & GetRandom()
Return a reference to the random number generator currently being used by world.
Definition: World.h:770
void Update(size_t pos)
Assume a position has changed; refresh it AND everything that had it as a closest connection...
Definition: World_structure.h:419
World< ORG > & world
World object being tracked.
Definition: World_structure.h:268
size_t num_trait_bins
How many bins should we use for each trait?
Definition: World_structure.h:275
void SetKillOrgFun(const fun_kill_org_t &_fun)
Definition: World.h:522
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
emp::vector< size_t > org_bins
Which bin is each org currently in?
Definition: World_structure.h:278
uint32_t GetIndex() const
Definition: World_structure.h:44
Definition: BitVector.h:785
emp::vector< size_t > nearest_id
For each individual, whom are they closest to?
Definition: World_structure.h:265
TraitSet< ORG > traits
Traits we are tryng to spread.
Definition: World_structure.h:269
emp::vector< double > distance
And what is their distance?
Definition: World_structure.h:266
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 SetAddInjectFun(const fun_find_inject_pos_t &_fun)
Definition: World.h:513
this_t & MarkSpaceStructured(bool in=true)
Definition: World.h:300
Setup a World with a population of organisms that can evolve or deal with ecological effects...
Definition: World.h:94
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 SetMapElites(World< ORG > &world, TraitSet< ORG > traits, const emp::vector< size_t > &trait_counts)
Definition: World_structure.h:164
WorldPosition & MarkInvalid()
Definition: World_structure.h:53
void Resize(size_t new_size)
Definition: World.h:723
WorldPosition & SetPopID(size_t _id)
Definition: World_structure.h:51
WorldPosition & SetActive(bool _active=true)
Definition: World_structure.h:50
bool IsActive() const
Definition: World_structure.h:47
size_t FindKill()
Definition: World_structure.h:397
Build a class to track distances between organisms.
Definition: World_structure.h:262
size_t GetSize() const
How many organisms can fit in the world?
Definition: World.h:245
WorldPosition(size_t _id, size_t _pop_id=0)
Definition: World_structure.h:38
void Refresh(size_t refresh_id, size_t start_id=0)
Definition: World_structure.h:313
World_MinDistInfo(World< ORG > &in_world, const TraitSet< ORG > &in_traits)
Definition: World_structure.h:280
emp::vector< double > min_vals
Smallest value found for each trait.
Definition: World_structure.h:270
void SetAddBirthFun(const fun_find_birth_pos_t &_fun)
Definition: World.h:518
void SetDiverseElites(World< ORG > &world, TraitSet< ORG > traits, size_t world_size)
This first version will setup a Diverse-Elites world and specify traits to use.
Definition: World_structure.h:501
size_t CalcBin(size_t id)
Calculate which bin an organism should be in.
Definition: World_structure.h:340
size_t GetSize() const
Definition: Trait.h:132
WorldPosition()
Definition: World_structure.h:37
A vector that can be indexed with a WorldPosition.
Definition: World_structure.h:58
emp::vector< double > max_vals
Largest value found for each trait.
Definition: World_structure.h:271
void SetAttribute(const std::string &name, T &&val)
Definition: World.h:636
size_t EvalBin(target_t &target, emp::vector< size_t > bin_counts) const
Definition: Trait.h:167
bool IsValid(WorldPosition pos) const
Test if a position is currently valid.
Definition: World_structure.h:63
static constexpr type_if< T, std::is_integral > Pow(T base, T p)
A fast (O(log p)) integral-power command.
Definition: math.h:150
void resize(size_t new_size)
Definition: vector.h:161
ORG & GetOrg(size_t id)
Definition: World.h:316
static constexpr size_t invalid_id
Definition: World_structure.h:35
double CalcDist(size_t id1, size_t id2)
Definition: World_structure.h:288
If we are in emscripten, make sure to include the header.
Definition: array.h:37
size_t GetRandomCellID()
Get the position a cell, at random.
Definition: World.h:779
Definition: Ptr.h:711
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
emp::vector< double > bin_width
Largest value found for each trait.
Definition: World_structure.h:272
void SetPools(World< ORG > &world, size_t num_pools, size_t pool_size, bool synchronous_gen=false)
Definition: World_structure.h:96
size_t GetBirthPos(size_t world_size)
Return an empty world position. If none are available, return the position of an org to be killed...
Definition: World_structure.h:411
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 RemoveOrgAt(WorldPosition pos)
Definition: World.h:887
size_t FindMinIndex(const T &v)
Find the index with the minimal value (picks first in cases of a tie).
Definition: vector_utils.h:63
bool IsValid() const
Definition: World_structure.h:48
const T & operator()(WorldPosition pos) const
Definition: World_structure.h:85
emp::vector< std::set< size_t > > bin_ids
Which org ids fall into each bin?
Definition: World_structure.h:277
emp::vector< double > CalcOffsets(target_t &target1, target_t &target2) const
Definition: Trait.h:177
void Refresh_AgainstBin(size_t refresh_id, size_t target_bin)
Definition: World_structure.h:296
void Setup()
Definition: World_structure.h:370
constexpr size_t GetSize(T(&)[N])
Determine the size of a built-in array.
Definition: functions.h:81
size_t num_total_bins
How many bins are there overall?
Definition: World_structure.h:276
bool IsOccupied(WorldPosition pos) const
Does the specified cell ID have an organism in it?
Definition: World.h:277
this_t & MarkSynchronous(bool in=true)
Definition: World.h:296