Skip to content

Commit b281d30

Browse files
committed
start of antibiotic mode prototype, functors aren't quite right
1 parent d6397cc commit b281d30

9 files changed

Lines changed: 193 additions & 26 deletions

File tree

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ pgg-mode: source/native/symbulation_pgg.cc
5555
sgp-mode: source/native/symbulation_sgp.cc
5656
$(CXX_nat) $(CFLAGS_nat) source/native/symbulation_sgp.cc -o symbulation_sgp
5757

58+
antibiotic-mode: source/native/symbulation_antibiotic.cc
59+
$(CXX_nat) $(CFLAGS_nat) source/native/symbulation_antibiotic.cc -o symbulation_antibiotic
60+
5861
symbulation.js: source/web/symbulation-web.cc
5962
$(CXX_web) $(CFLAGS_web) source/web/symbulation-web.cc -o web/symbulation.js
6063

source/Organism.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class Organism {
7474
std::cout << "GetDead called from Organism" << std::endl;
7575
throw "Organism method called!";
7676
}
77+
virtual void ApplyOutputPoints() { //TODO: make in SGPHost as well
78+
std::cout << "ApplyOutputPoints called from Organism" << std::endl;
79+
throw "Organism method called!";
80+
}
7781
virtual void Process(emp::WorldPosition location) {
7882
std::cout << "Process called from Organism" << std::endl;
7983
throw "Organism method called!";
@@ -382,5 +386,15 @@ class Organism {
382386
throw "Organism method called!";
383387
}
384388

389+
//TODO: Figure out how to remove?
390+
virtual bool MeetsIndependentReproRequirements() {
391+
std::cout << "MeetsIndependentReproRequirements called from Organism" << std::endl;
392+
throw "Organism method called!";
393+
}
394+
virtual void PayIndependentReproCost() {
395+
std::cout << "PayIndependentReproCost called from Organism" << std::endl;
396+
throw "Organism method called!";
397+
}
398+
385399
};
386400
#endif
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef ANTIBIOTIC_CONFIG_H
2+
#define ANTIBIOTIC_CONFIG_H
3+
#include "../../Empirical/include/emp/config/config.hpp"
4+
#include "../ConfigSetup.h"
5+
#include "../sgp_mode/SGPConfigSetup.h"
6+
7+
namespace antibioticmode{
8+
9+
/*Notes: can we set different defaults for values in this config?*/
10+
EMP_EXTEND_CONFIG(AntibioticConfig, sgpmode::SymConfigSGP,
11+
GROUP(ANTI, "Settings for antibiotic resistance"),
12+
VALUE(NUM_HUMANS, size_t, 10, "Number of humans in the simulation")
13+
)
14+
}
15+
16+
#endif

source/antibiotic-mode/Human.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Properties:
3+
* SGPWorld - microbiome
4+
*
5+
*/
6+
7+
#ifndef HUMAN_H
8+
#define HUMAN_H
9+
10+
#include "../sgp_mode/SGPWorld.h"
11+
#include "AntibioticConfigSetup.h"
12+
13+
namespace antibioticmode {
14+
15+
class Human {
16+
17+
protected:
18+
19+
/**
20+
* The SGPWorld that holds the microbiome of this human.
21+
*/
22+
emp::Ptr<sgpmode::SGPWorld> microbiome;
23+
24+
/**
25+
* Config for all settings
26+
*/
27+
emp::Ptr<AntibioticConfig> my_config;
28+
29+
public:
30+
Human(emp::Random& _random, emp::Ptr<AntibioticConfig> _config) :
31+
my_config(_config)
32+
{
33+
microbiome = emp::NewPtr<sgpmode::SGPWorld>(_random, _config);
34+
microbiome->Setup();
35+
}
36+
37+
emp::Ptr<sgpmode::SGPWorld> GetMicrobiome() { return microbiome; }
38+
39+
};
40+
}
41+
#endif //HUMAN_H

