|
57 | 57 | #include <limits>
|
58 | 58 | #include <numeric>
|
59 | 59 | #include <set>
|
| 60 | +#include <utility> |
60 | 61 | #include <vector>
|
61 | 62 |
|
62 | 63 | #include "stdlib.h"
|
@@ -5471,6 +5472,114 @@ class cActionReplicateDemesHighestBirthCount : public cAction
|
5471 | 5472 | };
|
5472 | 5473 |
|
5473 | 5474 |
|
| 5475 | +/* |
| 5476 | + * Replicate deme(s) with the highest fecundity |
| 5477 | + * (cell count with ties broken by birth count) |
| 5478 | + */ |
| 5479 | +class cActionReplicateDemesHighestFecundity : public cAction |
| 5480 | +{ |
| 5481 | +private: |
| 5482 | + double m_replprob; |
| 5483 | + int m_replmax; |
| 5484 | +public: |
| 5485 | + cActionReplicateDemesHighestFecundity(cWorld *world, const cString &args, Feedback &) : cAction(world, args), m_replprob(0.01), m_replmax(std::numeric_limits<int>::max()) |
| 5486 | + { |
| 5487 | + cString largs(args); |
| 5488 | + if (largs.GetSize()) m_replprob = largs.PopWord().AsDouble(); |
| 5489 | + if (largs.GetSize()) m_replmax = largs.PopWord().AsInt(); |
| 5490 | + |
| 5491 | + assert(m_replprob >= 0); |
| 5492 | + } |
| 5493 | + |
| 5494 | + static const cString GetDescription() { return "Arguments: [double replprob=0.01] [int replmax = intmax]"; } |
| 5495 | + |
| 5496 | + void Process(cAvidaContext &ctx) |
| 5497 | + { |
| 5498 | + const int part_size = m_world->GetConfig().DEMES_PARTITION_INTERVAL.Get(); |
| 5499 | + const int num_demes = m_world->GetPopulation().GetNumDemes(); |
| 5500 | + if (part_size) |
| 5501 | + { |
| 5502 | + for (int i = 0; i < num_demes; i += part_size) |
| 5503 | + { |
| 5504 | + const int begin = i; |
| 5505 | + const int end = std::min(i + part_size, num_demes); |
| 5506 | + ProcessPartition(begin, end, ctx); |
| 5507 | + } |
| 5508 | + } |
| 5509 | + else |
| 5510 | + { |
| 5511 | + ProcessPartition(0, num_demes, ctx); |
| 5512 | + } |
| 5513 | + } |
| 5514 | + |
| 5515 | + void ProcessPartition(const int begin, const int end, cAvidaContext &ctx) |
| 5516 | + { |
| 5517 | + cPopulation& pop = m_world->GetPopulation(); |
| 5518 | + const int num_demes = end - begin; |
| 5519 | + std::vector<int> deme_indices(num_demes); |
| 5520 | + std::iota(std::begin(deme_indices), std::end(deme_indices), begin); |
| 5521 | + |
| 5522 | + const int binomial_draw = ctx.GetRandom().GetRandBinomial( |
| 5523 | + num_demes, |
| 5524 | + m_replprob |
| 5525 | + ); |
| 5526 | + const int repl_quota = std::min(binomial_draw, m_replmax); |
| 5527 | + if (repl_quota == 0) return; |
| 5528 | + |
| 5529 | + if (repl_quota != binomial_draw) { |
| 5530 | + std::cout << "warning: capped repl quota at " << repl_quota << " from " << binomial_draw << " binomial sample with " << num_demes << " eligible and repl prob " << m_replprob << std::endl; |
| 5531 | + } |
| 5532 | + |
| 5533 | + using fecundity_t = std::pair<int, int>; |
| 5534 | + struct GetFecundity { |
| 5535 | + cPopulation &pop; |
| 5536 | + GetFecundity(cPopulation &pop) : pop(pop) {} |
| 5537 | + fecundity_t operator()(const int d) { |
| 5538 | + return fecundity_t( |
| 5539 | + pop.GetDeme(d).GetOrgCount(), pop.GetDeme(d).GetBirthCount() |
| 5540 | + ); |
| 5541 | + } |
| 5542 | + }; |
| 5543 | + std::vector<fecundity_t> fecundities(num_demes); |
| 5544 | + std::transform( |
| 5545 | + std::begin(deme_indices), std::end(deme_indices), |
| 5546 | + std::begin(fecundities), |
| 5547 | + GetFecundity(pop) |
| 5548 | + ); |
| 5549 | + |
| 5550 | + struct Comp { |
| 5551 | + std::vector<fecundity_t> &fecundities; |
| 5552 | + const int begin; |
| 5553 | + Comp(std::vector<fecundity_t> &fecundities, const int begin) |
| 5554 | + : fecundities(fecundities), begin(begin) {} |
| 5555 | + bool operator()(const int d1, const int d2) |
| 5556 | + { |
| 5557 | + return fecundities[d1 - begin] > fecundities[d2 - begin]; |
| 5558 | + } |
| 5559 | + }; |
| 5560 | + std::partial_sort( |
| 5561 | + std::begin(deme_indices), |
| 5562 | + std::next(std::begin(deme_indices), repl_quota), |
| 5563 | + std::end(deme_indices), |
| 5564 | + Comp(fecundities, begin) |
| 5565 | + ); |
| 5566 | + |
| 5567 | + struct DoRepl { |
| 5568 | + cPopulation &pop; |
| 5569 | + cAvidaContext &ctx; |
| 5570 | + DoRepl(cPopulation &pop, cAvidaContext &ctx) : pop(pop), ctx(ctx) {} |
| 5571 | + void operator()(const int d) { pop.ReplicateDeme(pop.GetDeme(d), ctx); } |
| 5572 | + }; |
| 5573 | + std::for_each( |
| 5574 | + std::begin(deme_indices), |
| 5575 | + std::next(std::begin(deme_indices), repl_quota), |
| 5576 | + DoRepl(pop, ctx) |
| 5577 | + ); |
| 5578 | + |
| 5579 | + } // End Process() |
| 5580 | +}; |
| 5581 | + |
| 5582 | + |
5474 | 5583 | /*
|
5475 | 5584 | Set the ages at which treatable demes can be treated
|
5476 | 5585 |
|
@@ -6143,6 +6252,7 @@ void RegisterPopulationActions(cActionLibrary* action_lib)
|
6143 | 6252 | action_lib->Register<cActionSetDemeTreatmentAges>("SetDemeTreatmentAges");
|
6144 | 6253 | action_lib->Register<cActionKillDemesHighestParasiteLoad>("KillDemesHighestParasiteLoad");
|
6145 | 6254 | action_lib->Register<cActionReplicateDemesHighestBirthCount>("ReplicateDemesHighestBirthCount");
|
| 6255 | + action_lib->Register<cActionReplicateDemesHighestFecundity>("ReplicateDemesHighestFecundity"); |
6146 | 6256 | action_lib->Register<cActionKillMeanBelowThresholdPaintable>("KillMeanBelowThresholdPaintable");
|
6147 | 6257 |
|
6148 | 6258 | action_lib->Register<cActionDiffuseHGTGenomeFragments>("DiffuseHGTGenomeFragments");
|
|
0 commit comments