From 70ba8e4ad84ea5da1589a870e9b665e00e07875d Mon Sep 17 00:00:00 2001 From: "George G. Vega Yon" Date: Tue, 11 Jun 2024 23:09:28 -0600 Subject: [PATCH] Virus dist params detach from class --- epiworld.hpp | 184 +++++---------------- examples/00-hello-world/main.cpp | 6 +- include/epiworld/model-meat-print.hpp | 24 +-- include/epiworld/models/init-functions.hpp | 37 ++--- include/epiworld/virus-bones.hpp | 13 +- include/epiworld/virus-meat.hpp | 110 ++---------- 6 files changed, 89 insertions(+), 285 deletions(-) diff --git a/epiworld.hpp b/epiworld.hpp index 4f0e4d30..c42b1901 100644 --- a/epiworld.hpp +++ b/epiworld.hpp @@ -8834,26 +8834,10 @@ inline const Model & Model::print(bool lite) const if (i < n_viruses_model) { - if (virus->get_prevalence_as_proportion()) - { - - printf_epiworld( - " - %s (baseline prevalence: %.2f%%)\n", - virus->get_name().c_str(), - virus->get_prevalence() * 100.00 - ); - - } - else - { - - printf_epiworld( - " - %s (baseline prevalence: %i seeds)\n", - virus->get_name().c_str(), - static_cast(virus->get_prevalence()) - ); - - } + printf_epiworld( + " - %s\n", + virus->get_name().c_str() + ); } else { @@ -10020,18 +10004,20 @@ class Virus { epiworld_fast_int queue_removed = -99; ///< Change of state when agent is removed // Information about how distribution works - epiworld_double prevalence = 0.0; - bool prevalence_as_proportion = false; VirusToAgentFun dist_fun = nullptr; public: Virus( std::string name = "unknown virus", - epiworld_double prevalence = 0.0, - bool prevalence_as_proportion = false, VirusToAgentFun dist_fun = nullptr ); + Virus( + std::string name = "unknown virus", + epiworld_double prevalence = 0.0, + bool as_proportion = true + ); + void mutate(Model * model); void set_mutation(MutFun fun); @@ -10135,9 +10121,6 @@ class Virus { * @brief Get information about the prevalence of the virus */ ///@{ - epiworld_double get_prevalence() const; - void set_prevalence(epiworld_double prevalence, bool as_proportion); - bool get_prevalence_as_proportion() const; void distribute(Model * model); void set_dist_fun(VirusToAgentFun fun); ///@} @@ -10383,16 +10366,27 @@ inline VirusFun virus_fun_logit( template inline Virus::Virus( std::string name, - epiworld_double prevalence, - bool prevalence_as_proportion, VirusToAgentFun dist_fun ) { set_name(name); - - set_prevalence(prevalence, prevalence_as_proportion); set_dist_fun(dist_fun); } +template +inline Virus::Virus( + std::string name, + epiworld_double prevalence, + bool prevalence_as_proportion + ) { + set_name(name); + set_dist_fun( + distribute_virus_randomly( + prevalence, + prevalence_as_proportion + ) + ); +} + template inline void Virus::mutate( Model * model @@ -10995,38 +10989,6 @@ inline void Virus::print() const } -template -inline epiworld_double Virus::get_prevalence() const -{ - return prevalence; -} - -template -inline bool Virus::get_prevalence_as_proportion() const -{ - return prevalence_as_proportion; -} - -template -inline void Virus::set_prevalence( - epiworld_double preval, - bool as_proportion - ) -{ - - if (as_proportion) { - - if ((preval < 0.0) || (preval > 1.0)) - throw std::range_error( - "The prevalence should be between 0 and 1. " + - std::string("Got ") + std::to_string(preval) - ); - } - - prevalence = preval; - prevalence_as_proportion = as_proportion; -} - template inline void Virus::distribute(Model * model) { @@ -11036,65 +10998,6 @@ inline void Virus::distribute(Model * model) dist_fun(*this, model); - } else { - - // Figuring out how what agents are available - std::vector< size_t > idx; - for (const auto & agent: model->get_agents()) - if (agent.get_virus() == nullptr) - idx.push_back(agent.get_id()); - - // Picking how many - size_t n = model->size(); - int n_available = static_cast(idx.size()); - int n_to_sample; - if (prevalence_as_proportion) - { - n_to_sample = static_cast(std::floor(prevalence * n)); - - if (n_to_sample == static_cast(n)) - n_to_sample--; - } - else - { - n_to_sample = static_cast(prevalence); - } - - if (n_to_sample > n_available) - throw std::range_error( - "There are only " + std::to_string(n_available) + - " individuals with no virus in the population. " + - "Cannot add the virus to " + - std::to_string(n_to_sample) - ); - - auto & population = model->get_agents(); - for (int i = 0; i < n_to_sample; ++i) - { - - int loc = static_cast( - floor(model->runif() * (n_available--)) - ); - - // Correcting for possible overflow - if ((loc > 0) && (loc >= n_available)) - loc = n_available - 1; - - Agent & agent = population[idx[loc]]; - - // Adding action - agent.set_virus( - *this, - const_cast * >(model), - this->state_init, - this->queue_init - ); - - // Adjusting sample - std::swap(idx[loc], idx[n_available]); - - } - } } @@ -15821,13 +15724,12 @@ inline std::function*)> create_init_function_sir( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; @@ -15895,13 +15797,12 @@ inline std::function*)> create_init_function_sird( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; @@ -15973,13 +15874,12 @@ inline std::function*)> create_init_function_seir( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; @@ -16055,13 +15955,13 @@ inline std::function*)> create_init_function_seird( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; diff --git a/examples/00-hello-world/main.cpp b/examples/00-hello-world/main.cpp index c2336807..3bf5915c 100644 --- a/examples/00-hello-world/main.cpp +++ b/examples/00-hello-world/main.cpp @@ -17,7 +17,11 @@ int main() model.add_state("Removed"); // Adding the tool and virus - epiworld::Virus virus("covid 19", 50, false); + epiworld::Virus virus( + "covid 19", + distribute_virus_randomly(50, false) + ); + virus.set_post_immunity(1.0); virus.set_state(1,2,3); virus.set_prob_death(.01); diff --git a/include/epiworld/model-meat-print.hpp b/include/epiworld/model-meat-print.hpp index d429dfea..1d4d6bc0 100644 --- a/include/epiworld/model-meat-print.hpp +++ b/include/epiworld/model-meat-print.hpp @@ -157,26 +157,10 @@ inline const Model & Model::print(bool lite) const if (i < n_viruses_model) { - if (virus->get_prevalence_as_proportion()) - { - - printf_epiworld( - " - %s (baseline prevalence: %.2f%%)\n", - virus->get_name().c_str(), - virus->get_prevalence() * 100.00 - ); - - } - else - { - - printf_epiworld( - " - %s (baseline prevalence: %i seeds)\n", - virus->get_name().c_str(), - static_cast(virus->get_prevalence()) - ); - - } + printf_epiworld( + " - %s\n", + virus->get_name().c_str() + ); } else { diff --git a/include/epiworld/models/init-functions.hpp b/include/epiworld/models/init-functions.hpp index 136d45b0..1ac26c99 100644 --- a/include/epiworld/models/init-functions.hpp +++ b/include/epiworld/models/init-functions.hpp @@ -30,13 +30,12 @@ inline std::function*)> create_init_function_sir( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; @@ -104,13 +103,12 @@ inline std::function*)> create_init_function_sird( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; @@ -182,13 +180,12 @@ inline std::function*)> create_init_function_seir( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; @@ -264,13 +261,13 @@ inline std::function*)> create_init_function_seird( // Figuring out information about the viruses double tot = 0.0; double n = static_cast(model->size()); - for (const auto & virus: model->get_viruses()) + + for (const auto & agent: model->get_agents()) { - if (virus->get_prevalence_as_proportion()) - tot += virus->get_prevalence(); - else - tot += virus->get_prevalence() / n; + if (agent.get_virus() != nullptr) + tot += 1.0; } + tot /= n; // Putting the total into context double tot_left = 1.0 - tot; diff --git a/include/epiworld/virus-bones.hpp b/include/epiworld/virus-bones.hpp index d3014c5e..2209a861 100644 --- a/include/epiworld/virus-bones.hpp +++ b/include/epiworld/virus-bones.hpp @@ -55,18 +55,20 @@ class Virus { epiworld_fast_int queue_removed = -99; ///< Change of state when agent is removed // Information about how distribution works - epiworld_double prevalence = 0.0; - bool prevalence_as_proportion = false; VirusToAgentFun dist_fun = nullptr; public: Virus( std::string name = "unknown virus", - epiworld_double prevalence = 0.0, - bool prevalence_as_proportion = false, VirusToAgentFun dist_fun = nullptr ); + Virus( + std::string name = "unknown virus", + epiworld_double prevalence = 0.0, + bool as_proportion = true + ); + void mutate(Model * model); void set_mutation(MutFun fun); @@ -170,9 +172,6 @@ class Virus { * @brief Get information about the prevalence of the virus */ ///@{ - epiworld_double get_prevalence() const; - void set_prevalence(epiworld_double prevalence, bool as_proportion); - bool get_prevalence_as_proportion() const; void distribute(Model * model); void set_dist_fun(VirusToAgentFun fun); ///@} diff --git a/include/epiworld/virus-meat.hpp b/include/epiworld/virus-meat.hpp index 1270a6f0..95068e20 100644 --- a/include/epiworld/virus-meat.hpp +++ b/include/epiworld/virus-meat.hpp @@ -82,16 +82,27 @@ inline VirusFun virus_fun_logit( template inline Virus::Virus( std::string name, - epiworld_double prevalence, - bool prevalence_as_proportion, VirusToAgentFun dist_fun ) { set_name(name); - - set_prevalence(prevalence, prevalence_as_proportion); set_dist_fun(dist_fun); } +template +inline Virus::Virus( + std::string name, + epiworld_double prevalence, + bool prevalence_as_proportion + ) { + set_name(name); + set_dist_fun( + distribute_virus_randomly( + prevalence, + prevalence_as_proportion + ) + ); +} + template inline void Virus::mutate( Model * model @@ -694,38 +705,6 @@ inline void Virus::print() const } -template -inline epiworld_double Virus::get_prevalence() const -{ - return prevalence; -} - -template -inline bool Virus::get_prevalence_as_proportion() const -{ - return prevalence_as_proportion; -} - -template -inline void Virus::set_prevalence( - epiworld_double preval, - bool as_proportion - ) -{ - - if (as_proportion) { - - if ((preval < 0.0) || (preval > 1.0)) - throw std::range_error( - "The prevalence should be between 0 and 1. " + - std::string("Got ") + std::to_string(preval) - ); - } - - prevalence = preval; - prevalence_as_proportion = as_proportion; -} - template inline void Virus::distribute(Model * model) { @@ -735,65 +714,6 @@ inline void Virus::distribute(Model * model) dist_fun(*this, model); - } else { - - // Figuring out how what agents are available - std::vector< size_t > idx; - for (const auto & agent: model->get_agents()) - if (agent.get_virus() == nullptr) - idx.push_back(agent.get_id()); - - // Picking how many - size_t n = model->size(); - int n_available = static_cast(idx.size()); - int n_to_sample; - if (prevalence_as_proportion) - { - n_to_sample = static_cast(std::floor(prevalence * n)); - - if (n_to_sample == static_cast(n)) - n_to_sample--; - } - else - { - n_to_sample = static_cast(prevalence); - } - - if (n_to_sample > n_available) - throw std::range_error( - "There are only " + std::to_string(n_available) + - " individuals with no virus in the population. " + - "Cannot add the virus to " + - std::to_string(n_to_sample) - ); - - auto & population = model->get_agents(); - for (int i = 0; i < n_to_sample; ++i) - { - - int loc = static_cast( - floor(model->runif() * (n_available--)) - ); - - // Correcting for possible overflow - if ((loc > 0) && (loc >= n_available)) - loc = n_available - 1; - - Agent & agent = population[idx[loc]]; - - // Adding action - agent.set_virus( - *this, - const_cast * >(model), - this->state_init, - this->queue_init - ); - - // Adjusting sample - std::swap(idx[loc], idx[n_available]); - - } - } }