Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/catch/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
#include "../test/sgp_mode_test/functional_tests/SGPHost_Tasks.test.cc"
#include "../test/sgp_mode_test/functional_tests/SGPHost_Reproduce.test.cc"
#include "../test/sgp_mode_test/functional_tests/SGPHardware_Tasks.test.cc"

#include "../test/sgp_mode_test/functional_tests/SGPPhylogenies.test.cc"



Expand Down
86 changes: 67 additions & 19 deletions source/default_mode/SymWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class SymWorld : public emp::World<Organism> {
enum class SPATIAL_STRUCT_MODE { WELL_MIXED, GRID, LOAD };
static const std::unordered_map<std::string, SPATIAL_STRUCT_MODE> spatial_struct_mode_cfg_mapping;

enum class PHYLO_TAXON_TYPE { INTERACTION_VALUE_BINNED, INTERACTION_VALUE_EXACT, TAG, INDIVIDUAL };
enum class PHYLO_TAXON_TYPE { INTERACTION_VALUE_BINNED, INTERACTION_VALUE_EXACT, TAG, INDIVIDUAL, TASK_CYCLE_BINNED};
static const std::unordered_map<std::string, PHYLO_TAXON_TYPE> phylo_taxon_type_cfg_mapping;

enum class TAG_METRIC_TYPE { HAMMING, STREAK, HASH };
Expand Down Expand Up @@ -251,7 +251,14 @@ class SymWorld : public emp::World<Organism> {
*/
void SetupSpatialStructure_Load();

/**
* Purpose: Set up phylogeny taxon binning and data collection.
*/
void SetupPhylogenyTracking();

/**
* Purpose: Set up tag distance metrics.
*/
void SetupTagMatching();

public:
Expand All @@ -274,9 +281,6 @@ class SymWorld : public emp::World<Organism> {

emp_assert(!(my_config->TAG_MATCHING() && my_config->FREE_LIVING_SYMS()));

if (my_config->PHYLOGENY()) {
SetupPhylogenyTracking();
}
if (my_config->TAG_MATCHING()) {
SetupTagMatching();
}
Expand Down Expand Up @@ -651,13 +655,46 @@ class SymWorld : public emp::World<Organism> {
* Input: None
*
* Output: The standard function object that determines which bin hosts
* should belong to depending on their interaction value
* should belong to.
*
* Purpose: To classify hosts based on their interaction value.
* Purpose: To classify hosts.
*/
fun_calc_info_t GetCalcHostInfoFun() {
// NOTE: Probably don't want one of the taxon type modes defined separately from
// others?
virtual fun_calc_info_t GetCalcHostInfoFun() {
switch (phylo_taxon_type) {
case PHYLO_TAXON_TYPE::INTERACTION_VALUE_BINNED:
calc_host_info_fun = [&](Organism& org) {
const size_t num_phylo_bins = my_config->NUM_PHYLO_BINS();
// classify orgs into bins base on interaction values,
// inclusive of lower bound, exclusive of upper
const float size_of_bin = 2.0 / num_phylo_bins;
const double int_val = org.GetIntVal();
float prog = (int_val + 1);
prog = (prog/size_of_bin) + (0.0000000000001);
size_t bin = (size_t) prog;
if (bin >= num_phylo_bins) bin = num_phylo_bins - 1;
// bin = num_phylo_bins - (size_t)(bin >= num_phylo_bins);
return bin;
};
break;
case PHYLO_TAXON_TYPE::INTERACTION_VALUE_EXACT:
calc_host_info_fun = [&](Organism& org) {
return org.GetIntVal();
};
break;
case PHYLO_TAXON_TYPE::TAG:
calc_host_info_fun = [&](Organism& org) {
return org.GetTag().GetValue();
};
break;
case PHYLO_TAXON_TYPE::INDIVIDUAL:
calc_host_info_fun = [&](Organism& org) {
return (long unsigned) host_sys->GetNextID();
};
break;
default:
emp_error("Unimplemented phylogeny taxon type.");
break;
}
emp_assert(calc_host_info_fun);
return calc_host_info_fun;
}
Expand All @@ -666,18 +703,28 @@ class SymWorld : public emp::World<Organism> {
* Input: None
*
* Output: The standard function object that determines which bin symbionts
* should belong to depending on their interaction value
* should belong to.
*
* Purpose: To classify symbionts based on their interaction value.
* Purpose: To classify symbionts.
*/
fun_calc_info_t GetCalcSymInfoFun() {
emp_assert(calc_sym_info_fun);
// By default the sym info function is the same as the host one,
// but separating them allows us to change the sym info function
// to something else if we need to.
if (!calc_sym_info_fun) {
calc_sym_info_fun = GetCalcHostInfoFun();
virtual fun_calc_info_t GetCalcSymInfoFun() {
switch (phylo_taxon_type) {
// binning function is the same for hosts and symbionts for interaction value and tag phylogenies
case PHYLO_TAXON_TYPE::INTERACTION_VALUE_BINNED:
case PHYLO_TAXON_TYPE::INTERACTION_VALUE_EXACT:
case PHYLO_TAXON_TYPE::TAG:
calc_sym_info_fun = GetCalcHostInfoFun();
break;
case PHYLO_TAXON_TYPE::INDIVIDUAL:
calc_sym_info_fun = [&](Organism& org) {
return (long unsigned) sym_sys->GetNextID();
};
break;
default:
emp_error("Unimplemented phylogeny taxon type.");
break;
}
emp_assert(calc_sym_info_fun);
return calc_sym_info_fun;
}

Expand Down Expand Up @@ -1468,7 +1515,8 @@ const std::unordered_map<
{"interaction-value-binned", PHYLO_TAXON_TYPE::INTERACTION_VALUE_BINNED},
{"interaction-value-exact", PHYLO_TAXON_TYPE::INTERACTION_VALUE_EXACT},
{"tag", PHYLO_TAXON_TYPE::TAG},
{"individual", PHYLO_TAXON_TYPE::INDIVIDUAL}
{"individual", PHYLO_TAXON_TYPE::INDIVIDUAL},
{"task-cycle-binned", PHYLO_TAXON_TYPE::TASK_CYCLE_BINNED}
};

const std::unordered_map<
Expand Down
53 changes: 4 additions & 49 deletions source/default_mode/WorldSetup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ void SymWorld::Setup() {
SetupHosts(&POP_SIZE);
long unsigned int total_syms = POP_SIZE * start_moi;
SetupSymbionts(&total_syms);

if (my_config->PHYLOGENY()) {
SetupPhylogenyTracking();
}
}

void SymWorld::SetupSpatialStructure() {
Expand Down Expand Up @@ -169,55 +173,6 @@ void SymWorld::SetupPhylogenyTracking() {
cfg_taxon_type
);
phylo_taxon_type = phylo_taxon_type_cfg_mapping.at(cfg_taxon_type);
// NOTE: For now, hosts / symbionts share taxon type mode.
switch (phylo_taxon_type) {
case PHYLO_TAXON_TYPE::INTERACTION_VALUE_BINNED:
// NOTE: Moved this definition here to centralize where all of these modes are defined.
calc_host_info_fun = [&](Organism& org) {
const size_t num_phylo_bins = my_config->NUM_PHYLO_BINS();
// classify orgs into bins base on interaction values,
// inclusive of lower bound, exclusive of upper
const float size_of_bin = 2.0 / num_phylo_bins;
const double int_val = org.GetIntVal();
float prog = (int_val + 1);
prog = (prog/size_of_bin) + (0.0000000000001);
size_t bin = (size_t) prog;
if (bin >= num_phylo_bins) bin = num_phylo_bins - 1;
// bin = num_phylo_bins - (size_t)(bin >= num_phylo_bins);
return bin;
};
calc_sym_info_fun = calc_host_info_fun;
break;
case PHYLO_TAXON_TYPE::INTERACTION_VALUE_EXACT:
calc_host_info_fun = [&](Organism& org) {
return org.GetIntVal();
};
calc_sym_info_fun = [&](Organism& org) {
return org.GetIntVal();
};
break;
case PHYLO_TAXON_TYPE::TAG:
calc_host_info_fun = [&](Organism& org) {
return org.GetTag().GetValue();
};

calc_sym_info_fun = [&](Organism& org) {
return org.GetTag().GetValue();
};
break;
case PHYLO_TAXON_TYPE::INDIVIDUAL:
calc_host_info_fun = [&](Organism& org) {
return (long unsigned) host_sys->GetNextID();
};

calc_sym_info_fun = [&](Organism& org) {
return (long unsigned) sym_sys->GetNextID();
};
break;
default:
emp_error("Unimplemented phylogeny taxon type.");
break;
}

host_sys = emp::NewPtr<host_systematics_t>(GetCalcHostInfoFun());
sym_sys = emp::NewPtr<sym_systematics_t>(GetCalcSymInfoFun());
Expand Down
1 change: 1 addition & 0 deletions source/sgp_mode/SGPHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ class SGPHost : public Host {
auto& cpu_state = hardware.GetCPUState();

host_offspring->LineageLength(reproductions + 1);
offspring_cpu_state.SetParentCPUCyclesSinceRepro(cpu_state.GetCPUCyclesSinceRepro());
cpu_state.SetCPUCyclesSinceRepro(0);
offspring_cpu_state.SetCPUCyclesSinceRepro(0);
// Offspring needs to be given parent's (this) task profile
Expand Down
1 change: 1 addition & 0 deletions source/sgp_mode/SGPSymbiont.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ void ProcessOutputBuffer() {
auto& offspring_hw = sym_offspring->GetHardware();
auto& offspring_cpu_state = offspring_hw.GetCPUState();
auto& cpu_state = hardware.GetCPUState();
offspring_cpu_state.SetParentCPUCyclesSinceRepro(cpu_state.GetCPUCyclesSinceRepro());
// Offspring needs to be given parent's (this) task profile
offspring_cpu_state.SetParentTasksPerformed(
hardware.GetCPUState().GetTasksPerformed()
Expand Down
54 changes: 54 additions & 0 deletions source/sgp_mode/SGPWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,60 @@ class SGPWorld : public SymWorld {
*/
event_manager_t& GetEventManager() { return event_manager; }


/**
* Input: None
*
* Output: The standard function object that determines which bin hosts
* should belong to.
*
* Purpose: To classify hosts.
*/
fun_calc_info_t GetCalcHostInfoFun() override {
switch (phylo_taxon_type) {
case PHYLO_TAXON_TYPE::TASK_CYCLE_BINNED:
calc_host_info_fun = [&](Organism& org) {
return std::stod(
static_cast<sgp_host_t&>(org).GetHardware().GetCPUState().GetParentTasksPerformed().ToString() + "." +
std::to_string(static_cast<sgp_host_t&>(org).GetHardware().GetCPUState().GetParentCPUCyclesSinceRepro())
);
};
break;
default:
calc_host_info_fun = SymWorld::GetCalcHostInfoFun();
break;
}
emp_assert(calc_host_info_fun);
return calc_host_info_fun;
}

/**
* Input: None
*
* Output: The standard function object that determines which bin symbionts
* should belong to.
*
* Purpose: To classify symbionts.
*/
fun_calc_info_t GetCalcSymInfoFun() override {
switch (phylo_taxon_type) {
case PHYLO_TAXON_TYPE::TASK_CYCLE_BINNED:
calc_sym_info_fun = [&](Organism& org) {
return std::stod(
static_cast<sgp_sym_t&>(org).GetHardware().GetCPUState().GetParentTasksPerformed().ToString() + "." +
std::to_string(static_cast<sgp_sym_t&>(org).GetHardware().GetCPUState().GetParentCPUCyclesSinceRepro())
);
};
break;
default:
calc_sym_info_fun = SymWorld::GetCalcSymInfoFun();
break;
}
emp_assert(calc_sym_info_fun);
return calc_sym_info_fun;
}


/**
* Input: A host, a symbiont, the value of a task before applying nutrient interaction, and the task id.
* Output: The change in the points the host will gain from the task after the nutrient interaction.
Expand Down
5 changes: 5 additions & 0 deletions source/sgp_mode/SGPWorldSetup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ void SGPWorld::Setup() {
);
}

// Setup phylogeny tracking
if (my_config->PHYLOGENY()) {
SetupPhylogenyTracking();
}

SetupHosts(&POP_SIZE);
// NOTE - any way to clean this up a little? Or, add some explanatory comments.
long unsigned int total_syms = POP_SIZE * start_moi;
Expand Down
21 changes: 21 additions & 0 deletions source/sgp_mode/hardware/CPUState.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class CPUState {
// the queue. When the organism dies, its queue slot will be invalidated.
ReproInfo repro_info;
size_t cpu_cycles_since_repro = 0;
size_t parent_cpu_cycles_since_repro = 0;

emp::vector<size_t> jump_table;

Expand Down Expand Up @@ -568,6 +569,26 @@ class CPUState {
cpu_cycles_since_repro = value;
}

/**
* Input: None.
*
* Output: Size_t, number that the parent cycles since repro will be set to
*
* Purpose: Used to track parent cycles before reproduction
*/
size_t GetParentCPUCyclesSinceRepro() const { return parent_cpu_cycles_since_repro; }

/**
* Input: Size_t, the number that the parent cycles since repro will be set to
*
* Output: None.
*
* Purpose: Sets the number of parent cycles that occured before this organism was born
*/
void SetParentCPUCyclesSinceRepro(size_t value) {
parent_cpu_cycles_since_repro = value;
}

/**
* Input: None.
*
Expand Down
9 changes: 8 additions & 1 deletion source/test/default_mode_test/Phylogenies.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ TEST_CASE( "Host Phylogeny", "[default]" ) {
config.PHYLOGENY(1);
config.NUM_PHYLO_BINS(20);
config.PHYLOGENY_TAXON_TYPE("interaction-value-binned");
int int_val = 0;
int int_val = 0;
sym_world_t world(random, &config);
world.Setup();
int world_size = 4;
world.Resize(world_size);


emp::Ptr<Organism> host = emp::NewPtr<Host>(&random, &world, &config, int_val);
emp::Ptr<emp::Systematics<Organism, taxon_t::info_t, datastruct::HostTaxonData>> host_sys = world.GetHostSys();

Expand Down Expand Up @@ -152,6 +153,7 @@ TEST_CASE( "Symbiont Phylogeny", "[default]" ) {
sym_world_t world(random, &config);
int world_size = 20;
world.Resize(world_size);
world.SetupPhylogenyTracking();

emp::Ptr<emp::Systematics<Organism, taxon_t::info_t, datastruct::SymbiontTaxonData>> sym_sys = world.GetSymSys();

Expand Down Expand Up @@ -276,6 +278,7 @@ TEST_CASE("Interaction Tracking Phylogeny", "[default]") {
config.WORLD_WIDTH(grid_side);
config.WORLD_HEIGHT(grid_side);
world.SetupSpatialStructure();
world.SetupPhylogenyTracking();
emp::Ptr<emp::Systematics<Organism, taxon_t::info_t, datastruct::HostTaxonData>> host_sys = world.GetHostSys();
emp::Ptr<emp::Systematics<Organism, taxon_t::info_t, datastruct::SymbiontTaxonData>> sym_sys = world.GetSymSys();

Expand Down Expand Up @@ -374,6 +377,7 @@ TEST_CASE("Tag-based Phylogeny", "[default]") {

sym_world_t world(random, &config);
world.SetupSpatialStructure();
world.SetupPhylogenyTracking();

emp::HammingMetric<TAG_LENGTH> tag_metric = emp::HammingMetric<TAG_LENGTH>();

Expand Down Expand Up @@ -575,6 +579,7 @@ TEST_CASE("Individual-level phylogenies", "[default]") {
int int_val = 0;
int world_size = 10;
world.Resize(world_size);
world.SetupPhylogenyTracking();

WHEN("Free living symbionts reproduce and die") {
config.FREE_LIVING_SYMS(1);
Expand Down Expand Up @@ -853,6 +858,7 @@ TEST_CASE("Host switch counter", "[default]") {
int int_val = 0;
int world_size = 4;
world.Resize(world_size);
world.SetupPhylogenyTracking();

WHEN("A symbiont vertically transmits") {
config.VERTICAL_TRANSMISSION(1);
Expand Down Expand Up @@ -992,6 +998,7 @@ TEST_CASE("Unpruned phylogenies", "[default]") {
int int_val = 0;
int world_size = 5;
world.Resize(world_size);
world.SetupPhylogenyTracking();

// set up the lineages
emp::Ptr<Organism> host_grandparent = emp::NewPtr<Host>(&random, &world, &config, int_val);
Expand Down
Loading
Loading