source/default_mode/SymWorld.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ class SymWorld : public emp::World<Organism> {
3636
using pop_t = typename emp::World<Organism>::pop_t;
3737
using host_systematics_t = emp::Systematics<Organism, taxon_t::info_t, datastruct::HostTaxonData>;
3838
using sym_systematics_t = emp::Systematics<Organism, taxon_t::info_t, datastruct::SymbiontTaxonData>;
39+
using fun_check_sym_independent_repro_reqs_t = std::function<bool(
40+
Organism& /* symbiont */
41+
)>;
42+
using fun_pay_sym_independent_repro_cost_t = std::function<void(
43+
Organism& /* symbiont */
44+
)>;
3945

4046
enum class SPATIAL_STRUCT_MODE { WELL_MIXED, GRID, LOAD };
4147
static const std::unordered_map<std::string, SPATIAL_STRUCT_MODE> spatial_struct_mode_cfg_mapping;
@@ -86,6 +92,19 @@ class SymWorld : public emp::World<Organism> {
8692
*/
8793
fun_calc_info_t calc_sym_info_fun;
8894

95+
/**
96+
*
97+
* Purpose: Represents a standard function object which determines if a symbiont can reproduce independently.
98+
*
99+
*/
100+
fun_check_sym_independent_repro_reqs_t fun_check_sym_independent_repro_reqs;
101+
102+
/**
103+
*
104+
* Purpose: Represents a standard function object which pays the cost of independent reproduction for a symbiont.
105+
*
106+
*/
107+
fun_pay_sym_independent_repro_cost_t fun_pay_sym_independent_repro_cost;
89108

90109
/**
91110
*
@@ -269,6 +288,18 @@ class SymWorld : public emp::World<Organism> {
269288
if (my_config->TAG_MATCHING()) {
270289
SetupTagMatching();
271290
}
291+
292+
fun_check_sym_independent_repro_reqs = [](
293+
Organism& sym
294+
) {
295+
return sym.MeetsIndependentReproRequirements();
296+
};
297+
298+
fun_pay_sym_independent_repro_cost = [](
299+
Organism& sym
300+
) {
301+
sym.PayIndependentReproCost();
302+
};
272303
}
273304

274305

@@ -330,6 +361,23 @@ class SymWorld : public emp::World<Organism> {
330361
}
331362
}
332363

364+
/* Allow setting functor from native file*/
365+
void SetCheckSymIndependentReproReqsFunctor(fun_check_sym_independent_repro_reqs_t fun) {
366+
fun_check_sym_independent_repro_reqs = fun;
367+
}
368+
369+
bool CheckSymIndependentReproReqs(Organism& sym) {
370+
return fun_check_sym_independent_repro_reqs(sym);
371+
}
372+
373+
void SetPaySymIndependentReproCostFunctor(fun_pay_sym_independent_repro_cost_t fun) {
374+
fun_pay_sym_independent_repro_cost = fun;
375+
}
376+
377+
void PaySymIndependentReproCost(Organism& sym) {
378+
fun_pay_sym_independent_repro_cost(sym);
379+
}
380+
333381
/**
334382
* Input: Boolean indicating whether world uses synchronous generations or not.
335383
*

source/default_mode/Symbiont.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,22 @@ class Symbiont: public Organism {
802802
return GetPoints() >= required_points;
803803
}
804804

805+
/*
806+
* Input: None
807+
*
808+
* Output: None
809+
*
810+
* Purpose: To pay the cost of independent reproduction, by subtracting the required resources from the symbiont's points.
811+
*/
812+
void PayIndependentReproCost() {
813+
// symbiont reproduces independently (horizontal transmission) if it has enough resources
814+
//TODO: try just subtracting points to be consistent with vertical transmission
815+
//points = points - my_config->SYM_HORIZ_TRANS_RES();
816+
if(!my_config->TAG_MATCHING() && !my_config->FREE_HT_FAILURE()) SetPoints(0);
817+
// removing the above for tag matching--sym parent points are
818+
// now set to 0 in symdobirth
819+
}
820+
805821
/*
806822
* Input: sym_pos, world position
807823
*
@@ -811,18 +827,15 @@ class Symbiont: public Organism {
811827
*/
812828
bool AttemptIndependentReproduction(emp::WorldPosition sym_pos) {
813829
if (my_config->HORIZ_TRANS()) { //non-lytic horizontal transmission enabled
814-
if (MeetsIndependentReproRequirements()) {
830+
if (my_world->CheckSymIndependentReproReqs(*this)) {
815831
emp::DataMonitor<double, emp::data::Histogram>& data_node_attempts_horiztrans = my_world->GetHorizontalTransmissionAttemptCount();
816832
data_node_attempts_horiztrans.AddDatum(GetIntVal());
817833

818-
// symbiont reproduces independently (horizontal transmission) if it has enough resources
819-
//TODO: try just subtracting points to be consistent with vertical transmission
820-
//points = points - my_config->SYM_HORIZ_TRANS_RES();
821834

822835

823-
if(!my_config->TAG_MATCHING() && !my_config->FREE_HT_FAILURE()) SetPoints(0);
824-
// removing the above for tag matching--sym parent points are
825-
// now set to 0 in symdobirth
836+
my_world->PaySymIndependentReproCost(*this);
837+
838+
826839
return true;
827840
}
828841
}

source/sgp_mode/SGPSymbiont.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#include "../default_mode/Symbiont.h"
55
#include "hardware/SGPHardware.h"
66
#include "SGPHost.h"
7+
#include "org_type_info.h"
78

89
#include "emp/base/Ptr.hpp"
910
#include "emp/Evolve/World_structure.hpp"
1011

1112
namespace sgpmode {
13+
using nutrient_sym_mode_t = typename org_info::NutrientSymbiontType;
1214

1315
template<typename HW_SPEC_T>
1416
class SGPSymbiont : public Symbiont {
@@ -245,6 +247,29 @@ class SGPSymbiont : public Symbiont {
245247
if(my_host) my_world->TriggerAfterEndosymProcessSig(pos, *this, my_host);
246248
}
247249

250+
void ApplyOutputPoints(double points) {
251+
// Calc base task value based on task environment, task requirements, and
252+
// symbiont's current point value.
253+
// NOTE - A little funky because task value might be a multiplier on
254+
// current sym points.
255+
// So, to get the value *added* by the task, we subtract original point value.
256+
257+
double task_points = points - GetPoints();
258+
259+
//Parasitic Nutrient symbionts receieve less rewards from completing tasks to incentivize matching tasks with hosts
260+
if(my_world->GetConfig().ENABLE_NUTRIENT() && my_world->GetNutrientSymType() == nutrient_sym_mode_t::PARASITE){
261+
task_points *= my_world->GetConfig().PARASITE_BASE_TASK_VALUE_PROP();
262+
}
263+
264+
// Add earned task points to symbiont's point total
265+
AddPoints(task_points);
266+
// // Enforce limits on points
267+
// const double max_points = sgp_config.SYM_HORIZ_TRANS_RES();
268+
// if (sym.GetPoints() > (1.5 * sgp_config.SYM_HORIZ_TRANS_RES())) {
269+
// sym.SetPoints(1.5 * sgp_config.SYM_HORIZ_TRANS_RES());
270+
// }
271+
}
272+
248273
/**
249274
* Input: emp::Ptr<Organism> to host offspring, emp::Ptr<Organism> to symbiont offspring
250275
*

source/sgp_mode/SGPWorld.cc

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -351,30 +351,13 @@ void SGPWorld::ProcessSymOutputBuffer(sgp_sym_t& sym) {
351351
// Track success
352352
++sym_task_successes[task_id];
353353

354-
// Calc base task value based on task environment, task requirements, and
355-
// symbiont's current point value.
356-
// NOTE - A little funky because task value might be a multiplier on
357-
// current sym points.
358-
// So, to get the value *added* by the task, we subtract original point value.
359354
double new_points = task_req_info.fun_calc_task_val(
360355
task_env,
361356
task_req_info,
362357
sym.GetPoints()
363358
);
364-
double task_points = new_points - sym.GetPoints();
365-
366-
//Parasitic Nutrient symbionts receieve less rewards from completing tasks to incentivize matching tasks with hosts
367-
if(sgp_config.ENABLE_NUTRIENT() && GetNutrientSymType() == nutrient_sym_mode_t::PARASITE){
368-
task_points *= sgp_config.PARASITE_BASE_TASK_VALUE_PROP();
369-
}
370-
371-
// Add earned task points to symbiont's point total
372-
sym.AddPoints(task_points);
373-
// // Enforce limits on points
374-
// const double max_points = sgp_config.SYM_HORIZ_TRANS_RES();
375-
// if (sym.GetPoints() > (1.5 * sgp_config.SYM_HORIZ_TRANS_RES())) {
376-
// sym.SetPoints(1.5 * sgp_config.SYM_HORIZ_TRANS_RES());
377-
// }
359+
360+
ApplySymOutputPoints(sym, new_points);
378361
}
379362
}
380363
}

source/sgp_mode/SGPWorld.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ class SGPWorld : public SymWorld {
102102
size_t /* task id */
103103
)>;
104104

105+
using fun_apply_sym_output_points_t = std::function<void(
106+
sgp_sym_t&,
107+
double /* total points of sym after task, in case of multiplier */
108+
)>;
109+
105110
// using fun_process_endosym_t = std::function<void(
106111
// sgp_sym_t&, /* endosymbiont */
107112
// const emp::WorldPosition&, /* sym pos */
@@ -428,6 +433,7 @@ class SGPWorld : public SymWorld {
428433
fun_calc_host_nutrient_interaction_t fun_calc_host_nutrient_interaction;
429434
fun_calc_sym_nutrient_interaction_t fun_calc_sym_nutrient_interaction;
430435
func_apply_host_points_t fun_apply_host_points;
436+
fun_apply_sym_output_points_t fun_apply_sym_output_points;
431437

432438
// NOTE - Don't love this being owned by the world.
433439
// Not sure of better alterative. Need to know this in InitializeState
@@ -615,6 +621,13 @@ class SGPWorld : public SymWorld {
615621
) {
616622
return 0.0;
617623
};
624+
625+
fun_apply_sym_output_points = [](
626+
sgp_sym_t& sym,
627+
double total_points
628+
) {
629+
sym.ApplyOutputPoints(total_points);
630+
};
618631
}
619632

620633
~SGPWorld() {
@@ -708,6 +721,17 @@ class SGPWorld : public SymWorld {
708721
fun_apply_host_points(host,task_value_before, task_id);
709722
}
710723

724+
void SetApplySymOutputPointsFunctor(fun_apply_sym_output_points_t func) {
725+
fun_apply_sym_output_points = func;
726+
}
727+
728+
void ApplySymOutputPoints(
729+
sgp_sym_t& sym,
730+
double total_points
731+
) {
732+
fun_apply_sym_output_points(sym, total_points);
733+
}
734+
711735
const emp::BitVector& GetSymTaskProfile(
712736
sgp_sym_t& sym
713737
) {

0 commit comments

Comments
 (0)