Skip to content

Commit 04a5341

Browse files
committed
Impl, test ReplicateDemesHighestFecundity
This criterion prevents demes from gaming ReplicateDemesHighestBirthCount by spamming nonviable offspring
1 parent 8d41137 commit 04a5341

14 files changed

+1382
-0
lines changed

Diff for: avida-core/source/actions/PopulationActions.cc

+110
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <limits>
5858
#include <numeric>
5959
#include <set>
60+
#include <utility>
6061
#include <vector>
6162

6263
#include "stdlib.h"
@@ -5471,6 +5472,114 @@ class cActionReplicateDemesHighestBirthCount : public cAction
54715472
};
54725473

54735474

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+
54745583
/*
54755584
Set the ages at which treatable demes can be treated
54765585
@@ -6143,6 +6252,7 @@ void RegisterPopulationActions(cActionLibrary* action_lib)
61436252
action_lib->Register<cActionSetDemeTreatmentAges>("SetDemeTreatmentAges");
61446253
action_lib->Register<cActionKillDemesHighestParasiteLoad>("KillDemesHighestParasiteLoad");
61456254
action_lib->Register<cActionReplicateDemesHighestBirthCount>("ReplicateDemesHighestBirthCount");
6255+
action_lib->Register<cActionReplicateDemesHighestFecundity>("ReplicateDemesHighestFecundity");
61466256
action_lib->Register<cActionKillMeanBelowThresholdPaintable>("KillMeanBelowThresholdPaintable");
61476257

61486258
action_lib->Register<cActionDiffuseHGTGenomeFragments>("DiffuseHGTGenomeFragments");

Diff for: avida-core/tests/demes_ReplicateDemesHighestFecundity/config/avida.cfg

+689
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#filetype germline_data
2+
#format deme_id hw_type inst_set sequence deme_birth_count deme_parasite_memory_score
3+
# Mode 1 Germline Save
4+
# Tue Aug 29 01:14:50 2023
5+
# 1: Deme ID
6+
# 2: Hardware Type ID
7+
# 3: Inst Set Name
8+
# 4: Genome Sequence
9+
# 5: Deme Birth Count
10+
# 6: Deme Parasite Memory Score
11+
12+
0 2 transsmt ycdBCiEdimFjfCDaknmsAjempczypqvcrGxab 42 24.8
13+
1 2 transsmt ycdBCiEdimFjfCDaknmsAjemEEcgccgssmhEEcsdseDcAcBcggclEEcDEgcvrsAmlzessjhcdcggkhamtmciEEvjDdhjidzoAyndvmEdbgznjDmcjohohooayaxdyalbcekzebjcogEtjgjacblDvubADnslyyocgsAcjCbobffhmvnnAdbDfkmxcagBFfndytqhutjdzfdjsnflfoqCwcvhsjcvbmlsqcjrgyiDivvnFhrArcsmifbClvluDqmCBbtiDhiEfACcarpEczijdljujACbfzuDEFyaqqekizDosbbzjgmpczypqvcrGxab 33 24.8
14+
1 2 transsmt ycdBCiEdimFjfCDaknmsAjemEEcgccgssmhEEcsdseDcAcBcggclEEcDEgcvrsAmlzessjhcdcggkhamtmciEEvjDdhjidzoAyndvmEdbgznjDmcjohohooayaxdyalbcekzebjcogEtjgjacblDvubADnslyyocgsAcjCbobffhmvnnAdbDfkmxcagBFfndytqhutjdzfdjsnflfoqCwcvhsjcvbmlsqcjrgyiDivvnFhrArcsmifbClvluDqmCBbtiDhiEfACcarpEczijdljujACbfzuDEFyaqqekizDosbbzjgmpczypqvcrGxab 33 24.8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
REACTION NOT not process:value=1.0:type=pow requisite:max_count=1
2+
REACTION NAND nand process:value=1.0:type=pow requisite:max_count=1
3+
REACTION AND and process:value=2.0:type=pow requisite:max_count=1
4+
REACTION ORN orn process:value=2.0:type=pow requisite:max_count=1
5+
REACTION OR or process:value=3.0:type=pow requisite:max_count=1
6+
REACTION ANDN andn process:value=3.0:type=pow requisite:max_count=1
7+
REACTION NOR nor process:value=4.0:type=pow requisite:max_count=1
8+
REACTION XOR xor process:value=4.0:type=pow requisite:max_count=1
9+
REACTION EQU equ process:value=5.0:type=pow requisite:max_count=1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
u begin InjectAll filename=evolved-not.org
2+
u begin LoadGermlines detailgermlines-500.sgerm
3+
u begin LoadBirthCounts detailgermlines-500.sgerm
4+
u begin SavePopulation
5+
u begin SaveGermlines filename=evolved.sgerm:birthcounts=1
6+
u 2 ReplicateDemesHighestFecundity 1.0 1
7+
u 2 SaveGermlines filename=evolved.sgerm:birthcounts=1
8+
u 2 SavePopulation
9+
u 3 Exit

0 commit comments

Comments
 (0)