diff --git a/epiworld.hpp b/epiworld.hpp index 4d4ad7f6..4f0e4d30 100644 --- a/epiworld.hpp +++ b/epiworld.hpp @@ -12169,8 +12169,6 @@ class Entity { epiworld_fast_int queue_init = 0; ///< Change of state when added to agent. epiworld_fast_int queue_post = 0; ///< Change of state when removed from agent. - epiworld_double prevalence = 0.0; - bool prevalence_as_proportion = false; EntityToAgentFun dist_fun = nullptr; public: @@ -12182,19 +12180,13 @@ class Entity { * This constructor initializes an Entity object with the specified parameters. * * @param name The name of the entity. - * @param preval The prevalence of the entity. - * @param as_proportion A flag indicating whether the prevalence is given as a proportion. * @param fun A function pointer to a function that maps the entity to an agent. */ Entity( std::string name, - epiworld_double preval, - bool as_proportion, EntityToAgentFun fun = nullptr ) : entity_name(name), - prevalence(preval), - prevalence_as_proportion(as_proportion), dist_fun(fun) {}; @@ -12238,10 +12230,6 @@ class Entity { std::vector< size_t > & get_agents(); void print() const; - - void set_prevalence(epiworld_double p, bool as_proportion); - epiworld_double get_prevalence() const noexcept; - bool get_prevalence_as_proportion() const noexcept; void set_dist_fun(EntityToAgentFun fun); }; @@ -12274,33 +12262,54 @@ template /** * Distributes an entity to unassigned agents in the model. * + * @param prevalence The proportion of agents to distribute the entity to. + * @param as_proportion Flag indicating whether the prevalence is a proportion + * @param to_unassigned Flag indicating whether to distribute the entity only + * to unassigned agents. * @return An EntityToAgentFun object that distributes the entity to unassigned * agents. */ -inline EntityToAgentFun distribute_entity_to_unassigned() +inline EntityToAgentFun distribute_entity_randomly( + epiworld_double prevalence, + bool as_proportion, + bool to_unassigned +) { - return [](Entity & e, Model * m) -> void { + return [prevalence, as_proportion, to_unassigned]( + Entity & e, Model * m + ) -> void { // Preparing the sampling space std::vector< size_t > idx; - for (const auto & a: m->get_agents()) - if (a.get_n_entities() == 0) + if (to_unassigned) + { + for (const auto & a: m->get_agents()) + if (a.get_n_entities() == 0) + idx.push_back(a.get_id()); + } + else + { + + for (const auto & a: m->get_agents()) idx.push_back(a.get_id()); + + } + size_t n = idx.size(); // Figuring out how many to sample int n_to_sample; - if (e.get_prevalence_as_proportion()) + if (as_proportion) { - n_to_sample = static_cast(std::floor(e.get_prevalence() * n)); + 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(e.get_prevalence()); + n_to_sample = static_cast(prevalence); if (n_to_sample > static_cast(n)) throw std::range_error("There are only " + std::to_string(n) + " individuals in the population. Cannot add the entity to " + @@ -12652,61 +12661,12 @@ template inline void Entity::distribute() { - // Starting first infection - int n = this->model->size(); - std::vector< size_t > idx(n); - if (dist_fun) { dist_fun(*this, model); } - else - { - - // Picking how many - int n_to_assign; - if (prevalence_as_proportion) - { - n_to_assign = static_cast(std::floor(prevalence * size())); - } - else - { - n_to_assign = static_cast(prevalence); - } - - if (n_to_assign > static_cast(model->size())) - throw std::range_error("There are only " + std::to_string(model->size()) + - " individuals in the population. Cannot add the entity to " + std::to_string(n_to_assign)); - - int n_left = n; - std::iota(idx.begin(), idx.end(), 0); - while ((n_to_assign > 0) && (n_left > 0)) - { - int loc = static_cast( - floor(model->runif() * n_left--) - ); - - // Correcting for possible overflow - if ((loc > 0) && (loc >= n_left)) - loc = n_left - 1; - - auto & agent = model->get_agent(idx[loc]); - - if (!agent.has_entity(id)) - { - agent.add_entity( - *this, this->model, this->state_init, this->queue_init - ); - n_to_assign--; - } - - std::swap(idx[loc], idx[n_left]); - - } - - } } @@ -12728,28 +12688,6 @@ inline void Entity::print() const ); } -template -inline void Entity::set_prevalence( - epiworld_double p, - bool as_proportion -) -{ - prevalence = p; - prevalence_as_proportion = as_proportion; -} - -template -inline epiworld_double Entity::get_prevalence() const noexcept -{ - return prevalence; -} - -template -inline bool Entity::get_prevalence_as_proportion() const noexcept -{ - return prevalence_as_proportion; -} - template inline void Entity::set_dist_fun(EntityToAgentFun fun) { diff --git a/examples/11-entities/main.cpp b/examples/11-entities/main.cpp index 369c6cc0..3d2902e2 100644 --- a/examples/11-entities/main.cpp +++ b/examples/11-entities/main.cpp @@ -38,9 +38,9 @@ int main() { ); // Creating three groups - Entity<> e1("Entity 1", 0.0, false, dist_factory<>(0, 3000)); - Entity<> e2("Entity 2", 0.0, false, dist_factory<>(3000, 6000)); - Entity<> e3("Entity 3", 0.0, false, dist_factory<>(6000, 10000)); + Entity<> e1("Entity 1", dist_factory<>(0, 3000)); + Entity<> e2("Entity 2", dist_factory<>(3000, 6000)); + Entity<> e3("Entity 3", dist_factory<>(6000, 10000)); model.add_entity(e1); model.add_entity(e2); diff --git a/include/epiworld/entity-bones.hpp b/include/epiworld/entity-bones.hpp index 49869bb2..79ed8d57 100644 --- a/include/epiworld/entity-bones.hpp +++ b/include/epiworld/entity-bones.hpp @@ -59,8 +59,6 @@ class Entity { epiworld_fast_int queue_init = 0; ///< Change of state when added to agent. epiworld_fast_int queue_post = 0; ///< Change of state when removed from agent. - epiworld_double prevalence = 0.0; - bool prevalence_as_proportion = false; EntityToAgentFun dist_fun = nullptr; public: @@ -72,19 +70,13 @@ class Entity { * This constructor initializes an Entity object with the specified parameters. * * @param name The name of the entity. - * @param preval The prevalence of the entity. - * @param as_proportion A flag indicating whether the prevalence is given as a proportion. * @param fun A function pointer to a function that maps the entity to an agent. */ Entity( std::string name, - epiworld_double preval, - bool as_proportion, EntityToAgentFun fun = nullptr ) : entity_name(name), - prevalence(preval), - prevalence_as_proportion(as_proportion), dist_fun(fun) {}; @@ -128,10 +120,6 @@ class Entity { std::vector< size_t > & get_agents(); void print() const; - - void set_prevalence(epiworld_double p, bool as_proportion); - epiworld_double get_prevalence() const noexcept; - bool get_prevalence_as_proportion() const noexcept; void set_dist_fun(EntityToAgentFun fun); }; diff --git a/include/epiworld/entity-distribute-meat.hpp b/include/epiworld/entity-distribute-meat.hpp index 613f8400..d589a368 100644 --- a/include/epiworld/entity-distribute-meat.hpp +++ b/include/epiworld/entity-distribute-meat.hpp @@ -6,33 +6,54 @@ template /** * Distributes an entity to unassigned agents in the model. * + * @param prevalence The proportion of agents to distribute the entity to. + * @param as_proportion Flag indicating whether the prevalence is a proportion + * @param to_unassigned Flag indicating whether to distribute the entity only + * to unassigned agents. * @return An EntityToAgentFun object that distributes the entity to unassigned * agents. */ -inline EntityToAgentFun distribute_entity_to_unassigned() +inline EntityToAgentFun distribute_entity_randomly( + epiworld_double prevalence, + bool as_proportion, + bool to_unassigned +) { - return [](Entity & e, Model * m) -> void { + return [prevalence, as_proportion, to_unassigned]( + Entity & e, Model * m + ) -> void { // Preparing the sampling space std::vector< size_t > idx; - for (const auto & a: m->get_agents()) - if (a.get_n_entities() == 0) + if (to_unassigned) + { + for (const auto & a: m->get_agents()) + if (a.get_n_entities() == 0) + idx.push_back(a.get_id()); + } + else + { + + for (const auto & a: m->get_agents()) idx.push_back(a.get_id()); + + } + size_t n = idx.size(); // Figuring out how many to sample int n_to_sample; - if (e.get_prevalence_as_proportion()) + if (as_proportion) { - n_to_sample = static_cast(std::floor(e.get_prevalence() * n)); + 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(e.get_prevalence()); + n_to_sample = static_cast(prevalence); if (n_to_sample > static_cast(n)) throw std::range_error("There are only " + std::to_string(n) + " individuals in the population. Cannot add the entity to " + diff --git a/include/epiworld/entity-meat.hpp b/include/epiworld/entity-meat.hpp index 020f33f8..33f7e6ac 100644 --- a/include/epiworld/entity-meat.hpp +++ b/include/epiworld/entity-meat.hpp @@ -230,61 +230,12 @@ template inline void Entity::distribute() { - // Starting first infection - int n = this->model->size(); - std::vector< size_t > idx(n); - if (dist_fun) { dist_fun(*this, model); } - else - { - - // Picking how many - int n_to_assign; - if (prevalence_as_proportion) - { - n_to_assign = static_cast(std::floor(prevalence * size())); - } - else - { - n_to_assign = static_cast(prevalence); - } - - if (n_to_assign > static_cast(model->size())) - throw std::range_error("There are only " + std::to_string(model->size()) + - " individuals in the population. Cannot add the entity to " + std::to_string(n_to_assign)); - - int n_left = n; - std::iota(idx.begin(), idx.end(), 0); - while ((n_to_assign > 0) && (n_left > 0)) - { - int loc = static_cast( - floor(model->runif() * n_left--) - ); - - // Correcting for possible overflow - if ((loc > 0) && (loc >= n_left)) - loc = n_left - 1; - - auto & agent = model->get_agent(idx[loc]); - - if (!agent.has_entity(id)) - { - agent.add_entity( - *this, this->model, this->state_init, this->queue_init - ); - n_to_assign--; - } - - std::swap(idx[loc], idx[n_left]); - - } - - } } @@ -306,28 +257,6 @@ inline void Entity::print() const ); } -template -inline void Entity::set_prevalence( - epiworld_double p, - bool as_proportion -) -{ - prevalence = p; - prevalence_as_proportion = as_proportion; -} - -template -inline epiworld_double Entity::get_prevalence() const noexcept -{ - return prevalence; -} - -template -inline bool Entity::get_prevalence_as_proportion() const noexcept -{ - return prevalence_as_proportion; -} - template inline void Entity::set_dist_fun(EntityToAgentFun fun) { diff --git a/tests/05-mixing.cpp b/tests/05-mixing.cpp index 467c1a0f..7d56f647 100644 --- a/tests/05-mixing.cpp +++ b/tests/05-mixing.cpp @@ -33,9 +33,9 @@ EPIWORLD_TEST_CASE("SEIRMixing", "[SEIR-mixing]") { model.add_virus(v1); // Creating three groups - Entity<> e1("Entity 1", 0.0, false, dist_factory<>(0, 3000)); - Entity<> e2("Entity 2", 0.0, false, dist_factory<>(3000, 6000)); - Entity<> e3("Entity 3", 0.0, false, dist_factory<>(6000, 10000)); + Entity<> e1("Entity 1", dist_factory<>(0, 3000)); + Entity<> e2("Entity 2", dist_factory<>(3000, 6000)); + Entity<> e3("Entity 3", dist_factory<>(6000, 10000)); model.add_entity(e1); model.add_entity(e2); @@ -131,13 +131,9 @@ EPIWORLD_TEST_CASE("SEIRMixing", "[SEIR-mixing]") { // If entities don't have a dist function, then it should be // OK - e1.set_dist_fun(nullptr); - e2.set_dist_fun(nullptr); - e3.set_dist_fun(nullptr); - - e1.set_prevalence(2000, false); - e2.set_prevalence(2000, false); - e3.set_prevalence(2000, false); + e1.set_dist_fun(distribute_entity_randomly<>(2000, false, true)); + e2.set_dist_fun(distribute_entity_randomly<>(2000, false, true)); + e3.set_dist_fun(distribute_entity_randomly<>(2000, false, true)); model.rm_entity(0); model.rm_entity(1); diff --git a/tests/06-mixing.cpp b/tests/06-mixing.cpp index 1afa0e1f..14980cde 100644 --- a/tests/06-mixing.cpp +++ b/tests/06-mixing.cpp @@ -34,9 +34,9 @@ EPIWORLD_TEST_CASE("SIRMixing", "[SIR-mixing]") { model.add_virus(v1); // Creating three groups - Entity<> e1("Entity 1", 0, false, dist_factory<>(0, 3000)); - Entity<> e2("Entity 2", 0, false, dist_factory<>(3000, 6000)); - Entity<> e3("Entity 3", 0, false, dist_factory<>(6000, 10000)); + Entity<> e1("Entity 1", dist_factory<>(0, 3000)); + Entity<> e2("Entity 2", dist_factory<>(3000, 6000)); + Entity<> e3("Entity 3", dist_factory<>(6000, 10000)); model.add_entity(e1); model.add_entity(e2); diff --git a/tests/07-entitifuns.cpp b/tests/07-entitifuns.cpp index 06728dc9..7e09def5 100644 --- a/tests/07-entitifuns.cpp +++ b/tests/07-entitifuns.cpp @@ -19,9 +19,9 @@ EPIWORLD_TEST_CASE("Entity member", "[Entity]") { ); // Generating two entities, 100 distribution - auto dfun = epiworld::distribute_entity_to_unassigned<>(); - Entity<> e1("Entity 1", 5000, false, dfun); - Entity<> e2("Entity 2", 5000, false, dfun); + auto dfun = epiworld::distribute_entity_randomly<>(5000, false, true); + Entity<> e1("Entity 1", dfun); + Entity<> e2("Entity 2", dfun); model.add_entity(e1); model.add_entity(e2); @@ -75,8 +75,8 @@ EPIWORLD_TEST_CASE("Entity member", "[Entity]") { 1.0/2.0// epiworld_double recovery_rate ); - Entity<> e3("Entity 3", n, false, nullptr); - Entity<> e4("Entity 4", n, false, nullptr); + Entity<> e3("Entity 3", distribute_entity_randomly<>(n, false, false)); + Entity<> e4("Entity 4", distribute_entity_randomly<>(n, false, false)); model2.add_entity(e3); model2.add_entity(e4); diff --git a/tests/08-mixing-entities.cpp b/tests/08-mixing-entities.cpp index 2f819a1f..8a6197a3 100644 --- a/tests/08-mixing-entities.cpp +++ b/tests/08-mixing-entities.cpp @@ -23,9 +23,9 @@ int main() ); // Creating three groups - Entity<> e1("Entity 1", 3000, false); - Entity<> e2("Entity 2", 3000, false); - Entity<> e3("Entity 3", 3000, false); + Entity<> e1("Entity 1", distribute_entity_randomly<>(n, false, true)); + Entity<> e2("Entity 2", distribute_entity_randomly<>(n, false, true)); + Entity<> e3("Entity 3", distribute_entity_randomly<>(n, false, true)); model.add_entity(e1); model.add_entity(e2);