Empirical
Systematics.h
Go to the documentation of this file.
1 
22 #ifndef EMP_EVO_SYSTEMATICS_H
23 #define EMP_EVO_SYSTEMATICS_H
24 
25 #include <ostream>
26 #include <set>
27 #include <unordered_set>
28 #include <map>
29 
30 #include "../base/Ptr.h"
31 #include "../control/Signal.h"
32 #include "../data/DataManager.h"
33 #include "../data/DataNode.h"
34 #include "../tools/info_theory.h"
35 #include "../tools/map_utils.h"
36 #include "../tools/set_utils.h"
37 #include "../tools/stats.h"
38 #include "../tools/string_utils.h"
39 
40 namespace emp {
41 
47 
48  namespace datastruct {
49  struct no_data {
50  using has_fitness_t = std::false_type;
51  using has_mutations_t = std::false_type;
52  using has_phen_t = std::false_type;
53  };
54 
55  template <typename PHEN_TYPE>
57  using phen_t = PHEN_TYPE;
60  using has_phen_t = std::true_type;
61  using has_mutations_t = std::true_type;
62  using has_fitness_t = std::true_type;
63  // using has_phenotype_t = true;
64 
65  std::unordered_map<std::string, int> mut_counts;
67  PHEN_TYPE phenotype;
68 
69  const PHEN_TYPE & GetPhenotype() const {
70  return phenotype;
71  }
72 
73  const double GetFitness() const {
74  return fitness.GetMean();
75  }
76 
77  void RecordMutation(std::unordered_map<std::string, int> muts) {
78  for (auto mut : muts) {
79  if (Has(mut_counts, mut.first)) {
80  mut_counts[mut.first] += mut.second;
81  } else {
82  mut_counts[mut.first] = mut.second;
83  }
84  }
85  }
86 
87  void RecordFitness(double fit) {
88  fitness.Add(fit);
89  }
90 
91  void RecordPhenotype(PHEN_TYPE phen) {
92  phenotype = phen;
93  }
94 
95  };
96  }
97 
104  template <typename ORG_INFO, typename DATA_STRUCT = emp::datastruct::no_data>
105  class Taxon {
106  protected:
108  using info_t = ORG_INFO;
109 
110  size_t id;
111  const info_t info;
113  size_t num_orgs;
114  size_t tot_orgs;
115  size_t num_offspring;
117  size_t depth;
119 
120  DATA_STRUCT data;
121 
122  public:
123  using data_t = DATA_STRUCT;
124 
125  Taxon(size_t _id, const info_t & _info, Ptr<this_t> _parent=nullptr)
126  : id (_id), info(_info), parent(_parent)
127  , num_orgs(0), tot_orgs(0), num_offspring(0), total_offspring(0)
128  , depth(parent ? (parent->depth+1) : 0) { ; }
129  Taxon(const Taxon &) = delete;
130  Taxon(Taxon &&) = default;
131  Taxon & operator=(const Taxon &) = delete;
132  Taxon & operator=(Taxon &&) = default;
133 
135  size_t GetID() const { return id; }
136 
138  const info_t & GetInfo() const { return info; }
139 
141  Ptr<this_t> GetParent() const { return parent; }
142 
144  size_t GetNumOrgs() const { return num_orgs; }
145 
147  size_t GetTotOrgs() const { return tot_orgs; }
148 
150  size_t GetNumOff() const { return num_offspring; }
151 
153  size_t GetDepth() const { return depth; }
154 
155  data_t & GetData() {return data;}
156  const data_t & GetData() const {return data;}
157 
158  double GetOriginationTime() const {return origination_time;}
159  void SetOriginationTime(double time) {origination_time = time;}
160 
162  void AddOrg() { ++num_orgs; ++tot_orgs; }
163 
165  void AddOffspring() { ++num_offspring; AddTotalOffspring();}
166 
168  // Should this be protected or private or something?
170  ++total_offspring;
171  if (parent) { // Keep going until we hit root
172  parent->AddTotalOffspring();
173  }
174  }
175 
178  int GetTotalOffspring(){ return total_offspring; }
179 
182  bool RemoveOrg() {
183  emp_assert(num_orgs > 0, num_orgs);
184  --num_orgs;
185 
186  // If we are out of BOTH organisms and offspring, this Taxon should deactivate.
187  return num_orgs;
188  }
189 
192  emp_assert(num_offspring > 0);
193  --num_offspring;
194 
195  // If we are out of BOTH offspring and organisms, this Taxon should deactivate.
196  return num_orgs || num_offspring;
197  }
198 
202  --total_offspring;
203  if (parent) { // Keep going until we hit root
204  parent->RemoveTotalOffspring();
205  }
206  }
207  };
208 
209 
212 
213  template <typename ORG>
215  protected:
219  bool archive;
222 
223  // Stats about active taxa... (totals are across orgs, not taxa)
224  size_t org_count;
225  size_t total_depth;
226  size_t num_roots;
227 
228  size_t next_id;
229  size_t curr_update;
230 
232 
233  public:
234  SystematicsBase(bool _active=true, bool _anc=true, bool _all=false, bool _pos=true)
235  : store_active(_active), store_ancestors(_anc), store_outside(_all)
236  , archive(store_ancestors || store_outside), store_position(_pos), track_synchronous(false)
237  , org_count(0), total_depth(0), num_roots(0), next_id(0), curr_update(0) { ; }
238 
239  virtual ~SystematicsBase(){;}
240 
243 
245  bool GetTrackSynchronous() const {return track_synchronous; }
246 
248  bool GetStoreActive() const { return store_active; }
249 
251  bool GetStoreAncestors() const { return store_ancestors; }
252 
254  bool GetStoreOutside() const { return store_outside; }
255 
257  bool GetArchive() const { return archive; }
258 
260  bool GetStorePosition() const { return store_position; }
261 
263  size_t GetTotalOrgs() const { return org_count; }
264 
266  size_t GetNumRoots() const { return num_roots; }
267 
269  double GetAveDepth() const { return ((double) total_depth) / (double) org_count; }
270 
272  void SetTrackSynchronous(bool new_val) {track_synchronous = new_val; }
273 
275  void SetStoreActive(bool new_val) { store_active = new_val; }
276 
278  void SetStoreAncestors(bool new_val) { store_ancestors = new_val; }
279 
281  void SetStoreOutside(bool new_val) { store_outside = new_val; }
282 
284  void SetArchive(bool new_val) { archive = new_val; }
285 
287  void SetStorePosition(bool new_val) { store_position = new_val; }
288 
289  // Returns a reference so that capturing it in a lambda to call on update
290  // is less confusing. It's possible we should change it to be consistent
291  // with GetFitnessDataNode, though.
292  data_ptr_t AddDataNode(const std::string & name) {
293  emp_assert(!data_nodes.HasNode(name));
294  return &(data_nodes.New(name));
295  }
296 
297  data_ptr_t AddDataNode(std::function<emp::vector<double>()> pull_set_fun, const std::string & name) {
298  emp_assert(!data_nodes.HasNode(name));
299  auto node = AddDataNode(name);
300  node->AddPullSet(pull_set_fun);
301  return node;
302  }
303 
304  data_ptr_t AddDataNode(std::function<double()> pull_fun, const std::string & name) {
305  emp_assert(!data_nodes.HasNode(name));
306  auto node = AddDataNode(name);
307  node->AddPull(pull_fun);
308  return node;
309  }
310 
311 
312  data_ptr_t GetDataNode(const std::string & name) {
313  return &(data_nodes.Get(name));
314  }
315 
316  virtual data_ptr_t AddEvolutionaryDistinctivenessDataNode(const std::string & name = "evolutionary_distinctiveness") = 0;
317  virtual data_ptr_t AddPairwiseDistanceDataNode(const std::string & name = "pairwise_distance") = 0;
318  virtual data_ptr_t AddPhylogeneticDiversityDataNode(const std::string & name = "phylogenetic_diversity") = 0;
319  virtual data_ptr_t AddDeleteriousStepDataNode(const std::string & name = "deleterious_steps") = 0;
320  virtual data_ptr_t AddVolatilityDataNode(const std::string & name = "volatility") = 0;
321  virtual data_ptr_t AddUniqueTaxaDataNode(const std::string & name = "unique_taxa") = 0;
322  virtual data_ptr_t AddMutationCountDataNode(const std::string & name = "mutation_count", const std::string & mutation = "substitution") = 0;
323 
324  virtual size_t GetNumActive() const = 0;
325  virtual size_t GetNumAncestors() const = 0;
326  virtual size_t GetNumOutside() const = 0;
327  virtual size_t GetTreeSize() const = 0;
328  virtual size_t GetNumTaxa() const = 0;
329  virtual int GetPhylogeneticDiversity() const = 0;
330  virtual double GetMeanPairwiseDistance(bool branch_only) const = 0;
331  virtual double GetSumPairwiseDistance(bool branch_only) const = 0;
332  virtual double GetVariancePairwiseDistance(bool branch_only) const = 0;
333  virtual emp::vector<double> GetPairwiseDistances(bool branch_only) const = 0;
334  virtual int GetMRCADepth() const = 0;
335  virtual void AddOrg(ORG && org, int pos, int update, bool next) = 0;
336  virtual void AddOrg(ORG & org, int pos, int update, bool next) = 0;
337  virtual bool RemoveOrg(int pos) = 0;
338  virtual bool RemoveNextOrg(int pos) = 0;
339  virtual void PrintStatus(std::ostream & os) const = 0;
340  virtual double CalcDiversity() const = 0;
341  virtual void Update() = 0;
342  virtual void SetNextParent(int pos) = 0;
343 
344  };
345 
354  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT = emp::datastruct::no_data>
355  class Systematics : public SystematicsBase<ORG> {
356  private:
359  using hash_t = typename Ptr<taxon_t>::hash_t;
360  using fun_calc_info_t = std::function<ORG_INFO(ORG &)>;
361 
362  fun_calc_info_t calc_info_fun;
363  Ptr<taxon_t> next_parent;
364 
365  using parent_t::store_active;
366  using parent_t::store_ancestors;
367  using parent_t::store_outside;
368  using parent_t::archive;
369  using parent_t::store_position;
370  using parent_t::track_synchronous;
371  using parent_t::org_count;
372  using parent_t::total_depth;
373  using parent_t::num_roots;
374  using parent_t::next_id;
375  using parent_t::curr_update;
376 
377  using typename parent_t::data_ptr_t;
378  using parent_t::GetNumActive;
379  using parent_t::GetNumAncestors;
380  using parent_t::GetNumOutside;
381  using parent_t::GetTreeSize;
382  using parent_t::GetNumTaxa;
383  // using parent_t::OnNew;
384  // using parent_t::OnPrune;
385  using parent_t::GetPhylogeneticDiversity;
386  // using parent_t::GetTaxonDistinctiveness;
387  // using parent_t::GetEvolutionaryDistinctiveness;
388  using parent_t::GetMeanPairwiseDistance;
389  using parent_t::GetSumPairwiseDistance;
390  using parent_t::GetVariancePairwiseDistance;
391  using parent_t::GetPairwiseDistances;
392  // using parent_t::GetDistanceToRoot;
393  // using parent_t::GetBranchesToRoot;
394  // using parent_t::GetMRCA;
395  using parent_t::GetMRCADepth;
396  using parent_t::AddOrg;
397  using parent_t::RemoveOrg;
398  using parent_t::RemoveNextOrg;
399  // using parent_t::Parent;
400  using parent_t::PrintStatus;
401  // using parent_t::PrintLineage;
402  using parent_t::CalcDiversity;
403  using parent_t::Update;
404  using parent_t::SetNextParent;
405 
406  using parent_t::GetDataNode;
407  using parent_t::AddDataNode;
408  using parent_t::AddEvolutionaryDistinctivenessDataNode;
409  using parent_t::AddPairwiseDistanceDataNode;
410  using parent_t::AddPhylogeneticDiversityDataNode;
411  using parent_t::AddDeleteriousStepDataNode;
412  using parent_t::AddVolatilityDataNode;
413  using parent_t::AddUniqueTaxaDataNode;
414  using parent_t::AddMutationCountDataNode;
415 
416  std::unordered_set< Ptr<taxon_t>, hash_t > active_taxa;
417  std::unordered_set< Ptr<taxon_t>, hash_t > ancestor_taxa;
418  std::unordered_set< Ptr<taxon_t>, hash_t > outside_taxa;
419 
420  emp::vector<Ptr<taxon_t> > taxon_locations;
421  emp::vector<Ptr<taxon_t> > next_taxon_locations;
422 
423  Signal<void(Ptr<taxon_t>)> on_new_sig;
424  Signal<void(Ptr<taxon_t>)> on_prune_sig;
425 
426  mutable Ptr<taxon_t> mrca;
427 
429  void Prune(Ptr<taxon_t> taxon);
430 
432  void RemoveOffspring(Ptr<taxon_t> taxon);
433 
435  void MarkExtinct(Ptr<taxon_t> taxon);
436 
437 
438  public:
439 
447  Systematics(fun_calc_info_t calc_taxon, bool _active=true, bool _anc=true, bool _all=false, bool _pos=true)
448  : parent_t(_active, _anc, _all, _pos)
449  , calc_info_fun(calc_taxon)
450  , active_taxa(), ancestor_taxa(), outside_taxa()
451  , mrca(nullptr) { ; }
452  Systematics(const Systematics &) = delete;
453  Systematics(Systematics &&) = default;
455  for (auto x : active_taxa) x.Delete();
456  for (auto x : ancestor_taxa) x.Delete();
457  for (auto x : outside_taxa) x.Delete();
458  active_taxa.clear();
459  ancestor_taxa.clear();
460  outside_taxa.clear();
461  }
462 
463 
464  void Update() {
465  ++curr_update;
466  std::swap(taxon_locations, next_taxon_locations);
467  next_taxon_locations.resize(0);
468  }
469 
470  void SetCalcInfoFun(fun_calc_info_t f) {calc_info_fun = f;}
471 
472  // Currently using raw pointers because of a weird bug in emp::Ptr. Should switch when fixed.
473  std::unordered_set< Ptr<taxon_t>, hash_t > * GetActivePtr() { return &active_taxa; }
474  const std::unordered_set< Ptr<taxon_t>, hash_t > & GetActive() const { return active_taxa; }
475  const std::unordered_set< Ptr<taxon_t>, hash_t > & GetAncestors() const { return ancestor_taxa; }
476 
478  size_t GetNumActive() const { return active_taxa.size(); }
479 
481  size_t GetNumAncestors() const { return ancestor_taxa.size(); }
482 
484  size_t GetNumOutside() const { return outside_taxa.size(); }
485 
487  size_t GetTreeSize() const { return GetNumActive() + GetNumAncestors(); }
488 
490  size_t GetNumTaxa() const { return GetTreeSize() + GetNumOutside(); }
491 
492  void SetNextParent(int pos) {
493  emp_assert(pos < (int)taxon_locations.size(), "Invalid parent", pos, taxon_locations.size());
494  if (pos == -1) {
495  next_parent = nullptr;
496  } else {
497  emp_assert(pos >= 0, "Invalid parent", pos);
498  next_parent = taxon_locations[pos];
499  }
500  }
501 
503  next_parent = p;
504  }
505 
506  SignalKey OnNew(std::function<void(Ptr<taxon_t>)> & fun) { return on_new_sig.AddAction(fun); }
507 
511  SignalKey OnPrune(std::function<void(Ptr<taxon_t>)> & fun) { return on_prune_sig.AddAction(fun); }
512 
513  virtual data_ptr_t
514  AddEvolutionaryDistinctivenessDataNode(const std::string & name = "evolutionary_distinctiveness") {
515  auto node = AddDataNode(name);
516  node->AddPullSet([this](){
517  emp::vector<double> result;
518  for (auto tax : active_taxa) {
519  result.push_back(GetEvolutionaryDistinctiveness(tax, curr_update));
520  }
521  return result;
522  });
523 
524  return node;
525  }
526 
527  virtual data_ptr_t AddPairwiseDistanceDataNode(const std::string & name = "pairwise_distances") {
528  auto node = AddDataNode(name);
529  node->AddPullSet([this](){
530  return GetPairwiseDistances();
531  });
532  return node;
533  }
534 
535  virtual data_ptr_t AddPhylogeneticDiversityDataNode(const std::string & name = "phylogenetic_diversity") {
536  auto node = AddDataNode(name);
537  node->AddPull([this](){
538  return GetPhylogeneticDiversity();
539  });
540  return node;
541  }
542 
543 
544  virtual data_ptr_t
545  AddDeleteriousStepDataNode(const std::string & name = "deleterious_steps") {
546  return AddDeleteriousStepDataNodeImpl(1, name);
547  }
548 
549  data_ptr_t AddDeleteriousStepDataNodeImpl(bool decoy, const std::string & name = "deleterious_steps") {
550  emp_assert(false, "Calculating deleterious steps requires suitable DATA_STRUCT");
551  return AddDataNode(name);
552  }
553 
554  template <typename T=int>
555  data_ptr_t
556  AddDeleteriousStepDataNodeImpl(typename std::enable_if<DATA_STRUCT::has_fitness_t::value, T>::type decoy, const std::string & name = "deleterious_steps") {
557  auto node = AddDataNode(name);
558  node->AddPullSet([this](){
559  emp::vector<double> result;
560  for (auto tax : active_taxa) {
561  result.push_back(CountDeleteriousSteps(tax));
562  }
563  return result;
564  });
565 
566  return node;
567  }
568 
569  virtual data_ptr_t
570  AddVolatilityDataNode(const std::string & name = "volatility") {
571  return AddVolatilityDataNodeImpl(1, name);
572  }
573 
574  data_ptr_t AddVolatilityDataNodeImpl(bool decoy, const std::string & name = "volatility") {
575  emp_assert(false, "Calculating taxon volatility requires suitable DATA_STRUCT");
576  return AddDataNode(name);
577  }
578 
579  template <typename T=int>
580  data_ptr_t
581  AddVolatilityDataNodeImpl(typename std::enable_if<DATA_STRUCT::has_phen_t::value, T>::type decoy, const std::string & name = "volatility") {
582  auto node = AddDataNode(name);
583  node->AddPullSet([this](){
584  emp::vector<double> result;
585  for (auto tax : active_taxa) {
586  result.push_back(CountPhenotypeChanges(tax));
587  }
588  return result;
589  });
590 
591  return node;
592  }
593 
594  virtual data_ptr_t
595  AddUniqueTaxaDataNode(const std::string & name = "unique_taxa") {
596  return AddUniqueTaxaDataNodeImpl(1, name);
597  }
598 
599  data_ptr_t AddUniqueTaxaDataNodeImpl(bool decoy, const std::string & name = "unique_taxa") {
600  emp_assert(false, "Calculating uniqe taxa requires suitable DATA_STRUCT");
601  return AddDataNode(name);
602  }
603 
604  template <typename T=int>
605  data_ptr_t
606  AddUniqueTaxaDataNodeImpl(typename std::enable_if<DATA_STRUCT::has_phen_t::value, T>::type decoy, const std::string & name = "unique_taxa") {
607  auto node = AddDataNode(name);
608  node->AddPullSet([this](){
609  emp::vector<double> result;
610  for (auto tax : active_taxa) {
611  result.push_back(CountUniquePhenotypes(tax));
612  }
613  return result;
614  });
615 
616  return node;
617  }
618 
619  virtual data_ptr_t
620  AddMutationCountDataNode(const std::string & name = "mutation_count", const std::string & mutation = "substitution") {
621  return AddMutationCountDataNodeImpl(1, name, mutation);
622  }
623 
624  data_ptr_t AddMutationCountDataNodeImpl(bool decoy, const std::string & name = "mutation_count", const std::string & mutation = "substitution") {
625  emp_assert(false, "Calculating mutation count requires suitable DATA_STRUCT");
626  return AddDataNode(name);
627  }
628 
629  template <typename T=int>
630  data_ptr_t
631  AddMutationCountDataNodeImpl(typename std::enable_if<DATA_STRUCT::has_mutations_t::value, T>::type decoy, const std::string & name = "mutation_count", const std::string & mutation = "substitution") {
632  auto node = AddDataNode(name);
633  node->AddPullSet([this,mutation](){
634  emp::vector<double> result;
635  for (auto tax : active_taxa) {
636  result.push_back(CountMuts(tax, mutation));
637  }
638  return result;
639  });
640 
641  return node;
642  }
643 
645  emp_assert(id < (int) taxon_locations.size(), "Invalid taxon location", id, taxon_locations.size());
646  emp_assert(taxon_locations[id], "No taxon at specified location");
647  return taxon_locations[id];
648  }
650  emp_assert(id < (int)next_taxon_locations.size(), "Invalid taxon location");
651  emp_assert(next_taxon_locations[id], "No taxon at specified location");
652 
653  return next_taxon_locations[id];
654  }
655 
669  // As shown on page 5 of Faith 1992, when all branch lengths are equal the phylogenetic
670  // diversity is the number of internal nodes plus the number of extant taxa - 1.
671  return ancestor_taxa.size() + active_taxa.size() - 1;
672  }
673 
678  double GetTaxonDistinctiveness(Ptr<taxon_t> tax) const {return 1.0/GetDistanceToRoot(tax);}
679 
691  double GetEvolutionaryDistinctiveness(Ptr<taxon_t> tax, double time) const {
692 
693  double depth = 0; // Length (in time units) of section we're currently exploring
694  double total = 0; // Count up scores for each section of tree
695  double divisor = tax->GetTotalOffspring() + 1; // Number of extant taxa this will split into (1 for current taxa, plus its offspring)
696 
697  // We're stopping when we hit MRCA, so we need to make sure it's been calculated.
698  GetMRCA();
699  if (tax == mrca) {
700  return 0;
701  }
702 
703  // std::cout << "Initializing divisor to " << divisor << " Offspinrg: " << tax->GetTotalOffspring() << std::endl;
704  // std::cout << "MRCA ID: " << mrca->GetID() << " Tax ID: " << tax->GetID() << " time: " << time << " Orig: " << tax->GetOriginationTime() << std::endl;
705 
706  Ptr<taxon_t> test_taxon = tax->GetParent();
707 
708  emp_assert(time != -1 && "Invalid time - are you passing time to rg?", time);
709  emp_assert(time >= tax->GetOriginationTime()
710  && "GetEvolutionaryDistinctiveness recieved a time that is earlier than the taxon's origination time.");
711 
712  while (test_taxon) {
713 
714  emp_assert(test_taxon->GetOriginationTime() != -1 &&
715  "Invalid time - are you passing time to rg?");
716 
717  depth += time - test_taxon->GetOriginationTime();
718  // std::cout << "Tax: " << test_taxon->GetID() << " depth: " << depth << " time: " << time << " Orig: " << test_taxon->GetOriginationTime() << " divisor: " << divisor << std::endl;
719  time = test_taxon->GetOriginationTime();
720  if (test_taxon == mrca || !test_taxon) {
721  // Stop when everything has converged or when we hit the root.
722  // std::cout << (int)(test_taxon == mrca) << " depth: " << depth << " divisor: " << divisor << std::endl;
723  total += depth/divisor;
724  return total;
725  } else if (test_taxon->GetNumOrgs() > 0) {
726  // If this taxon is still alive we need to update the divisor
727  // std::cout << "Alive point" << " depth: " << depth << " divisor: " << divisor << std::endl;
728  total += depth/divisor;
729  depth = 0;
730  divisor = test_taxon->GetTotalOffspring() + 1;
731  } else if (test_taxon->GetNumOff() > 1) {
732  // This is a branch point. We need to add the things on the other branch to the divisor..
733  // std::cout << "Branch point" << " depth: " << depth << " divisor: " << divisor << std::endl;
734  total += depth/divisor;
735  depth = 0;
736  divisor = test_taxon->GetTotalOffspring();
737  }
738 
739  test_taxon = test_taxon->GetParent();
740  }
741 
742  return -1;
743  }
744 
757  double GetMeanPairwiseDistance(bool branch_only=false) const {
758  emp::vector<double> dists = GetPairwiseDistances(branch_only);
759  return (double)Sum(dists)/dists.size();
760  }
761 
772  double GetSumPairwiseDistance(bool branch_only=false) const {
773  emp::vector<double> v = GetPairwiseDistances(branch_only);
774  return Sum(v);
775  }
776 
787  double GetVariancePairwiseDistance(bool branch_only=false) const {
788  emp::vector<double> v = GetPairwiseDistances(branch_only);
789  return Variance(v);
790  }
791 
801  emp::vector<double> GetPairwiseDistances(bool branch_only=false) const {
802  // The overarching approach here is to start with a bunch of pointers to all
803  // extant organisms (since that will include all leaves). Then we trace back up
804  // the tree, keeping track of distances. When things meet up, we calculate
805  // distances between the nodes on the sides that just met up.
806 
807  emp::vector<double> dists;
808 
809  std::map< Ptr<taxon_t>, emp::vector<emp::vector<int>> > curr_pointers;
810  std::map< Ptr<taxon_t>, emp::vector<emp::vector<int>> > next_pointers;
811 
812 
813  for (Ptr<taxon_t> tax : active_taxa) {
814  curr_pointers[tax] = emp::vector<emp::vector<int>>({{0}});
815  }
816 
817  // std::cout << "Starting curr_pointers size: " << curr_pointers.size() << std::endl;
818 
819  while (curr_pointers.size() > 0) {
820  for (auto & tax : curr_pointers) {
821  bool alive = tax.first->GetNumOrgs() > 0;
822  // std::cout << tax.first << " has " << to_string(tax.second) << "and is waiting for " << tax.first->GetNumOff() + int(alive) << std::endl;
823  if ( tax.second.size() < tax.first->GetNumOff() + int(alive)) {
824  if (Has(next_pointers, tax.first)) {
825  // In case an earlier iteration added this node to next_pointers
826  for (auto vec : tax.second) {
827  next_pointers[tax.first].push_back(vec);
828  }
829  } else {
830  next_pointers[tax.first] = curr_pointers[tax.first];
831  }
832  continue;
833  }
834  emp_assert(tax.first->GetNumOff() + int(alive) == tax.second.size(), tax.first->GetNumOff(), alive, to_string(tax.second), tax.second.size());
835 
836  // Okay, things should have just met up. Let's compute the distances
837  // between everything that just met.
838 
839  if (tax.second.size() > 1) {
840 
841  for (size_t i = 0; i < tax.second.size(); i++ ) {
842  for (size_t j = i+1; j < tax.second.size(); j++) {
843  for (int disti : tax.second[i]) {
844  for (int distj : tax.second[j]) {
845  // std::cout << "Adding " << disti << " and " << distj << std::endl;
846  dists.push_back(disti+distj);
847  }
848  }
849  }
850  }
851  }
852  // std::cout << "dists " << to_string(dists) << std::endl;
853  // Increment distances and stick them in new vector
854  emp::vector<int> new_dist_vec;
855  for (auto & vec : tax.second) {
856  for (int el : vec) {
857  new_dist_vec.push_back(el+1);
858  }
859  }
860 
861  // std::cout << "new_dist_vec " << to_string(new_dist_vec) << std::endl;
862 
863  next_pointers.erase(tax.first);
864 
865  Ptr<taxon_t> test_taxon = tax.first->GetParent();
866  while (test_taxon && test_taxon->GetNumOff() == 1 && test_taxon->GetNumOrgs() < 0) {
867  if (!branch_only) {
868  for (size_t i = 0; i < new_dist_vec.size(); i++){
869  new_dist_vec[i]++;
870  }
871  }
872  test_taxon = test_taxon->GetParent();
873  }
874 
875  if (!test_taxon) {
876  continue;
877  } else if (!Has(next_pointers, test_taxon)) {
878  next_pointers[test_taxon] = emp::vector<emp::vector<int> >({new_dist_vec});
879  } else {
880  next_pointers[test_taxon].push_back(new_dist_vec);
881  }
882  }
883  curr_pointers = next_pointers;
884  next_pointers.clear();
885  // std::cout << curr_pointers.size() << std::endl;
886  }
887 
888  if (dists.size() != (active_taxa.size()*(active_taxa.size()-1))/2) {
889  // The tree is not connected
890  // It's possible we should do something different here...
891  return dists;
892  }
893 
894  // std::cout << "Total: " << total << "Dists: " << dists.size() << std::endl;
895 
896  return dists;
897 
898  }
899 
900 
905  // Now, trace the line of descent, updating the candidate as we go.
906  GetMRCA();
907 
908  int depth = 0;
909  Ptr<taxon_t> test_taxon = tax->GetParent();
910  while (test_taxon) {
911  depth++;
912  if (test_taxon == mrca || !test_taxon) {
913  return depth;
914  }
915  test_taxon = test_taxon->GetParent();
916  }
917  return depth;
918  }
919 
927  GetMRCA();
928 
929  int depth = 0;
930  Ptr<taxon_t> test_taxon = tax->GetParent();
931  while (test_taxon) {
932  if (test_taxon == mrca || !test_taxon) {
933  return depth;
934  } else if (test_taxon->GetNumOff() > 1) {
935  depth++;
936  }
937  test_taxon = test_taxon->GetParent();
938  }
939  return depth;
940  }
941 
942 
943 
945  Ptr<taxon_t> GetMRCA() const;
946 
948  int GetMRCADepth() const;
949 
954  void AddOrg(ORG && org, int pos, int update=-1, bool next=false);
955  Ptr<taxon_t> AddOrg(ORG && org, int pos, Ptr<taxon_t> parent=nullptr, int update=-1, bool next=false);
956  Ptr<taxon_t> AddOrg(ORG && org, Ptr<taxon_t> parent=nullptr, int update=-1, bool next=false);
957 
958  void AddOrg(ORG & org, int pos, int update=-1, bool next=false);
959  Ptr<taxon_t> AddOrg(ORG & org, int pos, Ptr<taxon_t> parent=nullptr, int update=-1, bool next=false);
960  Ptr<taxon_t> AddOrg(ORG & org, Ptr<taxon_t> parent=nullptr, int update=-1, bool next=false);
961 
962 
964  bool RemoveOrg(int pos);
965  bool RemoveOrg(Ptr<taxon_t> taxon);
966 
968  bool RemoveNextOrg(int pos);
969  bool RemoveNextOrg(Ptr<taxon_t> taxon);
970 
972  Ptr<taxon_t> Parent(Ptr<taxon_t> taxon) const;
973 
975  void PrintStatus(std::ostream & os=std::cout) const;
976 
978  void PrintLineage(Ptr<taxon_t> taxon, std::ostream & os=std::cout) const;
979 
981  double CalcDiversity() const;
982 
983  };
984 
985  // =============================================================
986  // === ===
987  // === Out-of-class member function definitions from above ===
988  // === ===
989  // =============================================================
990 
991  // Should be called wheneven a taxon has no organisms AND no descendants.
992  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
994  on_prune_sig.Trigger(taxon);
995  RemoveOffspring( taxon->GetParent() ); // Notify parent of the pruning.
996  if (store_ancestors) ancestor_taxa.erase(taxon); // Clear from ancestors set (if there)
997  if (store_outside) outside_taxa.insert(taxon); // Add to outside set (if tracked)
998  else taxon.Delete(); // ...or else get rid of it.
999  }
1000 
1001  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1003  if (!taxon) { num_roots--; return; } // Offspring was root; remove and return.
1004  bool still_active = taxon->RemoveOffspring(); // Taxon still active w/ 1 fewer offspring?
1005  if (!still_active) Prune(taxon); // If out of offspring, remove from tree.
1006 
1007  // If the taxon is still active AND the is the current mrca AND now has only one offspring,
1008  // clear the MRCA for lazy re-evaluation later.
1009  else if (taxon == mrca && taxon->GetNumOff() == 1) mrca = nullptr;
1010  }
1011 
1012  // Mark a taxon extinct if there are no more living members. There may be descendants.
1013  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1015  emp_assert(taxon);
1016  emp_assert(taxon->GetNumOrgs() == 0);
1017 
1018  if (taxon->GetParent()) {
1019  // Update extant descendant count for all ancestors
1020  taxon->GetParent()->RemoveTotalOffspring();
1021  }
1022 
1023  if (store_active) active_taxa.erase(taxon);
1024  if (!archive) { // If we don't archive taxa, delete them.
1025  taxon.Delete();
1026  return;
1027  }
1028 
1029  if (store_ancestors) ancestor_taxa.insert(taxon); // Move taxon to ancestors...
1030  if (taxon->GetNumOff() == 0) Prune(taxon); // ...and prune from there if needed.
1031  }
1032 
1033 
1034  // Request a pointer to the Most-Recent Common Ancestor for the population.
1035  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1037  if (!mrca && num_roots == 1) { // Determine if we need to calculate the MRCA.
1038  // First, find a candidate among the living taxa. Only taxa that have one offsrping
1039  // can be on the line-of-descent to the MRCA, so anything else is a good start point.
1040  // There must be at least one! Stop as soon as we find a candidate.
1041  Ptr<taxon_t> candidate(nullptr);
1042  for (auto x : active_taxa) {
1043  if (x->GetNumOff() != 1) { candidate = x; break; }
1044  }
1045 
1046  // Now, trace the line of descent, updating the candidate as we go.
1047  Ptr<taxon_t> test_taxon = candidate->GetParent();
1048  while (test_taxon) {
1049  emp_assert(test_taxon->GetNumOff() >= 1);
1050  if (test_taxon->GetNumOff() > 1) candidate = test_taxon;
1051  test_taxon = test_taxon->GetParent();
1052  }
1053  mrca = candidate;
1054  }
1055  return mrca;
1056  }
1057 
1058  // Request the depth of the Most-Recent Common Ancestor; return -1 for none.
1059  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1061  GetMRCA();
1062  if (mrca) return (int) mrca->GetDepth();
1063  return -1;
1064  }
1065 
1066 
1067 
1068  // Add information about a new organism, including its stored info and parent's taxon;
1069  // Can't return a pointer for the associated taxon because of obnoxious inheritance problems
1070  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1071  // Ptr<typename Systematics<ORG, ORG_INFO, DATA_STRUCT>::taxon_t>
1072  void Systematics<ORG, ORG_INFO, DATA_STRUCT>::AddOrg(ORG & org, int pos, int update, bool next) {
1073  emp_assert(store_position, "Trying to pass position to a systematics manager that can't use it");
1074  // emp_assert(next_parent, "Adding organism with no parent specified and no next_parent set");
1075  AddOrg(org, pos, next_parent, update, next);
1076  next_parent = nullptr;
1077  }
1078 
1079  // Add information about a new organism, including its stored info and parent's taxon;
1080  // Can't return a pointer for the associated taxon because of obnoxious inheritance problems
1081  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1082  // Ptr<typename Systematics<ORG, ORG_INFO, DATA_STRUCT>::taxon_t>
1083  void Systematics<ORG, ORG_INFO, DATA_STRUCT>::AddOrg(ORG && org, int pos, int update, bool next) {
1084  emp_assert(store_position, "Trying to pass position to a systematics manager that can't use it");
1085  // emp_assert(next_parent, "Adding organism with no parent specified and no next_parent set");
1086  AddOrg(org, pos, next_parent, update, next);
1087  next_parent = nullptr;
1088  }
1089 
1090 
1091  // Version for if you aren't tracking positions
1092  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1094  Systematics<ORG, ORG_INFO, DATA_STRUCT>::AddOrg(ORG & org, Ptr<taxon_t> parent, int update, bool next) {
1095  return AddOrg(org, -1, parent, update, next);
1096  }
1097 
1098  // Version for if you aren't tracking positions
1099  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1101  Systematics<ORG, ORG_INFO, DATA_STRUCT>::AddOrg(ORG && org, Ptr<taxon_t> parent, int update, bool next) {
1102  return AddOrg(org, -1, parent, update, next);
1103  }
1104 
1105  // Add information about a new organism, including its stored info and parent's taxon;
1106  // return a pointer for the associated taxon.
1107  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1109  Systematics<ORG, ORG_INFO, DATA_STRUCT>::AddOrg(ORG && org, int pos, Ptr<taxon_t> parent, int update, bool next) {
1110  return AddOrg(org, pos, parent, update, next);
1111  }
1112 
1113  // Add information about a new organism, including its stored info and parent's taxon;
1114  // return a pointer for the associated taxon.
1115  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1117  Systematics<ORG, ORG_INFO, DATA_STRUCT>::AddOrg(ORG & org, int pos, Ptr<taxon_t> parent, int update, bool next) {
1118  org_count++; // Keep count of how many organisms are being tracked.
1119 
1120  ORG_INFO info = calc_info_fun(org);
1121 
1122  Ptr<taxon_t> cur_taxon = parent;
1123 
1124  // If this organism needs a new taxon, build it!
1125  if (!cur_taxon || cur_taxon->GetInfo() != info) {
1126  if (!cur_taxon) { // No parent -> NEW tree
1127  num_roots++; // ...track extra root.
1128  mrca = nullptr; // ...nix old common ancestor
1129  }
1130 
1131  cur_taxon = NewPtr<taxon_t>(++next_id, info, parent); // Build new taxon.
1132  on_new_sig.Trigger(cur_taxon);
1133  if (store_active) active_taxa.insert(cur_taxon); // Store new taxon.
1134  if (parent) parent->AddOffspring(); // Track tree info.
1135 
1136  cur_taxon->SetOriginationTime(update);
1137  }
1138 
1139  if (store_position && pos >= 0) {
1140  if (next) {
1141  if (pos >= (int)next_taxon_locations.size()) {
1142  next_taxon_locations.resize(pos+1);
1143  }
1144  next_taxon_locations[pos] = cur_taxon;
1145 
1146  } else {
1147  if (pos >= (int)taxon_locations.size()) {
1148  taxon_locations.resize(pos+1);
1149  }
1150  taxon_locations[pos] = cur_taxon;
1151  }
1152  }
1153 
1154  cur_taxon->AddOrg(); // Record the current organism in its taxon.
1155  total_depth += cur_taxon->GetDepth(); // Track the total depth (for averaging)
1156  return cur_taxon; // Return the taxon used.
1157  }
1158 
1159  // Remove an instance of an organism; track when it's gone.
1160  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1162  emp_assert(store_position, "Trying to remove org based on position from systematics manager that doesn't track it.");
1163  emp_assert(pos < (int)taxon_locations.size(), "Invalid position requested for removal", pos, taxon_locations.size());
1164  bool active = RemoveOrg(taxon_locations[pos]);
1165  taxon_locations[pos] = nullptr;
1166  return active;
1167  }
1168 
1169  // Remove an instance of an organism; track when it's gone.
1170  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1172  emp_assert(taxon);
1173 
1174  // Update stats
1175  org_count--;
1176  total_depth -= taxon->GetDepth();
1177 
1178  // emp_assert(Has(active_taxa, taxon));
1179  const bool active = taxon->RemoveOrg();
1180  if (!active) MarkExtinct(taxon);
1181 
1182  return active;
1183  }
1184 
1185  // Remove an instance of an organism; track when it's gone.
1186  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1188  emp_assert(track_synchronous, "Calling RemoveNextOrg on non-synchronous population. Did you mean to use RemoveOrg?");
1189  emp_assert(store_position, "Trying to remove org based on position from systematics manager that doesn't track it.");
1190  emp_assert(pos < (int)next_taxon_locations.size(), "Invalid position requested for removal", pos, taxon_locations.size());
1191 
1192  bool active = RemoveOrg(next_taxon_locations[pos]);
1193  next_taxon_locations[pos] = nullptr;
1194  return active;
1195  }
1196 
1197  // Remove an instance of an organism; track when it's gone.
1198  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1200  emp_assert(track_synchronous, "Calling RemoveNextOrg on non-synchronous population. Did you mean to use RemoveOrg?");
1201  emp_assert(taxon);
1202 
1203  // Update stats
1204  org_count--;
1205  total_depth -= taxon->GetDepth();
1206 
1207  // emp_assert(Has(active_taxa, taxon));
1208  const bool active = taxon->RemoveOrg();
1209  if (!active) MarkExtinct(taxon);
1210 
1211  return active;
1212  }
1213 
1214 
1215  // Climb up a lineage...
1216  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1218  emp_assert(taxon);
1219  emp_assert(Has(active_taxa, taxon));
1220  return taxon->GetParent();
1221  }
1222 
1223  // Print details about the Systematics manager.
1224  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1226  os << "Systematics Status:\n";
1227  os << " store_active=" << store_active
1228  << " store_ancestors=" << store_ancestors
1229  << " store_outside=" << store_outside
1230  << " archive=" << archive
1231  << " next_id=" << next_id
1232  << std::endl;
1233  os << "Active count: " << active_taxa.size();
1234  for (const auto & x : active_taxa) {
1235  os << " [" << x->GetID() << "|" << x->GetNumOrgs() << "," << x->GetNumOff() << "|"
1236  << ((bool) x->GetParent()) << "]";
1237  }
1238  os << std::endl;
1239 
1240  os << "Ancestor count: " << ancestor_taxa.size();
1241  for (const auto & x : ancestor_taxa) {
1242  os << " [" << x->GetID() << "|" << x->GetNumOrgs() << "," << x->GetNumOff() << "|"
1243  << ((bool) x->GetParent()) << "]";
1244  }
1245  os << std::endl;
1246 
1247  os << "Outside count: " << outside_taxa.size();
1248  for (const auto & x : outside_taxa) {
1249  os << " [" << x->GetID() << "|" << x->GetNumOrgs() << "," << x->GetNumOff() << "|"
1250  << ((bool) x->GetParent()) << "]";
1251  }
1252  os << std::endl;
1253  }
1254 
1255  // Print whole lineage.
1256  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1258  os << "Lineage:\n";
1259  while (taxon) {
1260  os << taxon->GetInfo() << std::endl;
1261  taxon = taxon->GetParent();
1262  }
1263  }
1264 
1265  // Calculate the genetic diversity of the population.
1266  template <typename ORG, typename ORG_INFO, typename DATA_STRUCT>
1268  return emp::Entropy(active_taxa, [](Ptr<taxon_t> x){ return x->GetNumOrgs(); }, (double) org_count);
1269  }
1270 
1271 }
1272 
1273 #endif
Ptr< taxon_t > GetTaxonAt(int id)
Definition: Systematics.h:644
SignalKey tracks a specific function triggered by a signal. For now, its just a value pair...
Definition: Signal.h:30
bool RemoveOrg()
Definition: Systematics.h:182
void RecordPhenotype(PHEN_TYPE phen)
Definition: Systematics.h:91
Definition: Systematics.h:214
const info_t info
Details for the organims associated within this taxanomic group.
Definition: Systematics.h:111
Systematics(fun_calc_info_t calc_taxon, bool _active=true, bool _anc=true, bool _all=false, bool _pos=true)
Definition: Systematics.h:447
virtual data_ptr_t AddDeleteriousStepDataNode(const std::string &name="deleterious_steps")
Definition: Systematics.h:545
bool GetArchive() const
Are we storing any taxa types that have died out?
Definition: Systematics.h:257
ORG_INFO info_t
Definition: Systematics.h:108
std::string to_string(ALL_TYPES &&...all_values)
Definition: string_utils.h:511
const data_t & GetData() const
Definition: Systematics.h:156
size_t GetDepth() const
Get the number of taxanomic steps since the ancestral organism was injected into the World...
Definition: Systematics.h:153
void RemoveTotalOffspring()
Definition: Systematics.h:201
void AddOrg(ORG &&org, int pos, int update=-1, bool next=false)
Definition: Systematics.h:1083
int CountDeleteriousSteps(Ptr< taxon_t > taxon)
Definition: SystematicsAnalysis.h:108
void Delete()
Definition: Ptr.h:737
double GetEvolutionaryDistinctiveness(Ptr< taxon_t > tax, double time) const
Definition: Systematics.h:691
The default - an empty struct.
Definition: Systematics.h:56
size_t GetNumAncestors() const
How many taxa are ancestors of living organisms (but have died out themselves)?
Definition: Systematics.h:481
int GetBranchesToRoot(Ptr< taxon_t > tax) const
Definition: Systematics.h:926
double GetSumPairwiseDistance(bool branch_only=false) const
Definition: Systematics.h:772
size_t num_orgs
How many organisms currently exist of this group?
Definition: Systematics.h:113
data_ptr_t GetDataNode(const std::string &name)
Definition: Systematics.h:312
~Systematics()
Definition: Systematics.h:454
void SetStoreActive(bool new_val)
Are we storing all taxa that are still alive in the population?
Definition: Systematics.h:275
std::true_type has_phen_t
Definition: Systematics.h:60
bool store_position
Keep a vector mapping positions to pointers.
Definition: Systematics.h:220
DataManagers handle sets of DataNode objects that all have the same tracking settings.
Definition: DataManager.h:25
emp::vector< double > GetPairwiseDistances(bool branch_only=false) const
Definition: Systematics.h:801
node_t & New(const std::string &name)
Creates and adds a new DataNode, with the name specified in.
Definition: DataManager.h:48
void RecordMutation(std::unordered_map< std::string, int > muts)
Definition: Systematics.h:77
void PrintLineage(Ptr< taxon_t > taxon, std::ostream &os=std::cout) const
Print whole lineage.
Definition: Systematics.h:1257
bool RemoveOrg(int pos)
Remove an instance of an organism; track when it&#39;s gone.
Definition: Systematics.h:1161
double GetMeanPairwiseDistance(bool branch_only=false) const
Definition: Systematics.h:757
bool track_synchronous
Does this systematics manager need to keep track of current and next positions?
Definition: Systematics.h:221
double GetVariancePairwiseDistance(bool branch_only=false) const
Definition: Systematics.h:787
std::true_type has_mutations_t
Definition: Systematics.h:61
void SetArchive(bool new_val)
Are we storing any taxa types that have died out?
Definition: Systematics.h:284
virtual ~SystematicsBase()
Definition: Systematics.h:239
void AddOrg()
Add a new organism to this Taxon.
Definition: Systematics.h:162
void SetStoreAncestors(bool new_val)
Are we storing all taxa that are the ancestors of living organims in the population?
Definition: Systematics.h:278
bool GetStoreAncestors() const
Are we storing all taxa that are the ancestors of living organims in the population?
Definition: Systematics.h:251
void PrintStatus(std::ostream &os=std::cout) const
Print details about the Systematics manager.
Definition: Systematics.h:1225
void Update()
Definition: Systematics.h:464
void push_back(PB_Ts &&...args)
Definition: vector.h:189
void SetNextParent(Ptr< taxon_t > p)
Definition: Systematics.h:502
int CountUniquePhenotypes(Ptr< taxon_t > taxon)
Definition: SystematicsAnalysis.h:144
double GetAveDepth() const
What is the average phylogenetic depth of organisms in the population?
Definition: Systematics.h:269
size_t tot_orgs
How many organisms have ever existed of this group?
Definition: Systematics.h:114
void Add()
Definition: DataNode.h:655
double Entropy(const CONTAINER &weights)
Convert a vector of weights to probabilities and return the entropy of the system.
Definition: info_theory.h:32
virtual data_ptr_t AddPairwiseDistanceDataNode(const std::string &name="pairwise_distances")
Definition: Systematics.h:527
data_ptr_t AddDataNode(std::function< double()> pull_fun, const std::string &name)
Definition: Systematics.h:304
double origination_time
When did this taxon first appear in the population?
Definition: Systematics.h:118
void SetTrackSynchronous(bool new_val)
Are we tracking organisms evolving in synchronous generations?
Definition: Systematics.h:272
Definition: Ptr.h:744
std::unordered_map< std::string, int > mut_counts
Definition: Systematics.h:65
void SetStoreOutside(bool new_val)
Are we storing all taxa that have died out, as have all of their descendants.
Definition: Systematics.h:281
data
A set of modifiers are available do describe DataNode.
Definition: DataNode.h:38
size_t GetNumActive() const
How many taxa are still active in the population?
Definition: Systematics.h:478
size_t GetTotalOrgs() const
How many living organisms are currently being tracked?
Definition: Systematics.h:263
size_t size() const
Definition: vector.h:151
const std::unordered_set< Ptr< taxon_t >, hash_t > & GetActive() const
Definition: Systematics.h:474
Ptr< taxon_t > GetNextTaxonAt(int id)
Definition: Systematics.h:649
const double GetFitness() const
Definition: Systematics.h:73
Definition: DataNode.h:648
int GetPhylogeneticDiversity() const
Definition: Systematics.h:668
std::false_type has_phen_t
Definition: Systematics.h:52
void AddTotalOffspring()
Recursively increment total offspring count for this and all ancestors.
Definition: Systematics.h:169
bool GetTrackSynchronous() const
Are we tracking a synchronous population?
Definition: Systematics.h:245
virtual data_ptr_t AddEvolutionaryDistinctivenessDataNode(const std::string &name="evolutionary_distinctiveness")
Definition: Systematics.h:514
SystematicsBase(bool _active=true, bool _anc=true, bool _all=false, bool _pos=true)
Definition: Systematics.h:234
Generic version of Signals; needs specialization to a function type..
Definition: Signal.h:159
SignalKey OnPrune(std::function< void(Ptr< taxon_t >)> &fun)
Definition: Systematics.h:511
size_t GetID() const
Get a unique ID for this taxon; IDs are assigned sequentially, so newer taxa have higher IDs...
Definition: Systematics.h:135
std::false_type has_mutations_t
Definition: Systematics.h:51
data_ptr_t AddDeleteriousStepDataNodeImpl(bool decoy, const std::string &name="deleterious_steps")
Definition: Systematics.h:549
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
bool RemoveNextOrg(int pos)
Remove org from next population (for use with synchronous generations)
Definition: Systematics.h:1187
data_ptr_t AddDeleteriousStepDataNodeImpl(typename std::enable_if< DATA_STRUCT::has_fitness_t::value, T >::type decoy, const std::string &name="deleterious_steps")
Definition: Systematics.h:556
size_t curr_update
Definition: Systematics.h:229
const info_t & GetInfo() const
Retrieve the tracked info associated with this Taxon.
Definition: Systematics.h:138
size_t num_offspring
How many direct offspring groups exist from this one.
Definition: Systematics.h:115
bool store_ancestors
Store all of the direct ancestors from living taxa?
Definition: Systematics.h:217
data_t & GetData()
Definition: Systematics.h:155
bool GetStoreOutside() const
Are we storing all taxa that have died out, as have all of their descendants.
Definition: Systematics.h:254
Definition: Systematics.h:49
bool RemoveOffspring()
Remove and offspring taxa after its entire sub-tree has died out (pruning)
Definition: Systematics.h:191
data_ptr_t AddDataNode(const std::string &name)
Definition: Systematics.h:292
DataNode< double, data::Current, data::Range > fitness
Definition: Systematics.h:66
data_ptr_t AddUniqueTaxaDataNodeImpl(bool decoy, const std::string &name="unique_taxa")
Definition: Systematics.h:599
size_t GetNumRoots() const
How many independent trees are being tracked?
Definition: Systematics.h:266
DATA_STRUCT data
A struct for storing additional information about this taxon.
Definition: Systematics.h:120
Ptr< this_t > parent
Pointer to parent group (nullptr if injected)
Definition: Systematics.h:112
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
int GetDistanceToRoot(Ptr< taxon_t > tax) const
Definition: Systematics.h:904
size_t org_count
How many organisms are currently active?
Definition: Systematics.h:224
size_t id
ID for this Taxon (Unique within this Systematics)
Definition: Systematics.h:110
void AddOffspring()
Add a new offspring Taxon to this one.
Definition: Systematics.h:165
void resize(size_t new_size)
Definition: vector.h:161
int CountPhenotypeChanges(Ptr< taxon_t > taxon)
Definition: SystematicsAnalysis.h:126
void SetCalcInfoFun(fun_calc_info_t f)
Definition: Systematics.h:470
data_ptr_t AddUniqueTaxaDataNodeImpl(typename std::enable_if< DATA_STRUCT::has_phen_t::value, T >::type decoy, const std::string &name="unique_taxa")
Definition: Systematics.h:606
virtual data_ptr_t AddVolatilityDataNode(const std::string &name="volatility")
Definition: Systematics.h:570
double GetTaxonDistinctiveness(Ptr< taxon_t > tax) const
Definition: Systematics.h:678
DATA_STRUCT data_t
Definition: Systematics.h:123
Ptr< taxon_t > Parent(Ptr< taxon_t > taxon) const
Climb up a lineage...
Definition: Systematics.h:1217
double GetOriginationTime() const
Definition: Systematics.h:158
bool GetStorePosition() const
Are we storing the positions of taxa?
Definition: Systematics.h:260
void RecordFitness(double fit)
Definition: Systematics.h:87
PHEN_TYPE phenotype
This taxon&#39;s fitness (for assessing deleterious mutational steps)
Definition: Systematics.h:67
Ptr< taxon_t > GetMRCA() const
Request a pointer to the Most-Recent Common Ancestor for the population.
Definition: Systematics.h:1036
size_t GetTotOrgs() const
Get the total number of organisms that have ever lived associated with this Taxon.
Definition: Systematics.h:147
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
int CountMuts(Ptr< taxon_t > taxon, std::string type="substitution")
Definition: SystematicsAnalysis.h:76
double CalcDiversity() const
Calculate the genetic diversity of the population.
Definition: Systematics.h:1267
Definition: Ptr.h:711
virtual data_ptr_t AddUniqueTaxaDataNode(const std::string &name="unique_taxa")
Definition: Systematics.h:595
SignalKey OnNew(std::function< void(Ptr< taxon_t >)> &fun)
Definition: Systematics.h:506
size_t GetTreeSize() const
How many taxa are in the current phylogeny?
Definition: Systematics.h:487
data_ptr_t AddDataNode(std::function< emp::vector< double >()> pull_set_fun, const std::string &name)
Definition: Systematics.h:297
#define emp_assert(...)
Definition: assert.h:199
void SetOriginationTime(double time)
Definition: Systematics.h:159
Ptr< this_t > GetParent() const
Retrieve a pointer to the parent Taxon.
Definition: Systematics.h:141
std::enable_if<!emp::is_ptr_type< typename C::value_type >::value &&std::is_scalar< typename C::value_type >::value, double >::type Variance(C &elements)
Definition: stats.h:113
virtual data_ptr_t AddMutationCountDataNode(const std::string &name="mutation_count", const std::string &mutation="substitution")
Definition: Systematics.h:620
Taxon(size_t _id, const info_t &_info, Ptr< this_t > _parent=nullptr)
Definition: Systematics.h:125
size_t num_roots
How many distint injected ancestors are currently in population?
Definition: Systematics.h:226
bool GetStoreActive() const
Are we storing all taxa that are still alive in the population?
Definition: Systematics.h:248
size_t GetNumOutside() const
How many taxa are stored that have died out, as have their descendents?
Definition: Systematics.h:484
void SetStorePosition(bool new_val)
Are we storing the location of taxa?
Definition: Systematics.h:287
virtual data_ptr_t AddPhylogeneticDiversityDataNode(const std::string &name="phylogenetic_diversity")
Definition: Systematics.h:535
DataManager< double, data::Current, data::Info, data::Range, data::Stats, data::Pull > data_nodes
Definition: Systematics.h:231
void SetNextParent(int pos)
Definition: Systematics.h:492
bool store_active
Store all of the currently active taxa?
Definition: Systematics.h:216
size_t total_offspring
How many total extant offspring taxa exist from this one (i.e. including indirect) ...
Definition: Systematics.h:116
std::true_type has_fitness_t
Definition: Systematics.h:62
size_t GetNumTaxa() const
How many taxa are stored in total?
Definition: Systematics.h:490
int GetTotalOffspring()
Definition: Systematics.h:178
size_t depth
How deep in tree is this node? (Root is 0)
Definition: Systematics.h:117
const PHEN_TYPE & GetPhenotype() const
This taxon&#39;s phenotype (for assessing phenotypic change)
Definition: Systematics.h:69
const node_t & Get(const std::string &name) const
Definition: DataManager.h:63
const std::unordered_set< Ptr< taxon_t >, hash_t > & GetAncestors() const
Definition: Systematics.h:475
size_t next_id
What ID value should the next new taxon have?
Definition: Systematics.h:228
size_t GetNumOff() const
Get the number of taxa that were produced by organisms from this Taxon.
Definition: Systematics.h:150
size_t GetNumOrgs() const
Get the number of living organisms currently associated with this Taxon.
Definition: Systematics.h:144
A Taxon represents a type of organism in a phylogeny.
Definition: Systematics.h:105
std::false_type has_fitness_t
Definition: Systematics.h:50
int GetMRCADepth() const
Request the depth of the Most-Recent Common Ancestor; return -1 for none.
Definition: Systematics.h:1060
data_ptr_t AddVolatilityDataNodeImpl(bool decoy, const std::string &name="volatility")
Definition: Systematics.h:574
std::unordered_set< Ptr< taxon_t >, hash_t > * GetActivePtr()
Definition: Systematics.h:473
data_ptr_t AddMutationCountDataNodeImpl(typename std::enable_if< DATA_STRUCT::has_mutations_t::value, T >::type decoy, const std::string &name="mutation_count", const std::string &mutation="substitution")
Definition: Systematics.h:631
PHEN_TYPE phen_t
Definition: Systematics.h:59
data_ptr_t AddMutationCountDataNodeImpl(bool decoy, const std::string &name="mutation_count", const std::string &mutation="substitution")
Definition: Systematics.h:624
data_ptr_t AddVolatilityDataNodeImpl(typename std::enable_if< DATA_STRUCT::has_phen_t::value, T >::type decoy, const std::string &name="volatility")
Definition: Systematics.h:581
bool store_outside
Store taxa that are extinct with no living descendants?
Definition: Systematics.h:218
size_t total_depth
Sum of taxa depths for calculating average.
Definition: Systematics.h:225
std::enable_if<!emp::is_ptr_type< typename C::value_type >::value &&std::is_scalar< typename C::value_type >::value, typename C::value_type >::type Sum(C &elements)
Definition: stats.h:33
bool HasNode(const std::string &name)
Definition: DataManager.h:43
bool archive
Set to true if we are supposed to do any archiving of extinct taxa.
Definition: Systematics.h:219