From c273e358ab99b42b5eeb57359c36ad67affda221 Mon Sep 17 00:00:00 2001 From: jubicker <113909589+jubicker@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:02:37 +0200 Subject: [PATCH 1/5] add ActivityType as input for corresponding fcts --- cpp/benchmarks/abm.cpp | 4 +- cpp/examples/abm_history_object.cpp | 14 +- cpp/examples/abm_minimal.cpp | 14 +- cpp/examples/abm_parameter_study.cpp | 2 +- cpp/examples/graph_abm.cpp | 33 +-- cpp/models/abm/CMakeLists.txt | 1 + cpp/models/abm/activity_type.h | 51 ++++ cpp/models/abm/common_abm_loggers.h | 20 +- cpp/models/abm/household.cpp | 5 +- cpp/models/abm/location_type.h | 5 +- cpp/models/abm/mobility_data.h | 28 +-- cpp/models/abm/mobility_rules.cpp | 100 ++++---- cpp/models/abm/mobility_rules.h | 25 +- cpp/models/abm/model.cpp | 31 +-- cpp/models/abm/model.h | 58 +++-- cpp/models/abm/model_functions.cpp | 5 +- cpp/models/abm/model_functions.h | 5 +- cpp/models/abm/person.cpp | 32 +-- cpp/models/abm/person.h | 68 +++--- cpp/models/abm/trip_list.h | 14 +- cpp/models/graph_abm/graph_abm_mobility.h | 15 +- cpp/models/graph_abm/graph_abmodel.h | 18 +- cpp/tests/abm_helpers.cpp | 14 +- cpp/tests/abm_helpers.h | 8 +- cpp/tests/test_abm_infection.cpp | 4 +- cpp/tests/test_abm_location.cpp | 13 +- cpp/tests/test_abm_lockdown_rules.cpp | 67 +++--- cpp/tests/test_abm_masks.cpp | 16 +- cpp/tests/test_abm_mobility_rules.cpp | 160 +++++++------ cpp/tests/test_abm_model.cpp | 280 ++++++++++++---------- cpp/tests/test_abm_person.cpp | 93 +++---- cpp/tests/test_abm_simulation.cpp | 83 ++++--- cpp/tests/test_abm_testing_strategy.cpp | 91 +++---- cpp/tests/test_graph_abm.cpp | 70 +++--- 34 files changed, 798 insertions(+), 649 deletions(-) create mode 100644 cpp/models/abm/activity_type.h diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index 0a16c654d3..70e4f9e494 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -51,7 +51,7 @@ mio::abm::Simulation<> make_simulation(size_t num_persons, std::initializer_list //create other locations for (auto loc_type : - {mio::abm::LocationType::School, mio::abm::LocationType::Work, mio::abm::LocationType::SocialEvent, + {mio::abm::LocationType::School, mio::abm::LocationType::Work, mio::abm::LocationType::Recreation, mio::abm::LocationType::BasicsShop, mio::abm::LocationType::Hospital, mio::abm::LocationType::ICU}) { const auto num_locs = std::max(size_t(1), num_persons / 2'000); @@ -112,7 +112,7 @@ mio::abm::Simulation<> make_simulation(size_t num_persons, std::initializer_list }; model.get_testing_strategy().add_scheme( - {mio::abm::LocationType::School, mio::abm::LocationType::Work, mio::abm::LocationType::SocialEvent, + {mio::abm::LocationType::School, mio::abm::LocationType::Work, mio::abm::LocationType::Recreation, mio::abm::LocationType::Home}, mio::abm::TestingScheme(random_criteria(), mio::abm::days(3), mio::abm::TimePoint(0), mio::abm::TimePoint(0) + mio::abm::days(10), {}, 0.5)); diff --git a/cpp/examples/abm_history_object.cpp b/cpp/examples/abm_history_object.cpp index f4240e44fa..8176d0349c 100644 --- a/cpp/examples/abm_history_object.cpp +++ b/cpp/examples/abm_history_object.cpp @@ -110,7 +110,7 @@ int main() // Add one social event with 5 maximum contacts. // Maximum contacs limit the number of people that a person can infect while being at this location. - auto event = model.add_location(mio::abm::LocationType::SocialEvent); + auto event = model.add_location(mio::abm::LocationType::Recreation); model.get_location(event).get_infection_parameters().set(5); // Add hospital and ICU with 5 maximum contacs. auto hospital = model.add_location(mio::abm::LocationType::Hospital); @@ -155,17 +155,17 @@ int main() for (auto& person : model.get_persons()) { const auto pid = person.get_id(); //assign shop and event - model.assign_location(pid, event); - model.assign_location(pid, shop); + model.assign_location(pid, event, mio::abm::ActivityType::Recreation); + model.assign_location(pid, shop, mio::abm::ActivityType::BasicsShop); //assign hospital and ICU - model.assign_location(pid, hospital); - model.assign_location(pid, icu); + model.assign_location(pid, hospital, mio::abm::ActivityType::Hospital); + model.assign_location(pid, icu, mio::abm::ActivityType::ICU); //assign work/school to people depending on their age if (person.get_age() == age_group_5_to_14) { - model.assign_location(pid, school); + model.assign_location(pid, school, mio::abm::ActivityType::School); } if (person.get_age() == age_group_15_to_34 || person.get_age() == age_group_35_to_59) { - model.assign_location(pid, work); + model.assign_location(pid, work, mio::abm::ActivityType::Work); } } diff --git a/cpp/examples/abm_minimal.cpp b/cpp/examples/abm_minimal.cpp index 426526c120..13f4c2bd8f 100644 --- a/cpp/examples/abm_minimal.cpp +++ b/cpp/examples/abm_minimal.cpp @@ -79,7 +79,7 @@ int main() // Add one social event with 5 maximum contacts. // Maximum contacs limit the number of people that a person can infect while being at this location. - auto event = model.add_location(mio::abm::LocationType::SocialEvent); + auto event = model.add_location(mio::abm::LocationType::Recreation); model.get_location(event).get_infection_parameters().set(5); // Add hospital and ICU with 5 maximum contacs. auto hospital = model.add_location(mio::abm::LocationType::Hospital); @@ -131,17 +131,17 @@ int main() for (auto& person : model.get_persons()) { const auto id = person.get_id(); //assign shop and event - model.assign_location(id, event); - model.assign_location(id, shop); + model.assign_location(id, event, mio::abm::ActivityType::Recreation); + model.assign_location(id, shop, mio::abm::ActivityType::BasicsShop); //assign hospital and ICU - model.assign_location(id, hospital); - model.assign_location(id, icu); + model.assign_location(id, hospital, mio::abm::ActivityType::Hospital); + model.assign_location(id, icu, mio::abm::ActivityType::ICU); //assign work/school to people depending on their age if (person.get_age() == age_group_5_to_14) { - model.assign_location(id, school); + model.assign_location(id, school, mio::abm::ActivityType::School); } if (person.get_age() == age_group_15_to_34 || person.get_age() == age_group_35_to_59) { - model.assign_location(id, work); + model.assign_location(id, work, mio::abm::ActivityType::Work); } } diff --git a/cpp/examples/abm_parameter_study.cpp b/cpp/examples/abm_parameter_study.cpp index e3cf55da0a..1f8627532a 100644 --- a/cpp/examples/abm_parameter_study.cpp +++ b/cpp/examples/abm_parameter_study.cpp @@ -91,7 +91,7 @@ mio::abm::Model make_model(const mio::RandomNumberGenerator& rng) // Add one social event with 5 maximum contacts. // Maximum contacts limit the number of people that a person can infect while being at this location. - auto event = model.add_location(mio::abm::LocationType::SocialEvent); + auto event = model.add_location(mio::abm::LocationType::Recreation); model.get_location(event).get_infection_parameters().set(5); // Add hospital and ICU with 5 maximum contacs. auto hospital = model.add_location(mio::abm::LocationType::Hospital); diff --git a/cpp/examples/graph_abm.cpp b/cpp/examples/graph_abm.cpp index 7050dc89a3..96b10f9316 100644 --- a/cpp/examples/graph_abm.cpp +++ b/cpp/examples/graph_abm.cpp @@ -18,6 +18,7 @@ * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/household.h" #include "abm/model.h" #include "abm/infection_state.h" @@ -167,7 +168,7 @@ int main() //Create locations for both models //model 1 - auto event_m1 = model1.add_location(mio::abm::LocationType::SocialEvent); + auto event_m1 = model1.add_location(mio::abm::LocationType::Recreation); model1.get_location(event_m1).get_infection_parameters().set(10); auto hospital_m1 = model1.add_location(mio::abm::LocationType::Hospital); model1.get_location(hospital_m1).get_infection_parameters().set(10); @@ -180,7 +181,7 @@ int main() auto work_m1 = model1.add_location(mio::abm::LocationType::Work); model1.get_location(work_m1).get_infection_parameters().set(10); //model 2 - auto event_m2 = model2.add_location(mio::abm::LocationType::SocialEvent); + auto event_m2 = model2.add_location(mio::abm::LocationType::Recreation); model2.get_location(event_m2).get_infection_parameters().set(10); auto hospital_m2 = model2.add_location(mio::abm::LocationType::Hospital); model2.get_location(hospital_m2).get_infection_parameters().set(10); @@ -206,22 +207,22 @@ int main() person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), model1.parameters, start_date, infection_state)); } - person.set_assigned_location(mio::abm::LocationType::SocialEvent, event_m1, model1.get_id()); - person.set_assigned_location(mio::abm::LocationType::BasicsShop, shop_m1, model1.get_id()); - person.set_assigned_location(mio::abm::LocationType::Hospital, hospital_m1, model1.get_id()); - person.set_assigned_location(mio::abm::LocationType::ICU, icu_m1, model1.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Recreation, event_m1, model1.get_id()); + person.set_assigned_location(mio::abm::ActivityType::BasicsShop, shop_m1, model1.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Hospital, hospital_m1, model1.get_id()); + person.set_assigned_location(mio::abm::ActivityType::ICU, icu_m1, model1.get_id()); if (person.get_age() == age_group_children) { - person.set_assigned_location(mio::abm::LocationType::School, school_m1, model1.get_id()); + person.set_assigned_location(mio::abm::ActivityType::School, school_m1, model1.get_id()); } if (person.get_age() == age_group_adults) { //10% of adults in model 1 work in model 2 size_t work_model = mio::DiscreteDistribution::get_instance()(mio::thread_local_rng(), std::vector{0.9, 0.1}); if (work_model == 1) { //person works in other model - person.set_assigned_location(mio::abm::LocationType::Work, work_m2, model2.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Work, work_m2, model2.get_id()); } else { //person works in same model - person.set_assigned_location(mio::abm::LocationType::Work, work_m1, model1.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Work, work_m1, model1.get_id()); } } } @@ -236,22 +237,22 @@ int main() person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), model2.parameters, start_date, infection_state)); } - person.set_assigned_location(mio::abm::LocationType::SocialEvent, event_m2, model2.get_id()); - person.set_assigned_location(mio::abm::LocationType::BasicsShop, shop_m2, model2.get_id()); - person.set_assigned_location(mio::abm::LocationType::Hospital, hospital_m2, model2.get_id()); - person.set_assigned_location(mio::abm::LocationType::ICU, icu_m2, model2.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Recreation, event_m2, model2.get_id()); + person.set_assigned_location(mio::abm::ActivityType::BasicsShop, shop_m2, model2.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Hospital, hospital_m2, model2.get_id()); + person.set_assigned_location(mio::abm::ActivityType::ICU, icu_m2, model2.get_id()); if (person.get_age() == age_group_children) { - person.set_assigned_location(mio::abm::LocationType::School, school_m2, model2.get_id()); + person.set_assigned_location(mio::abm::ActivityType::School, school_m2, model2.get_id()); } if (person.get_age() == age_group_adults) { //20% of adults in model 2 work in model 1 size_t work_model = mio::DiscreteDistribution::get_instance()(mio::thread_local_rng(), std::vector{0.2, 0.8}); if (work_model == 1) { //person works in same model - person.set_assigned_location(mio::abm::LocationType::Work, work_m2, model2.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Work, work_m2, model2.get_id()); } else { //person works in other model - person.set_assigned_location(mio::abm::LocationType::Work, work_m1, model1.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Work, work_m1, model1.get_id()); } } } diff --git a/cpp/models/abm/CMakeLists.txt b/cpp/models/abm/CMakeLists.txt index ae04b68b2d..28849159c2 100644 --- a/cpp/models/abm/CMakeLists.txt +++ b/cpp/models/abm/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(abm model.cpp model.h location_type.h + activity_type.h parameters.h parameters.cpp mobility_rules.cpp diff --git a/cpp/models/abm/activity_type.h b/cpp/models/abm/activity_type.h new file mode 100644 index 0000000000..891e50e51c --- /dev/null +++ b/cpp/models/abm/activity_type.h @@ -0,0 +1,51 @@ +/* +* Copyright (C) 2020-2026 MEmilio +* +* Authors: Julia Bicker +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef MIO_ABM_ACTIVITY_TYPE_H +#define MIO_ABM_ACTIVITY_TYPE_H + +#include + +namespace mio +{ +namespace abm +{ + +/** + * @brief Type of an Activity. This is used to determine the type of an Activity that a Person does at a Location. It is similar to LocationType, but is not necessarily the same as Persons can do different activities at the same location e.g. "Work" and "School" at a Location of LocationType "School". + */ +enum class ActivityType : std::uint32_t +{ + Home = 0, + School, + Work, + Recreation, // TODO: differentiate different kinds + BasicsShop, // groceries and other necessities + Hospital, + ICU, + Cemetery, // Location for all the dead persons. It is created once for the Model. + + Count, //last! + Invalid +}; + +} // namespace abm +} // namespace mio + +#endif diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index 0d91c69c24..d7d75c92f5 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -57,21 +57,21 @@ constexpr mio::abm::ActivityType guess_activity_type(mio::abm::LocationType curr case mio::abm::LocationType::Home: return mio::abm::ActivityType::Home; case mio::abm::LocationType::Work: - return mio::abm::ActivityType::Workplace; + return mio::abm::ActivityType::Work; case mio::abm::LocationType::School: - return mio::abm::ActivityType::Education; - case mio::abm::LocationType::SocialEvent: - return mio::abm::ActivityType::Leisure; + return mio::abm::ActivityType::School; + case mio::abm::LocationType::Recreation: + return mio::abm::ActivityType::Recreation; case mio::abm::LocationType::BasicsShop: - return mio::abm::ActivityType::Shopping; + return mio::abm::ActivityType::BasicsShop; case mio::abm::LocationType::ICU: - return mio::abm::ActivityType::OtherActivity; + return mio::abm::ActivityType::ICU; case mio::abm::LocationType::Hospital: - return mio::abm::ActivityType::OtherActivity; + return mio::abm::ActivityType::Hospital; case mio::abm::LocationType::Cemetery: - return mio::abm::ActivityType::OtherActivity; + return mio::abm::ActivityType::Cemetery; default: - return mio::abm::ActivityType::UnknownActivity; + return mio::abm::ActivityType::Home; } } @@ -126,7 +126,7 @@ struct LogPersonInformation : mio::LogOnce { person_information.reserve(sim.get_model().get_persons().size()); for (auto& person : sim.get_model().get_persons()) { person_information.push_back(std::make_tuple( - person.get_id(), sim.get_model().find_location(mio::abm::LocationType::Home, person.get_id()), + person.get_id(), sim.get_model().find_locations(mio::abm::ActivityType::Home, person.get_id())[0], person.get_age())); } return person_information; diff --git a/cpp/models/abm/household.cpp b/cpp/models/abm/household.cpp index e234aaff58..984f483358 100755 --- a/cpp/models/abm/household.cpp +++ b/cpp/models/abm/household.cpp @@ -19,6 +19,7 @@ */ #include "abm/household.h" +#include "abm/activity_type.h" #include "abm/person_id.h" #include "abm/location.h" #include "memilio/utils/random_number_generator.h" @@ -69,8 +70,8 @@ void add_household_to_model(Model& model, const Household& household) std::tie(member, count) = memberTouple; for (int j = 0; j < count; j++) { auto age_group = pick_age_group_from_age_distribution(model.get_rng(), member.get_age_weights()); - auto person = model.add_person(home, age_group); - model.assign_location(person, home); + auto person = model.add_person(home, age_group, ActivityType::Home); + model.assign_location(person, home, ActivityType::Home); } } } diff --git a/cpp/models/abm/location_type.h b/cpp/models/abm/location_type.h index 93b601c438..8f146cadbd 100644 --- a/cpp/models/abm/location_type.h +++ b/cpp/models/abm/location_type.h @@ -34,8 +34,9 @@ enum class LocationType : std::uint32_t { Home = 0, School, - Work, - SocialEvent, // TODO: differentiate different kinds + Office, + Work, // other workplaces than offices, e.g. factories + Recreation, // TODO: differentiate different kinds BasicsShop, // groceries and other necessities Hospital, ICU, diff --git a/cpp/models/abm/mobility_data.h b/cpp/models/abm/mobility_data.h index a192589d2a..0d19d46a52 100644 --- a/cpp/models/abm/mobility_data.h +++ b/cpp/models/abm/mobility_data.h @@ -43,20 +43,20 @@ enum class TransportMode : uint32_t Count //last!! }; -/** - * @brief Type of the activity. - */ -enum class ActivityType : uint32_t -{ - Workplace, - Education, - Shopping, - Leisure, - PrivateMatters, - OtherActivity, - Home, - UnknownActivity -}; +// /** +// * @brief Type of the activity. +// */ +// enum class ActivityType : uint32_t +// { +// Workplace, +// Education, +// Shopping, +// Leisure, +// PrivateMatters, +// OtherActivity, +// Home, +// UnknownActivity +// }; } // namespace abm } // namespace mio diff --git a/cpp/models/abm/mobility_rules.cpp b/cpp/models/abm/mobility_rules.cpp index 60d1946c5d..29f223a618 100644 --- a/cpp/models/abm/mobility_rules.cpp +++ b/cpp/models/abm/mobility_rules.cpp @@ -18,6 +18,7 @@ * limitations under the License. */ #include "abm/mobility_rules.h" +#include "abm/activity_type.h" #include "abm/person.h" #include "abm/random_events.h" #include "abm/location_type.h" @@ -28,151 +29,150 @@ namespace mio namespace abm { -LocationType random_mobility(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, +ActivityType random_mobility(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); auto make_transition = [current_loc](auto l) { return std::make_pair(l, l == current_loc ? 0. : 1.); }; if (t < params.get()) { return random_transition(rng, current_loc, dt, - {make_transition(LocationType::Work), make_transition(LocationType::Home), - make_transition(LocationType::School), make_transition(LocationType::SocialEvent), - make_transition(LocationType::BasicsShop)}); + {make_transition(ActivityType::Work), make_transition(ActivityType::Home), + make_transition(ActivityType::School), make_transition(ActivityType::Recreation), + make_transition(ActivityType::BasicsShop)}); } return current_loc; } -LocationType go_to_school(PersonalRandomNumberGenerator& /*rng*/, const Person& person, TimePoint t, TimeSpan dt, +ActivityType go_to_school(PersonalRandomNumberGenerator& /*rng*/, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); - if (current_loc == LocationType::Home && t < params.get() && t.day_of_week() < 5 && + if (current_loc == ActivityType::Home && t < params.get() && t.day_of_week() < 5 && person.get_go_to_school_time(params) >= t.time_since_midnight() && person.get_go_to_school_time(params) < t.time_since_midnight() + dt && params.get()[person.get_age()] && person.goes_to_school(t, params) && !person.is_in_quarantine(t, params)) { - return LocationType::School; + return ActivityType::School; } //return home - if (current_loc == LocationType::School && t.hour_of_day() >= 15) { - return LocationType::Home; + if (current_loc == ActivityType::School && t.hour_of_day() >= 15) { + return ActivityType::Home; } return current_loc; } -LocationType go_to_work(PersonalRandomNumberGenerator& /*rng*/, const Person& person, TimePoint t, TimeSpan dt, +ActivityType go_to_work(PersonalRandomNumberGenerator& /*rng*/, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); - if (current_loc == LocationType::Home && t < params.get() && + if (current_loc == ActivityType::Home && t < params.get() && params.get()[person.get_age()] && t.day_of_week() < 5 && t.time_since_midnight() + dt > person.get_go_to_work_time(params) && t.time_since_midnight() <= person.get_go_to_work_time(params) && person.goes_to_work(t, params) && !person.is_in_quarantine(t, params)) { - return LocationType::Work; + return ActivityType::Work; } //return home - if (current_loc == LocationType::Work && t.hour_of_day() >= 17) { - return LocationType::Home; + if (current_loc == ActivityType::Work && t.hour_of_day() >= 17) { + return ActivityType::Home; } return current_loc; } -LocationType go_to_shop(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, +ActivityType go_to_shop(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); //leave - if (t.day_of_week() < 6 && t.hour_of_day() > 7 && t.hour_of_day() < 22 && current_loc == LocationType::Home && + if (t.day_of_week() < 6 && t.hour_of_day() > 7 && t.hour_of_day() < 22 && current_loc == ActivityType::Home && !person.is_in_quarantine(t, params)) { return random_transition(rng, current_loc, dt, - {{LocationType::BasicsShop, params.get()[person.get_age()]}}); + {{ActivityType::BasicsShop, params.get()[person.get_age()]}}); } //return home - if (current_loc == LocationType::BasicsShop && person.get_time_at_location() >= hours(1)) { - return LocationType::Home; + if (current_loc == ActivityType::BasicsShop && person.get_time_at_location() >= hours(1)) { + return ActivityType::Home; } return current_loc; } -LocationType go_to_event(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, - const Parameters& params) +ActivityType go_to_recreation(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, + const Parameters& params) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); //leave - if (current_loc == LocationType::Home && t < params.get() && + if (current_loc == ActivityType::Home && t < params.get() && ((t.day_of_week() <= 4 && t.hour_of_day() >= 19 && t.hour_of_day() < 22) || (t.day_of_week() >= 5 && t.hour_of_day() >= 10 && t.hour_of_day() < 22)) && !person.is_in_quarantine(t, params)) { return random_transition( rng, current_loc, dt, - {{LocationType::SocialEvent, params.get().get_matrix_at( - SimulationTime(t.days()))[(size_t)person.get_age()]}}); + {{ActivityType::Recreation, params.get().get_matrix_at( + SimulationTime(t.days()))[(size_t)person.get_age()]}}); } //return home - if (current_loc == LocationType::SocialEvent && t.hour_of_day() >= 20 && - person.get_time_at_location() >= hours(2)) { - return LocationType::Home; + if (current_loc == ActivityType::Recreation && t.hour_of_day() >= 20 && person.get_time_at_location() >= hours(2)) { + return ActivityType::Home; } return current_loc; } -LocationType go_to_quarantine(PersonalRandomNumberGenerator& /*rng*/, const Person& person, TimePoint t, +ActivityType go_to_quarantine(PersonalRandomNumberGenerator& /*rng*/, const Person& person, TimePoint t, TimeSpan /*dt*/, const Parameters& params) { - auto current_loc = person.get_location_type(); - if (person.is_in_quarantine(t, params) && current_loc != LocationType::Hospital && - current_loc != LocationType::ICU) { - return LocationType::Home; + auto current_loc = person.get_activity_type(); + if (person.is_in_quarantine(t, params) && current_loc != ActivityType::Hospital && + current_loc != ActivityType::ICU) { + return ActivityType::Home; } return current_loc; } -LocationType go_to_hospital(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, +ActivityType go_to_hospital(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, TimeSpan /*dt*/, const Parameters& /*params*/) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); if (person.get_infection_state(t) == InfectionState::InfectedSevere) { - return LocationType::Hospital; + return ActivityType::Hospital; } return current_loc; } -LocationType go_to_icu(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, TimeSpan /*dt*/, +ActivityType go_to_icu(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, TimeSpan /*dt*/, const Parameters& /*params*/) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); if (person.get_infection_state(t) == InfectionState::InfectedCritical) { - return LocationType::ICU; + return ActivityType::ICU; } return current_loc; } -LocationType return_home_when_recovered(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, +ActivityType return_home_when_recovered(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, TimeSpan /*dt*/, const Parameters& /*params*/) { - auto current_loc = person.get_location_type(); - if ((current_loc == LocationType::Hospital || current_loc == LocationType::ICU) && + auto current_loc = person.get_activity_type(); + if ((current_loc == ActivityType::Hospital || current_loc == ActivityType::ICU) && person.get_infection_state(t) == InfectionState::Recovered) { - return LocationType::Home; + return ActivityType::Home; } return current_loc; } -LocationType get_buried(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, +ActivityType get_buried(PersonalRandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, TimeSpan /*dt*/, const Parameters& /*params*/) { - auto current_loc = person.get_location_type(); + auto current_loc = person.get_activity_type(); if (person.get_infection_state(t) == InfectionState::Dead) { - return LocationType::Cemetery; + return ActivityType::Cemetery; } return current_loc; } diff --git a/cpp/models/abm/mobility_rules.h b/cpp/models/abm/mobility_rules.h index 98dd9e250e..a531d3de04 100644 --- a/cpp/models/abm/mobility_rules.h +++ b/cpp/models/abm/mobility_rules.h @@ -20,7 +20,8 @@ #ifndef MIO_ABM_MOBILITY_RULES_H #define MIO_ABM_MOBILITY_RULES_H -#include "abm/location_type.h" +#include "abm/activity_type.h" +#include "abm/activity_type.h" #include "abm/parameters.h" #include "abm/time.h" #include "abm/person.h" @@ -45,61 +46,61 @@ namespace abm /** * @brief Completely random mobility to any other Location. */ -LocationType random_mobility(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, +ActivityType random_mobility(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, const Parameters& params); /** * @brief School age children go to school in the morning and return later in the day. */ -LocationType go_to_school(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, +ActivityType go_to_school(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, const Parameters& params); /** * @brief Adults may go shopping in their free time. */ -LocationType go_to_shop(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, +ActivityType go_to_shop(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params); /** * @brief Person%s might go to social events. */ -LocationType go_to_event(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, - const Parameters& params); +ActivityType go_to_recreation(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, + const Parameters& params); /** * @brief Adults go to work in the morning and return later in the day. */ -LocationType go_to_work(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, +ActivityType go_to_work(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params); /** * @brief Person%s who are in quarantine should go home. */ -LocationType go_to_quarantine(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint /*t*/, +ActivityType go_to_quarantine(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint /*t*/, TimeSpan /*dt*/, const Parameters& /*params*/); /** * @brief Infected Person%s may be hospitalized. */ -LocationType go_to_hospital(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, +ActivityType go_to_hospital(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, const Parameters& params); /** * @brief Person%s in the hospital may be put in intensive care. */ -LocationType go_to_icu(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, +ActivityType go_to_icu(PersonalRandomNumberGenerator& rng, const Person& p, TimePoint t, TimeSpan dt, const Parameters& params); /** * @brief Person%s in the hospital/icu return home when they recover. */ -LocationType return_home_when_recovered(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, +ActivityType return_home_when_recovered(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params); /** * @brief Person%s in the icu go to cemetery when they are dead. */ -LocationType get_buried(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, +ActivityType get_buried(PersonalRandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params); /**@}*/ diff --git a/cpp/models/abm/model.cpp b/cpp/models/abm/model.cpp index a886edde98..bee1f134fd 100755 --- a/cpp/models/abm/model.cpp +++ b/cpp/models/abm/model.cpp @@ -18,6 +18,7 @@ * limitations under the License. */ #include "abm/model.h" +#include "abm/activity_type.h" #include "abm/location_id.h" #include "abm/location_type.h" #include "abm/intervention_type.h" @@ -52,10 +53,10 @@ LocationId Model::add_location(LocationType type, uint32_t num_cells) return id; } -PersonId Model::add_person(const LocationId id, AgeGroup age) +PersonId Model::add_person(const LocationId id, AgeGroup age, ActivityType activity_type) { PersonId person_id = (static_cast(m_id)) << 32 | static_cast(m_persons.size()); - return add_person(Person(m_rng, get_location(id).get_type(), id, m_id, age, person_id)); + return add_person(Person(m_rng, get_location(id).get_type(), activity_type, id, m_id, age, person_id)); } PersonId Model::add_person(Person&& person) @@ -65,7 +66,7 @@ PersonId Model::add_person(Person&& person) "Added Person's location is not in Model."); assert(person.get_id() != PersonId::invalid_ID() && "Added Person's unique id must be valid."); assert(person.get_age() < (AgeGroup)parameters.get_num_groups() && "Added Person's AgeGroup is too large."); - person.set_assigned_location(LocationType::Cemetery, m_cemetery_id, m_id); + person.set_assigned_location(ActivityType::Cemetery, m_cemetery_id, m_id); m_persons.emplace_back(person); m_activeness_statuses.push_back(true); auto& new_person = m_persons.back(); @@ -113,8 +114,9 @@ void Model::perform_mobility(TimePoint t, TimeSpan dt) auto try_mobility_rule = [&](auto rule) -> bool { // run mobility rule and check if change of location can actually happen auto target_type = rule(personal_rng, person, t, dt, parameters); - if (person.get_assigned_location_model_id(target_type) == m_id) { - const Location& target_location = get_location(find_location(target_type, person)); + auto target = person.get_assigned_location(target_type, personal_rng); + if (target.second == m_id) { + const Location& target_location = get_location(target.first); const LocationId current_location = person.get_location(); // the Person cannot move if they do not wear mask as required at targeted location @@ -127,11 +129,10 @@ void Model::perform_mobility(TimePoint t, TimeSpan dt) get_number_persons(target_location.get_id()) >= target_location.get_capacity().persons) { return false; } - // The person cannot move if he has a positive test result, except he want to go to a hospital, ICU or home. + // The person cannot move if he has a positive test result, except he want to go to a hospital, ICU (as a patient) or home. if (!m_testing_strategy.run_and_check(personal_rng, person, target_location, t) && - target_location.get_type() != LocationType::Hospital && - target_location.get_type() != LocationType::ICU && - target_location.get_type() != LocationType::Home) { + target_type != ActivityType::Hospital && target_type != ActivityType::ICU && + target_type != ActivityType::Home) { return false; } @@ -147,7 +148,7 @@ void Model::perform_mobility(TimePoint t, TimeSpan dt) person.set_mask(MaskType::None, t); } // all requirements are met, move to target location - change_location(person, target_location.get_id()); + change_location(person, target_location.get_id(), target_type); return true; } return false; @@ -163,8 +164,8 @@ void Model::perform_mobility(TimePoint t, TimeSpan dt) (has_locations({LocationType::School, LocationType::Home}) && try_mobility_rule(&go_to_school)) || (has_locations({LocationType::Work, LocationType::Home}) && try_mobility_rule(&go_to_work)) || (has_locations({LocationType::BasicsShop, LocationType::Home}) && try_mobility_rule(&go_to_shop)) || - (has_locations({LocationType::SocialEvent, LocationType::Home}) && - try_mobility_rule(&go_to_event)) || + (has_locations({LocationType::Recreation, LocationType::Home}) && + try_mobility_rule(&go_to_recreation)) || (has_locations({LocationType::Home}) && try_mobility_rule(&go_to_quarantine)); } else { @@ -203,7 +204,7 @@ void Model::perform_mobility(TimePoint t, TimeSpan dt) continue; } // all requirements are met, move to target location - change_location(person, target_location.get_id(), trip.trip_mode); + change_location(person, target_location.get_id(), trip.activity, trip.trip_mode); // update worn mask to target location's requirements if (target_location.is_mask_required()) { // if the current MaskProtection level is lower than required, the Person changes mask @@ -373,9 +374,9 @@ auto Model::get_activeness_statuses() -> Range return {m_activeness_statuses}; } -LocationId Model::find_location(LocationType type, const PersonId person) const +std::vector Model::find_locations(ActivityType type, const PersonId person) const { - return find_location(type, get_person(person)); + return find_locations(type, get_person(person)); } size_t Model::get_subpopulation_combined(TimePoint t, InfectionState s) const diff --git a/cpp/models/abm/model.h b/cpp/models/abm/model.h index 90fff62025..b2250aa3c5 100644 --- a/cpp/models/abm/model.h +++ b/cpp/models/abm/model.h @@ -20,6 +20,7 @@ #ifndef MIO_ABM_MODEL_H #define MIO_ABM_MODEL_H +#include "abm/activity_type.h" #include "abm/infection_state.h" #include "abm/model_functions.h" #include "abm/location_type.h" @@ -38,6 +39,7 @@ #include "memilio/utils/stl_util.h" #include +#include #include #include @@ -59,8 +61,8 @@ class Model using ConstPersonIterator = std::vector::const_iterator; using ActivenessIterator = std::vector::iterator; using ConstActivenessIterator = std::vector::const_iterator; - using MobilityRuleType = LocationType (*)(PersonalRandomNumberGenerator&, const Person&, TimePoint, TimeSpan, - const Parameters&); + using MobilityRuleType = ActivityType (*)(PersonalRandomNumberGenerator&, const Person&, TimePoint, TimeSpan, + const Parameters&); using Compartments = mio::abm::InfectionState; /** @@ -203,9 +205,10 @@ class Model * @brief Add a Person to the Model. * @param[in] id The LocationID of the initial Location of the Person. * @param[in] age AgeGroup of the person. + * @param[in] activity_type The ActivityType the Person does at its initial Location. * @return Id of the newly created Person. */ - PersonId add_person(const LocationId id, AgeGroup age); + PersonId add_person(const LocationId id, AgeGroup age, ActivityType activity_type); /** * @brief Adds a copy of a given Person to the Model. @@ -242,12 +245,12 @@ class Model /** @} */ /** - * @brief Find an assigned Location of a Person. - * @param[in] type The #LocationType that specifies the assigned Location. + * @brief Find an all assigned Locations of a Person for a certain ActivityType. + * @param[in] type The ActivityType that specifies the assigned Locations. * @param[in] person Id of the Person. - * @return ID of the Location of LocationType type assigend to person. + * @return IDs of the Locations of ActivityType type assigend to person. */ - LocationId find_location(LocationType type, const PersonId person) const; + std::vector find_locations(ActivityType type, const PersonId person) const; /** * @brief Assign a Location to a Person. @@ -255,10 +258,11 @@ class Model * Assigning another Location of an already assigned LocationType will replace the prior assignment. * @param[in] person The Id of the person this location will be assigned to. * @param[in] location The LocationId of the Location. + * @param[in] activity The ActivityType the person does at the Location. */ - void assign_location(PersonId person, LocationId location) + void assign_location(PersonId person, LocationId location, ActivityType activity) { - assign_location(get_person(person), location); + assign_location(get_person(person), location, activity); } /** @@ -445,10 +449,10 @@ class Model * @param[in] mode The transport mode the person uses to change the Location. * @param[in] cells The cells within the destination the person should be in. */ - inline void change_location(PersonId person, LocationId destination, TransportMode mode = TransportMode::Unknown, - const std::vector& cells = {0}) + inline void change_location(PersonId person, LocationId destination, ActivityType activity, + TransportMode mode = TransportMode::Unknown, const std::vector& cells = {0}) { - change_location(get_person(person), destination, mode, cells); + change_location(get_person(person), destination, activity, mode, cells); } /** @@ -481,10 +485,11 @@ class Model * Assigning another Location of an already assigned LocationType will replace the prior assignment. * @param[in] person reference to the Person the location will be assigned to. * @param[in] location The LocationId of the Location. + * @param[in] activity The ActivityType the person does at the Location. */ - void assign_location(Person& person, LocationId location) + void assign_location(Person& person, LocationId location, ActivityType activity) { - person.set_assigned_location(get_location(location).get_type(), location, m_id); + person.set_assigned_location(activity, location, m_id); } Location& get_location(LocationId id) @@ -570,12 +575,13 @@ class Model * @param[in] mode The transport mode the person uses to change the Location. * @param[in] cells The cells within the destination the person should be in. */ - inline void change_location(Person& person, LocationId destination, TransportMode mode = TransportMode::Unknown, - const std::vector& cells = {0}) + inline void change_location(Person& person, LocationId destination, ActivityType activity, + TransportMode mode = TransportMode::Unknown, const std::vector& cells = {0}) { - LocationId origin = get_location(person).get_id(); - auto old_cells = person.get_cells(); - const bool has_changed_location = mio::abm::change_location(person, get_location(destination), mode, cells); + LocationId origin = get_location(person).get_id(); + auto old_cells = person.get_cells(); + const bool has_changed_location = + mio::abm::change_location(person, get_location(destination), activity, mode, cells); // if the person has changed location, invalidate exposure caches but keep population caches valid if (has_changed_location) { m_are_exposure_caches_valid = false; @@ -611,16 +617,16 @@ class Model } /** - * @brief Find an assigned Location of a Person. - * @param[in] type The #LocationType that specifies the assigned Location. + * @brief Find an assigned Locations of a Person. + * @param[in] type The ActivityType that specifies the assigned Locations. * @param[in] person Reference to Person. - * @return ID of the Location of LocationType type assigend to person. + * @return IDs of the Locations of ActivityType type assigend to person. */ - LocationId find_location(LocationType type, const Person& person) const + std::vector find_locations(ActivityType type, const Person& person) const { - auto location_id = person.get_assigned_location(type); - assert(location_id != LocationId::invalid_id() && "The person has no assigned location of that type."); - return location_id; + auto location_ids = person.get_assigned_locations()[static_cast(type)]; + assert(!location_ids.empty() && "The person has no assigned location of that type."); + return location_ids; } /** diff --git a/cpp/models/abm/model_functions.cpp b/cpp/models/abm/model_functions.cpp index 7529590521..c56f30bf39 100644 --- a/cpp/models/abm/model_functions.cpp +++ b/cpp/models/abm/model_functions.cpp @@ -19,6 +19,7 @@ */ #include "abm/model_functions.h" +#include "abm/activity_type.h" #include "abm/location.h" #include "abm/person.h" #include "abm/random_events.h" @@ -159,7 +160,7 @@ void normalize_exposure_contribution(ContactExposureRates& local_contact_exposur } } -bool change_location(Person& person, const Location& destination, const TransportMode mode, +bool change_location(Person& person, const Location& destination, ActivityType activity, const TransportMode mode, const std::vector& cells) { assert(std::all_of(cells.begin(), cells.end(), [&](const auto& cell) { @@ -167,7 +168,7 @@ bool change_location(Person& person, const Location& destination, const Transpor })); // make sure cell indices are valid if (person.get_location() != destination.get_id()) { - person.set_location(destination.get_type(), destination.get_id(), destination.get_model_id()); + person.set_location(activity, destination.get_type(), destination.get_id(), destination.get_model_id()); person.get_cells() = cells; person.set_last_transport_mode(mode); diff --git a/cpp/models/abm/model_functions.h b/cpp/models/abm/model_functions.h index 3b0bdbf462..e8bc2d5710 100644 --- a/cpp/models/abm/model_functions.h +++ b/cpp/models/abm/model_functions.h @@ -101,12 +101,13 @@ void interact(PersonalRandomNumberGenerator& personal_rng, Person& person, const * If the person already is at the destination, neither mode nor cells are set. * @param[in, out] person The person to change location. * @param[in] destination The destination to change location to. + * @param[in] activity The ActivityType the person does at the destination. * @param[in] mode The transport mode the person uses to change location. * @param[in] cells The cells within the destination the person should be in. * @return Returns false if the person already is at the given destination, true otherwise. */ -bool change_location(Person& person, const Location& destination, const TransportMode mode = TransportMode::Unknown, - const std::vector& cells = {0}); +bool change_location(Person& person, const Location& destination, ActivityType activity, + const TransportMode mode = TransportMode::Unknown, const std::vector& cells = {0}); /** * @brief Adjust ContactRates of location by MaximumContacts. diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index 19a66aec99..765e0f3db0 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -18,6 +18,7 @@ * limitations under the License. */ #include "abm/person.h" +#include "abm/activity_type.h" #include "abm/location_type.h" #include "abm/mask_type.h" #include "abm/parameters.h" @@ -25,6 +26,7 @@ #include "abm/location.h" #include "abm/person_id.h" #include "memilio/utils/random_number_generator.h" +#include #include #include @@ -33,12 +35,13 @@ namespace mio namespace abm { -Person::Person(mio::RandomNumberGenerator& rng, LocationType location_type, LocationId location_id, - int location_model_id, AgeGroup age, PersonId person_id) +Person::Person(mio::RandomNumberGenerator& rng, LocationType location_type, ActivityType activity_type, + LocationId location_id, int location_model_id, AgeGroup age, PersonId person_id) : m_location(location_id) , m_location_type(location_type) + , m_activity_type(activity_type) , m_location_model_id(location_model_id) - , m_assigned_locations((uint32_t)LocationType::Count, LocationId::invalid_id()) + , m_assigned_locations((uint32_t)ActivityType::Count) , m_home_isolation_start(TimePoint(-(std::numeric_limits::max() / 2))) , m_age(age) , m_time_at_location(0) @@ -95,10 +98,11 @@ LocationId Person::get_location() const return m_location; } -void Person::set_location(LocationType type, LocationId id, int model_id) +void Person::set_location(ActivityType type, LocationType location_type, LocationId id, int model_id) { m_location = id; - m_location_type = type; + m_location_type = location_type; + m_activity_type = type; m_location_model_id = model_id; m_time_at_location = TimeSpan(0); } @@ -113,20 +117,18 @@ Infection& Person::get_infection() return m_infections.back(); } -void Person::set_assigned_location(LocationType type, LocationId id, int model_id = 0) +void Person::set_assigned_location(ActivityType type, LocationId id, int model_id = 0) { - m_assigned_locations[static_cast(type)] = id; - m_assigned_location_model_ids[static_cast(type)] = model_id; + m_assigned_locations[static_cast(type)].push_back(id); + m_assigned_location_model_ids[static_cast(type)].push_back(model_id); } -LocationId Person::get_assigned_location(LocationType type) const +std::pair Person::get_assigned_location(ActivityType type, PersonalRandomNumberGenerator& rng) const { - return m_assigned_locations[static_cast(type)]; -} - -int Person::get_assigned_location_model_id(LocationType type) const -{ - return m_assigned_location_model_ids[static_cast(type)]; + size_t index = UniformIntDistribution::get_instance()( + rng, size_t(0), m_assigned_locations[static_cast(type)].size() - 1); + return {m_assigned_locations[static_cast(type)][index], + m_assigned_location_model_ids[static_cast(type)][index]}; } bool Person::goes_to_work(TimePoint t, const Parameters& params) const diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index e1cea60230..c799974528 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -24,6 +24,7 @@ #include "abm/infection_state.h" #include "abm/location_id.h" #include "abm/location_type.h" +#include "abm/activity_type.h" #include "abm/parameters.h" #include "abm/person_id.h" #include "abm/personal_rng.h" @@ -57,8 +58,9 @@ class Person * @param[in] person_index Index of the Person. * */ - explicit Person(mio::RandomNumberGenerator& rng, LocationType location_type, LocationId location_id, - int location_model_id, AgeGroup age, PersonId person_id = PersonId::invalid_ID()); + explicit Person(mio::RandomNumberGenerator& rng, LocationType location_type, ActivityType activity_type, + LocationId location_id, int location_model_id, AgeGroup age, + PersonId person_id = PersonId::invalid_ID()); explicit Person(const Person& other, PersonId person_id); @@ -128,11 +130,27 @@ class Person */ LocationId get_location() const; + /** + * @brief Get the LocationType of the current Location of the Person. + * @return LocationType of the current Location of the Person. + */ LocationType get_location_type() const { return m_location_type; } + /** + * @brief Get the ActivityType the Person does at its current Location. + * @return ActivityType of the current Location of the Person. + */ + ActivityType get_activity_type() const + { + return m_activity_type; + } + + /** + * @brief Get the model id of the current Location of the Person. Only used for Graph ABM. + */ int get_location_model_id() const { return m_location_model_id; @@ -140,11 +158,12 @@ class Person /** * @brief Change the location of the person. - * @param[in] type The LocationType of the new Location. + * @param[in] type The ActivityType the Person does at the new Location. + * @param[in] location_type The LocationType of the new Location. * @param[in] id The LocationId of the new Location. * @param[in] model_id The model id of the new Location. */ - void set_location(LocationType type, LocationId id, int model_id); + void set_location(ActivityType type, LocationType location_type, LocationId id, int model_id); /** * @brief Get the time the Person has been at its current Location. @@ -170,44 +189,35 @@ class Person * Important: Setting incorrect values will cause issues during simulation. It is preferable to use * Model::assign_location with a valid LocationId, obtained e.g. through Model::add_location. * - * The assigned Location is saved by the index of its LocationId. Assume that a Person has at most one assigned - * Location of a certain #LocationType. - * @param[in] type The LocationType of the Location. + * The assigned Location is saved by the index of its LocationId. + * @param[in] type The ActivityType the Person does at the Location. * @param[in] id The LocationId of the Location. * @param[in] model_id The model id of the Location. */ - void set_assigned_location(LocationType type, LocationId id, int model_id); + void set_assigned_location(ActivityType type, LocationId id, int model_id); /** - * @brief Returns the index of an assigned Location of the Person. - * Assume that a Person has at most one assigned Location of a certain #LocationType. - * @param[in] type #LocationType of the assigned Location. - * @return The index in the LocationId of the assigned Location. + * @brief Returns the index of an assigned Location of the Person. The index is uniformly sampled from the LocationIds of the assigned ActivityType. + * @param[in] type #ActivityType of the assigned Location. + * @param[in] rng RandomNumberGenerator for sampling the index of the assigned LocationId. + * @return The index in the LocationId and the model id of the assigned Location. */ - LocationId get_assigned_location(LocationType type) const; + std::pair get_assigned_location(ActivityType type, PersonalRandomNumberGenerator& rng) const; /** * @brief Get the assigned Location%s of the Person. * @return A vector with the indices of the assigned Location%s of the Person. */ - const std::vector& get_assigned_locations() const + const std::vector>& get_assigned_locations() const { return m_assigned_locations; } - /** - * @brief Returns the model id of an assigned location of the Person. - * Assume that a Person has at most one assigned Location of a certain #LocationType. - * @param[in] type #LocationType of the assigned Location. - * @return The model id of the assigned Location. - */ - int get_assigned_location_model_id(LocationType type) const; - /** * @brief Get the assigned locations' model ids of the Person. * @return A vector with the model ids of the assigned locations of the Person */ - const std::vector& get_assigned_location_model_ids() const + const std::vector>& get_assigned_location_model_ids() const { return m_assigned_location_model_ids; } @@ -446,9 +456,11 @@ class Person private: LocationId m_location; ///< Current Location of the Person. - LocationType m_location_type; ///< Type of the current Location. + LocationType m_location_type; ///< LocationType of the current Location. + ActivityType m_activity_type; ///< ActivityType the Person does at the current Location. int m_location_model_id; ///< Model id of the current Location. Only used for Graph ABM. - std::vector m_assigned_locations; /**! Vector with the indices of the assigned Locations so that the + std::vector> + m_assigned_locations; /**! Vector with the indices of the assigned Locations so that the Person always visits the same Home or School etc. */ std::vector m_vaccinations; ///< Vector with all vaccinations the Person has received. std::vector m_infections; ///< Vector with all Infection%s the Person had. @@ -467,7 +479,7 @@ class Person std::vector m_cells; ///< Vector with all Cell%s the Person visits at its current Location. mio::abm::TransportMode m_last_transport_mode; ///< TransportMode the Person used to get to its current Location. CustomIndexArray m_test_results; ///< CustomIndexArray for TestResults. - std::vector + std::vector> m_assigned_location_model_ids; ///< Vector with model ids of the assigned locations. Only used in graph abm. PersonId m_person_id; ///< Unique identifier of a person. Counter m_rng_counter{0}; ///< counter for RandomNumberGenerator. @@ -480,8 +492,8 @@ template <> struct DefaultFactory { static abm::Person create() { - return abm::Person(thread_local_rng(), abm::LocationType::Count, abm::LocationId(), 0, AgeGroup(0), - abm::PersonId()); + return abm::Person(thread_local_rng(), abm::LocationType::Count, abm::ActivityType::Count, abm::LocationId(), 0, + AgeGroup(0), abm::PersonId()); } }; diff --git a/cpp/models/abm/trip_list.h b/cpp/models/abm/trip_list.h index 0ffc03d93d..f244db7c67 100644 --- a/cpp/models/abm/trip_list.h +++ b/cpp/models/abm/trip_list.h @@ -20,6 +20,7 @@ #ifndef MIO_ABM_TRIP_LIST_H #define MIO_ABM_TRIP_LIST_H +#include "abm/activity_type.h" #include "abm/location_id.h" #include "abm/mobility_data.h" #include "abm/person.h" @@ -44,6 +45,7 @@ struct Trip { Model, where all Person%s are saved.*/ TimePoint trip_time; ///< Daytime at which a Person changes the Location. LocationId destination; ///< Location where the Person changes to. + ActivityType activity; ///< Activity the person does at the destination location. int destination_model_id; ///< Model id of destination Location. TransportMode trip_mode; ///< Mode of transportation. See TransportMode for all possible modes of transportation. std::vector cells; /**< If destination consists of different Cell%s, this gives the index of the @@ -54,17 +56,19 @@ struct Trip { * @param[in] id ID of the Person that makes the Trip. * @param[in] time Time at which a Person changes the Location this currently cant be set for s specific day just a timepoint in a day. * @param[in] destination Location where the Person changes to. - * @param[in] destination_model_id Model the Person changes to. + * @param[in] actvty Activity the person does at the destination location. + * @param[in] dest_model_id Model the Person changes to. * @param[in] origin Location where the person starts the Trip. * @param[in] origin_model_id Model the Person starts the Trip. * @param[in] input_cells The index of the Cell%s the Person changes to. */ - Trip(PersonId id, const TimePoint time, const LocationId dest, const int dest_model_id = 0, + Trip(PersonId id, const TimePoint time, const LocationId dest, ActivityType actvty, const int dest_model_id = 0, const TransportMode mode_of_transport = mio::abm::TransportMode::Unknown, const std::vector& input_cells = {}) : person_id(id) , trip_time(mio::abm::TimePoint(time.time_since_midnight().seconds())) , destination(dest) + , activity(actvty) , destination_model_id(dest_model_id) , trip_mode(mode_of_transport) , cells(input_cells) @@ -78,7 +82,8 @@ struct Trip { bool operator==(const Trip& other) const { return (person_id == other.person_id) && (trip_time == other.trip_time) && (destination == other.destination) && - (destination_model_id == other.destination_model_id) && (trip_mode == other.trip_mode); + (activity == other.activity) && (destination_model_id == other.destination_model_id) && + (trip_mode == other.trip_mode); } auto default_serialize() @@ -87,6 +92,7 @@ struct Trip { .add("person_id", person_id) .add("trip_time", trip_time) .add("destination", destination) + .add("activity", activity) .add("model_id", destination_model_id) .add("trip_mode", trip_mode); } @@ -173,7 +179,7 @@ template <> struct DefaultFactory { static abm::Trip create() { - return abm::Trip{abm::PersonId{}, abm::TimePoint{}, abm::LocationId{}}; + return abm::Trip{abm::PersonId{}, abm::TimePoint{}, abm::LocationId{}, abm::ActivityType::Count}; } }; diff --git a/cpp/models/graph_abm/graph_abm_mobility.h b/cpp/models/graph_abm/graph_abm_mobility.h index 99e6e78050..f4b8e62218 100644 --- a/cpp/models/graph_abm/graph_abm_mobility.h +++ b/cpp/models/graph_abm/graph_abm_mobility.h @@ -123,15 +123,14 @@ class ABMMobilityEdge std::sort(persons_to_change.begin(), persons_to_change.end()); //iterate over all persons that change from node_from for (int i = int(persons_to_change.size()) - 1; i >= 0; --i) { - auto& person = model_from.get_persons()[persons_to_change[i]]; - auto target_type = person.get_location_type(); - if (target_type == abm::LocationType::Invalid) { - target_type = model_to.get_location(person.get_location()).get_type(); - } + auto& person = model_from.get_persons()[persons_to_change[i]]; //check if Person uses this edge - if (person.get_assigned_location_model_id(target_type) == model_to.get_id()) { - - auto target_id = person.get_assigned_location(target_type); + if (person.get_location_model_id() == model_to.get_id()) { + auto target_id = person.get_location(); + auto target_type = person.get_location_type(); + if (target_type == abm::LocationType::Invalid) { + target_type = model_to.get_location(target_id).get_type(); + } //set correct location for person person.set_location(target_type, target_id, model_to.get_id()); //add person to model_to diff --git a/cpp/models/graph_abm/graph_abmodel.h b/cpp/models/graph_abm/graph_abmodel.h index 7ea9b799a5..7835bcc369 100644 --- a/cpp/models/graph_abm/graph_abmodel.h +++ b/cpp/models/graph_abm/graph_abmodel.h @@ -21,6 +21,7 @@ #ifndef MIO_ABM_GRAPH_ABMODEL_H #define MIO_ABM_GRAPH_ABMODEL_H +#include "abm/activity_type.h" #include "abm/location_type.h" #include "abm/model.h" #include "abm/person_id.h" @@ -48,7 +49,7 @@ class GraphABModel : public abm::Model std::vector mobility_rules = std::vector{&get_buried, &return_home_when_recovered, &go_to_hospital, &go_to_icu, &go_to_school, &go_to_work, &go_to_shop, - &go_to_event, &go_to_quarantine}) + &go_to_recreation, &go_to_quarantine}) : Base(num_agegroups, id) { Base::m_mobility_rules = mobility_rules; @@ -99,8 +100,9 @@ class GraphABModel : public abm::Model auto try_mobility_rule = [&](auto rule) -> bool { //run mobility rule and check if change of location can actually happen auto target_type = rule(personal_rng, person, t, dt, parameters); - if (person.get_assigned_location_model_id(target_type) == Base::m_id) { - const Location& target_location = Base::get_location(Base::find_location(target_type, person)); + auto target = person.get_assigned_location(target_type, personal_rng); + if (target.second == Base::m_id) { + const Location& target_location = Base::get_location(target.first); const LocationId current_location = person.get_location(); // the Person cannot move if they do not wear mask as required at targeted location if (target_location.is_mask_required() && @@ -127,13 +129,12 @@ class GraphABModel : public abm::Model else { person.set_mask(MaskType::None, t); } - Base::change_location(person, target_location.get_id()); + Base::change_location(person, target_location.get_id(), target_type); return true; } else { //person moves to other world Base::m_activeness_statuses[person_index] = false; - person.set_location(target_type, abm::LocationId::invalid_id(), - std::numeric_limits::max()); + person.set_location(target_type, abm::LocationType::Invalid, target.first, target.second); m_person_buffer.push_back(person_index); m_are_exposure_caches_valid = false; m_is_local_population_cache_valid = false; @@ -176,7 +177,7 @@ class GraphABModel : public abm::Model continue; } // all requirements are met, move to target location - change_location(person, target_location.get_id(), trip.trip_mode); + change_location(person, target_location.get_id(), trip.activity, trip.trip_mode); // update worn mask to target location's requirements if (target_location.is_mask_required()) { // if the current MaskProtection level is lower than required, the Person changes mask @@ -191,7 +192,8 @@ class GraphABModel : public abm::Model } else { //person moves to other world Base::m_activeness_statuses[person_index] = false; - person.set_location(abm::LocationType::Invalid, trip.destination, std::numeric_limits::max()); + person.set_location(trip.activity, abm::LocationType::Invalid, trip.destination, + trip.destination_model_id); m_person_buffer.push_back(person_index); m_are_exposure_caches_valid = false; m_is_local_population_cache_valid = false; diff --git a/cpp/tests/abm_helpers.cpp b/cpp/tests/abm_helpers.cpp index bf9af22c29..2ca81defaa 100644 --- a/cpp/tests/abm_helpers.cpp +++ b/cpp/tests/abm_helpers.cpp @@ -18,16 +18,18 @@ * limitations under the License. */ #include "abm_helpers.h" +#include "abm/activity_type.h" #include "abm/person.h" #include "abm/person_id.h" #include "memilio/utils/random_number_generator.h" -mio::abm::Person make_test_person(mio::RandomNumberGenerator& rng, mio::abm::Location& location, mio::AgeGroup age, +mio::abm::Person make_test_person(mio::RandomNumberGenerator& rng, mio::abm::Location& location, + mio::abm::ActivityType actvty_type, mio::AgeGroup age, mio::abm::InfectionState infection_state, mio::abm::TimePoint t, mio::abm::Parameters params, mio::abm::PersonId id) { assert(age.get() < params.get_num_groups()); - mio::abm::Person p(rng, location.get_type(), location.get_id(), location.get_model_id(), age, id); + mio::abm::Person p(rng, location.get_type(), actvty_type, location.get_id(), location.get_model_id(), age, id); if (infection_state != mio::abm::InfectionState::Susceptible) { auto rng_p = mio::abm::PersonalRandomNumberGenerator(rng, p); p.add_new_infection( @@ -36,11 +38,13 @@ mio::abm::Person make_test_person(mio::RandomNumberGenerator& rng, mio::abm::Loc return p; } -mio::abm::PersonId add_test_person(mio::abm::Model& model, mio::abm::LocationId loc_id, mio::AgeGroup age, +mio::abm::PersonId add_test_person(mio::abm::Model& model, mio::abm::LocationId loc_id, + mio::abm::ActivityType actvty_type, mio::AgeGroup age, mio::abm::InfectionState infection_state, mio::abm::TimePoint t) { - return model.add_person(make_test_person(model.get_rng(), model.get_location(loc_id), age, infection_state, t, - model.parameters, static_cast(model.get_persons().size()))); + return model.add_person(make_test_person(model.get_rng(), model.get_location(loc_id), actvty_type, age, + infection_state, t, model.parameters, + static_cast(model.get_persons().size()))); } void interact_testing(mio::abm::PersonalRandomNumberGenerator& personal_rng, mio::abm::Person& person, diff --git a/cpp/tests/abm_helpers.h b/cpp/tests/abm_helpers.h index 808e8dc173..518102433e 100644 --- a/cpp/tests/abm_helpers.h +++ b/cpp/tests/abm_helpers.h @@ -20,6 +20,7 @@ #ifndef ABM_HELPERS_H #define ABM_HELPERS_H +#include "abm/activity_type.h" #include "abm/model.h" #include "abm/person_id.h" @@ -94,17 +95,18 @@ struct ScopedMockDistribution { * @brief Create a Person without a Model object. Intended for simple use in tests. */ mio::abm::Person make_test_person(mio::RandomNumberGenerator& rng, mio::abm::Location& location, - mio::AgeGroup age = age_group_15_to_34, + mio::abm::ActivityType actvty_type, mio::AgeGroup age = age_group_15_to_34, mio::abm::InfectionState infection_state = mio::abm::InfectionState::Susceptible, mio::abm::TimePoint t = mio::abm::TimePoint(0), mio::abm::Parameters params = mio::abm::Parameters(num_age_groups), - mio::abm::PersonId id = mio::abm::PersonId(0)); + + mio::abm::PersonId id = mio::abm::PersonId(0)); /** * @brief Add a Person to the Model. Intended for simple use in tests. */ mio::abm::PersonId add_test_person(mio::abm::Model& model, mio::abm::LocationId loc_id, - mio::AgeGroup age = age_group_15_to_34, + mio::abm::ActivityType actvty_type, mio::AgeGroup age = age_group_15_to_34, mio::abm::InfectionState infection_state = mio::abm::InfectionState::Susceptible, mio::abm::TimePoint t = mio::abm::TimePoint(0)); diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index f8c7650de5..2ca97c7b81 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -298,8 +298,8 @@ TEST_F(TestInfection, getPersonalProtectiveFactor) const ScalarType eps = 1e-4; auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); - auto person = mio::abm::Person(this->get_rng(), location.get_type(), location.get_id(), location.get_model_id(), - age_group_15_to_34); + auto person = mio::abm::Person(this->get_rng(), location.get_type(), mio::abm::ActivityType::School, + location.get_id(), location.get_model_id(), age_group_15_to_34); auto t0 = mio::abm::TimePoint(0); person.add_new_vaccination(mio::abm::ProtectionType::GenericVaccine, t0); auto latest_protection = person.get_latest_protection(t0); diff --git a/cpp/tests/test_abm_location.cpp b/cpp/tests/test_abm_location.cpp index 5e04ddc931..13b41b74f2 100644 --- a/cpp/tests/test_abm_location.cpp +++ b/cpp/tests/test_abm_location.cpp @@ -18,6 +18,7 @@ * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/location_id.h" #include "abm/parameters.h" #include "abm/person.h" @@ -102,11 +103,11 @@ TEST_F(TestLocation, interact) // Setup location with some chance of exposure mio::abm::Location location(mio::abm::LocationType::Work, 0, num_age_groups); location.get_infection_parameters().get() = true; - auto infected1 = make_test_person(this->get_rng(), location, age_group_15_to_34, + auto infected1 = make_test_person(this->get_rng(), location, mio::abm::ActivityType::Work, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, t, params); - auto infected2 = make_test_person(this->get_rng(), location, age_group_80_plus, + auto infected2 = make_test_person(this->get_rng(), location, mio::abm::ActivityType::Work, age_group_80_plus, mio::abm::InfectionState::InfectedSymptoms, t, params); - auto infected3 = make_test_person(this->get_rng(), location, age_group_5_to_14, + auto infected3 = make_test_person(this->get_rng(), location, mio::abm::ActivityType::Work, age_group_5_to_14, mio::abm::InfectionState::InfectedSymptoms, t, params); std::vector local_population{infected1, infected2, infected3}; @@ -115,8 +116,8 @@ TEST_F(TestLocation, interact) ScopedMockDistribution>>> mock_discrete_dist; // Create a susceptible person and test interaction. - auto susceptible = - make_test_person(this->get_rng(), location, age, mio::abm::InfectionState::Susceptible, t, params); + auto susceptible = make_test_person(this->get_rng(), location, mio::abm::ActivityType::Work, age, + mio::abm::InfectionState::Susceptible, t, params); EXPECT_CALL(mock_exponential_dist.get_mock(), invoke).Times(1).WillOnce(Return(0.5)); // Probability of no infection auto person_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), susceptible); interact_testing(person_rng, susceptible, location, local_population, t, dt, params); @@ -176,7 +177,7 @@ TEST_F(TestLocation, getGeographicalLocation) */ TEST_F(TestLocation, adjustContactRates) { - mio::abm::Location loc(mio::abm::LocationType::SocialEvent, mio::abm::LocationId(0)); + mio::abm::Location loc(mio::abm::LocationType::Recreation, mio::abm::LocationId(0)); //Set the maximum contacts smaller than the contact rates loc.get_infection_parameters().get() = 2; loc.get_infection_parameters().get().get_baseline()(0, 0) = 4; diff --git a/cpp/tests/test_abm_lockdown_rules.cpp b/cpp/tests/test_abm_lockdown_rules.cpp index a292fc9984..d0de9c3a22 100644 --- a/cpp/tests/test_abm_lockdown_rules.cpp +++ b/cpp/tests/test_abm_lockdown_rules.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/lockdown_rules.h" #include "abm/mobility_rules.h" #include "abm/person.h" @@ -52,12 +53,14 @@ TEST_F(TestLockdownRules, school_closure) .WillRepeatedly(testing::Return(1.0)); // Set up two people with assigned locations (home and school) - auto p1 = mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); - p1.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p1.set_assigned_location(school.get_type(), school.get_id(), school.get_model_id()); - auto p2 = mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); - p2.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p2.set_assigned_location(school.get_type(), school.get_id(), school.get_model_id()); + auto p1 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_5_to_14); + p1.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p1.set_assigned_location(mio::abm::ActivityType::School, school.get_id(), school.get_model_id()); + auto p2 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_5_to_14); + p2.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p2.set_assigned_location(mio::abm::ActivityType::School, school.get_id(), school.get_model_id()); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); // Set the age group the can go to school is AgeGroup(1) (i.e. 5-14) params.get() = false; @@ -101,9 +104,10 @@ TEST_F(TestLockdownRules, school_opening) .WillRepeatedly(testing::Return(1.0)); // Set up one person with assigned locations (home and school) - auto p = mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); - p.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p.set_assigned_location(school.get_type(), school.get_id(), school.get_model_id()); + auto p = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_5_to_14); + p.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p.set_assigned_location(mio::abm::ActivityType::School, school.get_id(), school.get_model_id()); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); // Set the age group the can go to school is AgeGroup(1) (i.e. 5-14) @@ -157,14 +161,14 @@ TEST_F(TestLockdownRules, home_office) .WillOnce(testing::Return(0.7)) .WillRepeatedly(testing::Return(1.0)); - auto person1 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); - auto person2 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); - person1.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - person1.set_assigned_location(work.get_type(), work.get_id(), work.get_model_id()); - person2.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - person2.set_assigned_location(work.get_type(), work.get_id(), work.get_model_id()); + auto person1 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_15_to_34); + auto person2 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_15_to_34); + person1.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + person1.set_assigned_location(mio::abm::ActivityType::Work, work.get_id(), work.get_model_id()); + person2.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + person2.set_assigned_location(mio::abm::ActivityType::Work, work.get_id(), work.get_model_id()); // Check that person1 goes to work and person2 stays at home. auto p1_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person1); @@ -195,9 +199,10 @@ TEST_F(TestLockdownRules, no_home_office) .WillOnce(testing::Return(0.7)) .WillRepeatedly(testing::Return(1.0)); - auto p = mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); - p.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p.set_assigned_location(work.get_type(), work.get_id(), work.get_model_id()); + auto p = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_15_to_34); + p.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p.set_assigned_location(mio::abm::ActivityType::Work, work.get_id(), work.get_model_id()); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); // Set the age group the can go to school is AgeGroup(1) (i.e. 5-14) params.get() = false; @@ -226,10 +231,11 @@ TEST_F(TestLockdownRules, social_event_closure) auto t_evening = mio::abm::TimePoint(0) + mio::abm::hours(19); mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); - mio::abm::Location event(mio::abm::LocationType::SocialEvent, 1, num_age_groups); - auto p = mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); - p.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p.set_assigned_location(event.get_type(), event.get_id(), event.get_model_id()); + mio::abm::Location event(mio::abm::LocationType::Recreation, 1, num_age_groups); + auto p = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_5_to_14); + p.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p.set_assigned_location(mio::abm::ActivityType::Recreation, event.get_id(), event.get_model_id()); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); // Close social events @@ -237,7 +243,7 @@ TEST_F(TestLockdownRules, social_event_closure) // Checks that p stays home instead of attending social events during a closure. auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p); - EXPECT_EQ(mio::abm::go_to_event(p_rng, p, t_evening, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_recreation(p_rng, p, t_evening, dt, params), mio::abm::ActivityType::Home); } /** @@ -251,10 +257,11 @@ TEST_F(TestLockdownRules, social_events_opening) auto t_evening = mio::abm::TimePoint(0) + mio::abm::days(1) + mio::abm::hours(19); mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); - mio::abm::Location event(mio::abm::LocationType::SocialEvent, 1, num_age_groups); - auto p = mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); - p.set_assigned_location(event.get_type(), event.get_id(), event.get_model_id()); - p.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); + mio::abm::Location event(mio::abm::LocationType::Recreation, 1, num_age_groups); + auto p = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_5_to_14); + p.set_assigned_location(mio::abm::ActivityType::Recreation, event.get_id(), event.get_model_id()); + p.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); // Close then open social events @@ -267,5 +274,5 @@ TEST_F(TestLockdownRules, social_events_opening) // Test that after reopening, p attends social events again. auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p); - EXPECT_EQ(mio::abm::go_to_event(p_rng, p, t_evening, dt, params), mio::abm::LocationType::SocialEvent); + EXPECT_EQ(mio::abm::go_to_recreation(p_rng, p, t_evening, dt, params), mio::abm::ActivityType::Recreation); } diff --git a/cpp/tests/test_abm_masks.cpp b/cpp/tests/test_abm_masks.cpp index 5031dc7205..c3e68da12b 100644 --- a/cpp/tests/test_abm_masks.cpp +++ b/cpp/tests/test_abm_masks.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/person.h" #include "abm_helpers.h" #include "random_number_test.h" @@ -79,13 +80,16 @@ TEST_F(TestMasks, maskProtection) auto t = mio::abm::TimePoint(0); mio::abm::Location infection_location(mio::abm::LocationType::School, 0, num_age_groups); // Two susceptible persons, one with a mask, one without - auto susc_person1 = mio::abm::Person(this->get_rng(), infection_location.get_type(), infection_location.get_id(), - infection_location.get_model_id(), age_group_15_to_34); - auto susc_person2 = mio::abm::Person(this->get_rng(), infection_location.get_type(), infection_location.get_id(), - infection_location.get_model_id(), age_group_15_to_34); + auto susc_person1 = + mio::abm::Person(this->get_rng(), infection_location.get_type(), mio::abm::ActivityType::School, + infection_location.get_id(), infection_location.get_model_id(), age_group_15_to_34); + auto susc_person2 = + mio::abm::Person(this->get_rng(), infection_location.get_type(), mio::abm::ActivityType::School, + infection_location.get_id(), infection_location.get_model_id(), age_group_15_to_34); // Infected person interacting with susceptible persons - auto infected1 = make_test_person(this->get_rng(), infection_location, age_group_15_to_34, - mio::abm::InfectionState::InfectedSymptoms, t, params); // infected 7 days prior + auto infected1 = + make_test_person(this->get_rng(), infection_location, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms, t, params); // infected 7 days prior // Cache precomputed results for 1-day intervals auto dt = mio::abm::days(1); diff --git a/cpp/tests/test_abm_mobility_rules.cpp b/cpp/tests/test_abm_mobility_rules.cpp index f5bd9fcc3a..2280df17e7 100644 --- a/cpp/tests/test_abm_mobility_rules.cpp +++ b/cpp/tests/test_abm_mobility_rules.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/location_type.h" #include "abm/mobility_rules.h" #include "abm/person.h" @@ -32,9 +33,10 @@ TEST_F(TestMobilityRules, random_mobility) { int t = 0, dt = 1; auto default_type = mio::abm::LocationType::Cemetery; - auto person = mio::abm::Person(this->get_rng(), default_type, 0, 0, age_group_15_to_34); - auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); - auto params = mio::abm::Parameters(num_age_groups); + auto person = + mio::abm::Person(this->get_rng(), default_type, mio::abm::ActivityType::Cemetery, 0, 0, age_group_15_to_34); + auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); + auto params = mio::abm::Parameters(num_age_groups); ScopedMockDistribution>>> mock_exp_dist; EXPECT_CALL(mock_exp_dist.get_mock(), invoke) @@ -84,10 +86,10 @@ TEST_F(TestMobilityRules, student_goes_to_school) .WillRepeatedly(testing::Return(1.0)); mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); - auto p_child = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); - auto p_adult = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); + auto p_child = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_5_to_14); + auto p_adult = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_15_to_34); auto t_morning = mio::abm::TimePoint(0) + mio::abm::hours(7); auto t_weekend = mio::abm::TimePoint(0) + mio::abm::days(5) + mio::abm::hours(7); @@ -134,12 +136,12 @@ TEST_F(TestMobilityRules, students_go_to_school_in_different_times) .WillRepeatedly(testing::Return(1.0)); mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); - auto p_child_goes_to_school_at_6 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); + auto p_child_goes_to_school_at_6 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, + home.get_id(), home.get_model_id(), age_group_5_to_14); auto rng_child_goes_to_school_at_6 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_child_goes_to_school_at_6); - auto p_child_goes_to_school_at_8 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); + auto p_child_goes_to_school_at_8 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, + home.get_id(), home.get_model_id(), age_group_5_to_14); auto rng_child_goes_to_school_at_8 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_child_goes_to_school_at_8); @@ -200,14 +202,15 @@ TEST_F(TestMobilityRules, students_go_to_school_in_different_times_with_smaller_ mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); // First student goes to school at 6:00 AM - auto p_child_goes_to_school_at_6 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); + auto p_child_goes_to_school_at_6 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, + home.get_id(), home.get_model_id(), age_group_5_to_14); auto rng_child_goes_to_school_at_6 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_child_goes_to_school_at_6); // Second student goes to school at 8:30 AM auto p_child_goes_to_school_at_8_30 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_5_to_14); + mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_5_to_14); auto rng_child_goes_to_school_at_8_30 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_child_goes_to_school_at_8_30); @@ -245,8 +248,8 @@ TEST_F(TestMobilityRules, students_go_to_school_in_different_times_with_smaller_ TEST_F(TestMobilityRules, school_return) { mio::abm::Location school(mio::abm::LocationType::School, 0, num_age_groups); - auto p_child = - mio::abm::Person(this->get_rng(), school.get_type(), school.get_id(), school.get_model_id(), age_group_5_to_14); + auto p_child = mio::abm::Person(this->get_rng(), school.get_type(), mio::abm::ActivityType::School, school.get_id(), + school.get_model_id(), age_group_5_to_14); auto rng_child = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_child); // Simulate a time point after school hours @@ -278,12 +281,12 @@ TEST_F(TestMobilityRules, worker_goes_to_work) .WillOnce(testing::Return(0.)) .WillRepeatedly(testing::Return(1.0)); - auto p_retiree = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_60_to_79); + auto p_retiree = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_60_to_79); auto rng_retiree = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_retiree); - auto p_adult = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); - auto rng_adult = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_adult); + auto p_adult = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_15_to_34); + auto rng_adult = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_adult); auto t_morning = mio::abm::TimePoint(0) + mio::abm::hours(8); auto t_night = mio::abm::TimePoint(0) + mio::abm::days(1) + mio::abm::hours(4); @@ -328,12 +331,12 @@ TEST_F(TestMobilityRules, worker_goes_to_work_with_non_dividable_timespan) .WillRepeatedly(testing::Return(1.0)); // Set up two people: one retiree and one working adult. - auto p_retiree = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_60_to_79); + auto p_retiree = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_60_to_79); auto rng_retiree = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_retiree); - auto p_adult = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); - auto rng_adult = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_adult); + auto p_adult = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_15_to_34); + auto rng_adult = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_adult); auto t_morning = mio::abm::TimePoint(0) + mio::abm::hours(8); auto t_night = mio::abm::TimePoint(0) + mio::abm::days(1) + mio::abm::hours(4); @@ -383,12 +386,12 @@ TEST_F(TestMobilityRules, workers_go_to_work_in_different_times) .WillRepeatedly(testing::Return(1.0)); // Create two workers: one goes to work at 6 AM and the other at 8 AM. - auto p_adult_goes_to_work_at_6 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); + auto p_adult_goes_to_work_at_6 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, + home.get_id(), home.get_model_id(), age_group_15_to_34); auto rng_adult_goes_to_work_at_6 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_adult_goes_to_work_at_6); - auto p_adult_goes_to_work_at_8 = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_15_to_34); + auto p_adult_goes_to_work_at_8 = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, + home.get_id(), home.get_model_id(), age_group_15_to_34); auto rng_adult_goes_to_work_at_8 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_adult_goes_to_work_at_8); @@ -432,8 +435,8 @@ TEST_F(TestMobilityRules, work_return) { mio::abm::Location work(mio::abm::LocationType::Work, 0, num_age_groups); // Set up a random number generator and a worker who is currently at work - auto p_adult = - mio::abm::Person(this->get_rng(), work.get_type(), work.get_id(), work.get_model_id(), age_group_35_to_59); + auto p_adult = mio::abm::Person(this->get_rng(), work.get_type(), mio::abm::ActivityType::Work, work.get_id(), + work.get_model_id(), age_group_35_to_59); auto rng_adult = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_adult); // Set the time to 5 PM (17:00) when the worker should return home auto t = mio::abm::TimePoint(0) + mio::abm::hours(17); @@ -455,23 +458,23 @@ TEST_F(TestMobilityRules, quarantine) mio::abm::Location work(mio::abm::LocationType::Work, 0, num_age_groups); mio::abm::Location hospital(mio::abm::LocationType::Hospital, 0, num_age_groups); - auto p_inf1 = - make_test_person(this->get_rng(), work, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms, t); + auto p_inf1 = make_test_person(this->get_rng(), work, mio::abm::ActivityType::Work, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms, t); auto rng_inf1 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_inf1); p_inf1.get_tested(rng_inf1, t, test_params); // Check detected infected person quarantines at home EXPECT_EQ(mio::abm::go_to_quarantine(rng_inf1, p_inf1, t, dt, mio::abm::Parameters(num_age_groups)), mio::abm::LocationType::Home); - auto p_inf2 = - make_test_person(this->get_rng(), work, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms, t); + auto p_inf2 = make_test_person(this->get_rng(), work, mio::abm::ActivityType::Work, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms, t); auto rng_inf2 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_inf2); // Check that undetected infected person does not quaratine EXPECT_EQ(mio::abm::go_to_quarantine(rng_inf2, p_inf2, t, dt, mio::abm::Parameters(num_age_groups)), mio::abm::LocationType::Work); - auto p_inf3 = - make_test_person(this->get_rng(), hospital, age_group_15_to_34, mio::abm::InfectionState::InfectedSevere, t); + auto p_inf3 = make_test_person(this->get_rng(), hospital, mio::abm::ActivityType::Hospital, age_group_15_to_34, + mio::abm::InfectionState::InfectedSevere, t); auto rng_inf3 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_inf3); p_inf1.get_tested(rng_inf3, t, test_params); // Check that detected infected person does not leave hospital to quarantine @@ -485,18 +488,18 @@ TEST_F(TestMobilityRules, quarantine) TEST_F(TestMobilityRules, hospital) { mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); - auto t = mio::abm::TimePoint(12346); - auto dt = mio::abm::hours(1); - auto p_inf = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::InfectedSevere, t); + auto t = mio::abm::TimePoint(12346); + auto dt = mio::abm::hours(1); + auto p_inf = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedSevere, t); auto rng_inf = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_inf); // Ensure person goes to the hospital when severely infected EXPECT_EQ(mio::abm::go_to_hospital(rng_inf, p_inf, t, dt, mio::abm::Parameters(num_age_groups)), mio::abm::LocationType::Hospital); - auto p_car = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); + auto p_car = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms); auto rng_car = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_car); // Ensure person has infection symptoms still stay at home EXPECT_EQ(mio::abm::go_to_hospital(rng_car, p_car, t, dt, mio::abm::Parameters(num_age_groups)), @@ -517,12 +520,12 @@ TEST_F(TestMobilityRules, go_shopping) auto dt = mio::abm::hours(1); // Create an infected child in the hospital - auto p_hosp = make_test_person(this->get_rng(), hospital, age_group_0_to_4, + auto p_hosp = make_test_person(this->get_rng(), hospital, mio::abm::ActivityType::Hospital, age_group_0_to_4, mio::abm::InfectionState::InfectedSymptoms, t_weekday); auto rng_hosp = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_hosp); // Create a healthy elderly person at home - auto p_home = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_60_to_79); + auto p_home = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_60_to_79); auto rng_home = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_home); // Check that an infected person stays in the hospital and doesn't go shopping @@ -555,8 +558,8 @@ TEST_F(TestMobilityRules, shop_return) // Create a person at a basic shop who is asymptomatically infected mio::abm::Location shop(mio::abm::LocationType::BasicsShop, 0, num_age_groups); - auto p = - make_test_person(this->get_rng(), shop, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, t); + auto p = make_test_person(this->get_rng(), shop, mio::abm::ActivityType::BasicsShop, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, t); auto rng_p = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p); // Simulate the person spending 1 hour at the shop p.add_time_at_location(dt); @@ -573,12 +576,12 @@ TEST_F(TestMobilityRules, go_event) { // Initialize two people, one at work and one at home mio::abm::Location work(mio::abm::LocationType::Work, 0, num_age_groups); - auto p_work = - mio::abm::Person(this->get_rng(), work.get_type(), work.get_id(), work.get_model_id(), age_group_35_to_59); + auto p_work = mio::abm::Person(this->get_rng(), work.get_type(), mio::abm::ActivityType::Work, work.get_id(), + work.get_model_id(), age_group_35_to_59); auto rng_work = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_work); mio::abm::Location home(mio::abm::LocationType::Home, 1, num_age_groups); - auto p_home = - mio::abm::Person(this->get_rng(), home.get_type(), home.get_id(), home.get_model_id(), age_group_60_to_79); + auto p_home = mio::abm::Person(this->get_rng(), home.get_type(), mio::abm::ActivityType::Home, home.get_id(), + home.get_model_id(), age_group_60_to_79); auto rng_home = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_home); auto t_weekday = mio::abm::TimePoint(0) + mio::abm::days(4) + mio::abm::hours(20); @@ -587,23 +590,23 @@ TEST_F(TestMobilityRules, go_event) auto dt = mio::abm::hours(1); // Check that person at work should not go to an event during a weekday evening, so they stay at work - EXPECT_EQ(mio::abm::go_to_event(rng_work, p_work, t_weekday, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Work); + EXPECT_EQ(mio::abm::go_to_recreation(rng_work, p_work, t_weekday, dt, mio::abm::Parameters(num_age_groups)), + mio::abm::ActivityType::Work); // Check that person at home during nighttime should not go to an event, so they stay at home - EXPECT_EQ(mio::abm::go_to_event(rng_home, p_home, t_night, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_recreation(rng_home, p_home, t_night, dt, mio::abm::Parameters(num_age_groups)), + mio::abm::ActivityType::Home); // Mock the random distribution to simulate event participation based on random draw ScopedMockDistribution>>> mock_exponential_dist; EXPECT_CALL(mock_exponential_dist.get_mock(), invoke).Times(1).WillOnce(testing::Return(0.01)); // Check that person at home goes to a social event on a weekday evening based on a low random value - EXPECT_EQ(mio::abm::go_to_event(rng_home, p_home, t_weekday, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::SocialEvent); + EXPECT_EQ(mio::abm::go_to_recreation(rng_home, p_home, t_weekday, dt, mio::abm::Parameters(num_age_groups)), + mio::abm::ActivityType::Recreation); // Check that person at home goes to a social event on a Saturday morning based on a low random value EXPECT_CALL(mock_exponential_dist.get_mock(), invoke).Times(1).WillOnce(testing::Return(0.01)); - EXPECT_EQ(mio::abm::go_to_event(rng_home, p_home, t_saturday, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::SocialEvent); + EXPECT_EQ(mio::abm::go_to_recreation(rng_home, p_home, t_saturday, dt, mio::abm::Parameters(num_age_groups)), + mio::abm::ActivityType::Recreation); } /** @@ -616,15 +619,15 @@ TEST_F(TestMobilityRules, event_return) auto dt = mio::abm::hours(3); mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); - mio::abm::Location social_event(mio::abm::LocationType::SocialEvent, 1, num_age_groups); + mio::abm::Location social_event(mio::abm::LocationType::Recreation, 1, num_age_groups); // Initialize the person at the social event location - auto p = mio::abm::Person(this->get_rng(), social_event.get_type(), social_event.get_id(), - social_event.get_model_id(), age_group_15_to_34); + auto p = mio::abm::Person(this->get_rng(), social_event.get_type(), mio::abm::ActivityType::Recreation, + social_event.get_id(), social_event.get_model_id(), age_group_15_to_34); auto rng_p = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p); // Simulate the person spending 3 hours at the social event p.add_time_at_location(dt); // After spending the time at the social event, the person should return home - EXPECT_EQ(mio::abm::go_to_event(rng_p, p, t, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_recreation(rng_p, p, t, dt, params), mio::abm::LocationType::Home); } /** @@ -633,10 +636,10 @@ TEST_F(TestMobilityRules, event_return) TEST_F(TestMobilityRules, icu) { mio::abm::Location hospital(mio::abm::LocationType::Hospital, 0, num_age_groups); - auto t = mio::abm::TimePoint(12346); - auto dt = mio::abm::hours(1); - auto p_hosp = - make_test_person(this->get_rng(), hospital, age_group_15_to_34, mio::abm::InfectionState::InfectedCritical, t); + auto t = mio::abm::TimePoint(12346); + auto dt = mio::abm::hours(1); + auto p_hosp = make_test_person(this->get_rng(), hospital, mio::abm::ActivityType::Hospital, age_group_15_to_34, + mio::abm::InfectionState::InfectedCritical, t); auto rng_hosp = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_hosp); // Ensure critically infected person goes to the ICU @@ -644,8 +647,8 @@ TEST_F(TestMobilityRules, icu) mio::abm::LocationType::ICU); mio::abm::Location work(mio::abm::LocationType::Work, 1, num_age_groups); - auto p_work = - make_test_person(this->get_rng(), work, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms, t); + auto p_work = make_test_person(this->get_rng(), work, mio::abm::ActivityType::Work, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms, t); auto rng_work = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_work); // Ensure infected with symptions person can still go to work EXPECT_EQ(mio::abm::go_to_icu(rng_work, p_work, t, dt, mio::abm::Parameters(num_age_groups)), @@ -658,13 +661,13 @@ TEST_F(TestMobilityRules, icu) TEST_F(TestMobilityRules, recover) { mio::abm::Location hospital(mio::abm::LocationType::Hospital, 0); - auto t = mio::abm::TimePoint(12346); - auto dt = mio::abm::hours(1); - auto p_rec = - make_test_person(this->get_rng(), hospital, age_group_60_to_79, mio::abm::InfectionState::Recovered, t); + auto t = mio::abm::TimePoint(12346); + auto dt = mio::abm::hours(1); + auto p_rec = make_test_person(this->get_rng(), hospital, mio::abm::ActivityType::Hospital, age_group_60_to_79, + mio::abm::InfectionState::Recovered, t); auto rng_rec = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_rec); - auto p_inf = - make_test_person(this->get_rng(), hospital, age_group_60_to_79, mio::abm::InfectionState::InfectedSevere, t); + auto p_inf = make_test_person(this->get_rng(), hospital, mio::abm::ActivityType::Hospital, age_group_60_to_79, + mio::abm::InfectionState::InfectedSevere, t); auto rng_inf = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_inf); // Ensure recovered person returns home and infected severe person stay in hospital EXPECT_EQ(mio::abm::return_home_when_recovered(rng_rec, p_rec, t, dt, {num_age_groups}), @@ -681,7 +684,8 @@ TEST_F(TestMobilityRules, dead) mio::abm::Location icu(mio::abm::LocationType::ICU, 0); auto t = mio::abm::TimePoint(12346); auto dt = mio::abm::hours(1); - auto p_dead = make_test_person(this->get_rng(), icu, age_group_60_to_79, mio::abm::InfectionState::Dead, t); + auto p_dead = make_test_person(this->get_rng(), icu, mio::abm::ActivityType::ICU, age_group_60_to_79, + mio::abm::InfectionState::Dead, t); auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_dead); EXPECT_EQ(mio::abm::get_buried(p_rng, p_dead, t, dt, {num_age_groups}), mio::abm::LocationType::Cemetery); diff --git a/cpp/tests/test_abm_model.cpp b/cpp/tests/test_abm_model.cpp index fe7926ff06..371ee1d1c9 100644 --- a/cpp/tests/test_abm_model.cpp +++ b/cpp/tests/test_abm_model.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/location_id.h" #include "abm/person_id.h" #include "memilio/utils/random_number_generator.h" @@ -99,8 +100,8 @@ TEST_F(TestModel, addPerson) auto model = mio::abm::Model(num_age_groups); auto location = model.add_location(mio::abm::LocationType::School); - auto id1 = model.add_person(location, age_group_15_to_34); - auto id2 = model.add_person(location, age_group_35_to_59); + auto id1 = model.add_person(location, age_group_15_to_34, mio::abm::ActivityType::School); + auto id2 = model.add_person(location, age_group_35_to_59, mio::abm::ActivityType::Work); // Verify the number of persons in the model and their respective age groups. EXPECT_EQ(model.get_persons().size(), 2); @@ -123,8 +124,8 @@ TEST_F(TestModel, getNumberPersons) auto location = model.add_location(mio::abm::LocationType::School); // Add persons to the model. - model.add_person(location, age_group_15_to_34); - model.add_person(location, age_group_35_to_59); + model.add_person(location, age_group_15_to_34, mio::abm::ActivityType::School); + model.add_person(location, age_group_35_to_59, mio::abm::ActivityType::Work); EXPECT_TRUE(logger.read().empty()); @@ -161,12 +162,18 @@ TEST_F(TestModel, getSubpopulationCombined) auto home1 = model.add_location(mio::abm::LocationType::Home); // Add persons to these locations with various infection states. - add_test_person(model, school1, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); - add_test_person(model, school1, age_group_15_to_34, mio::abm::InfectionState::Susceptible); - add_test_person(model, school2, age_group_15_to_34, mio::abm::InfectionState::Susceptible); - add_test_person(model, school2, age_group_15_to_34, mio::abm::InfectionState::Susceptible); - add_test_person(model, school3, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); - add_test_person(model, home1, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); + add_test_person(model, school1, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms); + add_test_person(model, school1, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::Susceptible); + add_test_person(model, school2, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::Susceptible); + add_test_person(model, school2, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::Susceptible); + add_test_person(model, school3, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms); + add_test_person(model, home1, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms); // Verify the count of susceptible persons across all School locations. EXPECT_EQ(model.get_subpopulation_combined_per_location_type(t, mio::abm::InfectionState::Susceptible, @@ -194,22 +201,22 @@ TEST_F(TestModel, findLocation) auto work_id = model.add_location(mio::abm::LocationType::Work); // Add a person to the model and assign them to multiple locations. - auto person_id = add_test_person(model, home_id); + auto person_id = add_test_person(model, home_id, mio::abm::ActivityType::Home); auto& person = model.get_person(person_id); - person.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - person.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - person.set_assigned_location(mio::abm::LocationType::School, school_id, model.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + person.set_assigned_location(mio::abm::ActivityType::School, school_id, model.get_id()); // Verify that the find_location method correctly identifies each assigned location. - EXPECT_EQ(model.find_location(mio::abm::LocationType::Work, person_id), work_id); - EXPECT_EQ(model.find_location(mio::abm::LocationType::School, person_id), school_id); - EXPECT_EQ(model.find_location(mio::abm::LocationType::Home, person_id), home_id); + EXPECT_EQ(model.find_locations(mio::abm::ActivityType::Work, person_id)[0], work_id); + EXPECT_EQ(model.find_locations(mio::abm::ActivityType::School, person_id)[0], school_id); + EXPECT_EQ(model.find_locations(mio::abm::ActivityType::Home, person_id)[0], home_id); // Check that the method also works with a constant reference to the model. auto&& model_test = std::as_const(model); - EXPECT_EQ(model_test.find_location(mio::abm::LocationType::Work, person_id), work_id); - EXPECT_EQ(model_test.find_location(mio::abm::LocationType::School, person_id), school_id); - EXPECT_EQ(model_test.find_location(mio::abm::LocationType::Home, person_id), home_id); + EXPECT_EQ(model_test.find_locations(mio::abm::ActivityType::Work, person_id)[0], work_id); + EXPECT_EQ(model_test.find_locations(mio::abm::ActivityType::School, person_id)[0], school_id); + EXPECT_EQ(model_test.find_locations(mio::abm::ActivityType::Home, person_id)[0], home_id); } /** @@ -251,18 +258,21 @@ TEST_F(TestModel, evolveStateTransition) // Add locations and persons to the model with different initial infection states. auto location1 = model.add_location(mio::abm::LocationType::School); auto location2 = model.add_location(mio::abm::LocationType::Work); - add_test_person(model, location1, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); - add_test_person(model, location1, age_group_15_to_34, mio::abm::InfectionState::Susceptible); - add_test_person(model, location2, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); + add_test_person(model, location1, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms); + add_test_person(model, location1, mio::abm::ActivityType::School, age_group_15_to_34, + mio::abm::InfectionState::Susceptible); + add_test_person(model, location2, mio::abm::ActivityType::Work, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms); auto& p1 = model.get_persons()[0]; auto& p2 = model.get_persons()[1]; auto& p3 = model.get_persons()[2]; // Assign persons to their respective locations. - p1.set_assigned_location(mio::abm::LocationType::School, location1, model.get_id()); - p2.set_assigned_location(mio::abm::LocationType::School, location1, model.get_id()); - p3.set_assigned_location(mio::abm::LocationType::Work, location2, model.get_id()); + p1.set_assigned_location(mio::abm::ActivityType::School, location1, model.get_id()); + p2.set_assigned_location(mio::abm::ActivityType::School, location1, model.get_id()); + p3.set_assigned_location(mio::abm::ActivityType::Work, location2, model.get_id()); // Setup mock so p2 becomes infected ScopedMockDistribution>>> @@ -312,18 +322,20 @@ TEST_F(TestModel, evolveMobilityRules) .WillOnce(testing::Return(0.8)) // draw random school hour .WillRepeatedly(testing::Return(1.0)); - auto pid2 = add_test_person(model, home_id, age_group_5_to_14, mio::abm::InfectionState::Susceptible, t); - auto pid1 = add_test_person(model, home_id, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, t); + auto pid2 = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_5_to_14, + mio::abm::InfectionState::Susceptible, t); + auto pid1 = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, t); auto& p1 = model.get_person(pid1); auto& p2 = model.get_person(pid2); - p1.set_assigned_location(mio::abm::LocationType::School, school_id, model.get_id()); - p2.set_assigned_location(mio::abm::LocationType::School, school_id, model.get_id()); - p1.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p2.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p1.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p2.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); + p1.set_assigned_location(mio::abm::ActivityType::School, school_id, model.get_id()); + p2.set_assigned_location(mio::abm::ActivityType::School, school_id, model.get_id()); + p1.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p2.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p1.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p2.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); ScopedMockDistribution>>> mock_exponential_dist; @@ -368,7 +380,7 @@ TEST_F(TestModel, evolveMobilityTrips) // Add different location types to the model. auto home_id = model.add_location(mio::abm::LocationType::Home); - auto event_id = model.add_location(mio::abm::LocationType::SocialEvent); + auto event_id = model.add_location(mio::abm::LocationType::Recreation); auto work_id = model.add_location(mio::abm::LocationType::Work); auto hospital_id = model.add_location(mio::abm::LocationType::Hospital); @@ -386,11 +398,11 @@ TEST_F(TestModel, evolveMobilityTrips) .WillRepeatedly(testing::Return(0.8)); // this forces p1 and p3 to recover // Create persons with various infection states and assign them to multiple locations. - auto pid1 = model.add_person(home_id, age_group_15_to_34); - auto pid2 = model.add_person(home_id, age_group_15_to_34); - auto pid3 = model.add_person(home_id, age_group_15_to_34); - auto pid4 = model.add_person(hospital_id, age_group_15_to_34); - auto pid5 = model.add_person(home_id, age_group_15_to_34); + auto pid1 = model.add_person(home_id, age_group_15_to_34, mio::abm::ActivityType::Home); + auto pid2 = model.add_person(home_id, age_group_15_to_34, mio::abm::ActivityType::Home); + auto pid3 = model.add_person(home_id, age_group_15_to_34, mio::abm::ActivityType::Home); + auto pid4 = model.add_person(hospital_id, age_group_15_to_34, mio::abm::ActivityType::Hospital); + auto pid5 = model.add_person(home_id, age_group_15_to_34, mio::abm::ActivityType::Home); // Assign persons to locations for trips. auto& p1 = model.get_person(pid1); @@ -399,25 +411,28 @@ TEST_F(TestModel, evolveMobilityTrips) auto& p4 = model.get_person(pid4); auto& p5 = model.get_person(pid5); - p1.set_assigned_location(mio::abm::LocationType::SocialEvent, event_id, model.get_id()); - p2.set_assigned_location(mio::abm::LocationType::SocialEvent, event_id, model.get_id()); - p1.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p2.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p1.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p2.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p3.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p4.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p3.set_assigned_location(mio::abm::LocationType::Hospital, hospital_id, model.get_id()); - p4.set_assigned_location(mio::abm::LocationType::Hospital, hospital_id, model.get_id()); - p5.set_assigned_location(mio::abm::LocationType::SocialEvent, event_id, model.get_id()); - p5.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p5.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); + p1.set_assigned_location(mio::abm::ActivityType::Recreation, event_id, model.get_id()); + p2.set_assigned_location(mio::abm::ActivityType::Recreation, event_id, model.get_id()); + p1.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p2.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p1.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p2.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p3.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p4.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p3.set_assigned_location(mio::abm::ActivityType::Hospital, hospital_id, model.get_id()); + p4.set_assigned_location(mio::abm::ActivityType::Hospital, hospital_id, model.get_id()); + p5.set_assigned_location(mio::abm::ActivityType::Recreation, event_id, model.get_id()); + p5.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p5.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); // Set trips for persons between assigned locations. mio::abm::TripList& data = model.get_trip_list(); - mio::abm::Trip trip1(p1.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(9), work_id); - mio::abm::Trip trip2(p2.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(9), event_id); - mio::abm::Trip trip3(p5.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(9), event_id); + mio::abm::Trip trip1(p1.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(9), work_id, + mio::abm::ActivityType::Work); + mio::abm::Trip trip2(p2.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(9), event_id, + mio::abm::ActivityType::Recreation); + mio::abm::Trip trip3(p5.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(9), event_id, + mio::abm::ActivityType::Recreation); auto trips_part1 = std::vector{trip2, trip3}; auto trips_part2 = std::vector{trip1}; @@ -500,14 +515,14 @@ TEST_F(TestModel, reachCapacity) .WillRepeatedly(testing::Return(1.0)); // Create two persons with different infection states. - auto p1 = add_test_person(model, home_id, age_group_5_to_14); - auto p2 = add_test_person(model, home_id, age_group_5_to_14); + auto p1 = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_5_to_14); + auto p2 = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_5_to_14); // Assign both persons to School and Home. - model.get_person(p1).set_assigned_location(mio::abm::LocationType::School, school_id, 0); - model.get_person(p2).set_assigned_location(mio::abm::LocationType::School, school_id, 0); - model.get_person(p1).set_assigned_location(mio::abm::LocationType::Home, home_id, 0); - model.get_person(p2).set_assigned_location(mio::abm::LocationType::Home, home_id, 0); + model.get_person(p1).set_assigned_location(mio::abm::ActivityType::School, school_id, 0); + model.get_person(p2).set_assigned_location(mio::abm::ActivityType::School, school_id, 0); + model.get_person(p1).set_assigned_location(mio::abm::ActivityType::Home, home_id, 0); + model.get_person(p2).set_assigned_location(mio::abm::ActivityType::Home, home_id, 0); // Set the capacity of the school to 1 person with a distance requirement of 66. model.get_location(school_id).set_capacity(1, 66); @@ -555,25 +570,29 @@ TEST_F(TestModel, checkMobilityOfDeadPerson) EXPECT_CALL(mock_uniform_dist.get_mock(), invoke).WillRepeatedly(testing::Return(1.0)); // Create a person that is dead at time t - add_test_person(model, icu_id, age_group_60_to_79, mio::abm::InfectionState::Dead, t); + add_test_person(model, icu_id, mio::abm::ActivityType::ICU, age_group_60_to_79, mio::abm::InfectionState::Dead, t); // Create a person that is severe at hospital and will be dead at time t + dt - add_test_person(model, hospital_id, age_group_60_to_79, mio::abm::InfectionState::Dead, t + dt); + add_test_person(model, hospital_id, mio::abm::ActivityType::Hospital, age_group_60_to_79, + mio::abm::InfectionState::Dead, t + dt); auto& p_dead = model.get_persons()[0]; auto& p_severe = model.get_persons()[1]; - p_dead.set_assigned_location(mio::abm::LocationType::ICU, icu_id, model.get_id()); - p_dead.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_dead.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_severe.set_assigned_location(mio::abm::LocationType::Hospital, hospital_id, model.get_id()); - p_severe.set_assigned_location(mio::abm::LocationType::ICU, icu_id, model.get_id()); - p_severe.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); + p_dead.set_assigned_location(mio::abm::ActivityType::ICU, icu_id, model.get_id()); + p_dead.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_dead.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_severe.set_assigned_location(mio::abm::ActivityType::Hospital, hospital_id, model.get_id()); + p_severe.set_assigned_location(mio::abm::ActivityType::ICU, icu_id, model.get_id()); + p_severe.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); // Add trip to see if a dead person can change location outside of cemetery by scheduled trips mio::abm::TripList& trip_list = model.get_trip_list(); - mio::abm::Trip trip1(p_dead.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(2), home_id); - mio::abm::Trip trip2(p_dead.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(3), icu_id); - mio::abm::Trip trip3(p_severe.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(3), icu_id); + mio::abm::Trip trip1(p_dead.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(2), home_id, + mio::abm::ActivityType::Home); + mio::abm::Trip trip2(p_dead.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(3), icu_id, + mio::abm::ActivityType::ICU); + mio::abm::Trip trip3(p_severe.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(3), icu_id, + mio::abm::ActivityType::ICU); trip_list.add_trips({trip1, trip2, trip3}); // Check the dead person got burried and the severely infected person starts in Hospital @@ -612,12 +631,12 @@ TEST_F(TestModelTestingCriteria, testAddingAndUpdatingAndRunningTestingSchemes) auto test_time = mio::abm::minutes(30); // Add a person to the model with an infection state that requires testing. // Since tests are performed before current_time, the InfectionState of the Person has to take into account test_time - auto pid = add_test_person(model, home_id, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms, - current_time - test_time); + auto pid = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms, current_time - test_time); auto& person = model.get_person(pid); auto rng_person = mio::abm::PersonalRandomNumberGenerator(model.get_rng(), person); - person.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - person.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + person.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); auto validity_period = mio::abm::days(1); const auto start_date = mio::abm::TimePoint(0) + mio::abm::days(1); @@ -851,16 +870,16 @@ TEST_F(TestModel, mobilityRulesWithAppliedNPIs) .WillRepeatedly(testing::Return(0.9)); // draw that satisfies all pre-conditions of NPIs // Since tests are performed before t, the InfectionState of all the Person have to take into account test_time - auto p_id_compliant_go_to_work = - add_test_person(model, home_id, age_group_15_to_34, mio::abm::InfectionState::Susceptible, t - test_time); - auto p_id_compliant_go_to_school = - add_test_person(model, home_id, age_group_5_to_14, mio::abm::InfectionState::Susceptible, t - test_time); - auto p_id_no_mask = - add_test_person(model, home_id, age_group_15_to_34, mio::abm::InfectionState::Susceptible, t - test_time); - auto p_id_no_test = add_test_person(model, home_id, age_group_15_to_34, - mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); - auto p_id_no_isolation = add_test_person(model, home_id, age_group_15_to_34, - mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); + auto p_id_compliant_go_to_work = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Susceptible, t - test_time); + auto p_id_compliant_go_to_school = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_5_to_14, + mio::abm::InfectionState::Susceptible, t - test_time); + auto p_id_no_mask = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Susceptible, t - test_time); + auto p_id_no_test = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); + auto p_id_no_isolation = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); auto& p_compliant_go_to_work = model.get_person(p_id_compliant_go_to_work); auto& p_compliant_go_to_school = model.get_person(p_id_compliant_go_to_school); @@ -868,17 +887,17 @@ TEST_F(TestModel, mobilityRulesWithAppliedNPIs) auto& p_no_test = model.get_person(p_id_no_test); auto& p_no_isolation = model.get_person(p_id_no_isolation); - p_compliant_go_to_work.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_compliant_go_to_work.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_compliant_go_to_work.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_compliant_go_to_school.set_assigned_location(mio::abm::LocationType::School, school_id, model.get_id()); - p_compliant_go_to_school.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_no_mask.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_no_mask.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_no_test.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_no_test.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_no_isolation.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_no_isolation.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); + p_compliant_go_to_work.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_compliant_go_to_work.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_compliant_go_to_work.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_compliant_go_to_school.set_assigned_location(mio::abm::ActivityType::School, school_id, model.get_id()); + p_compliant_go_to_school.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_no_mask.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_no_mask.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_no_test.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_no_test.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_no_isolation.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_no_isolation.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); auto testing_criteria = mio::abm::TestingCriteria( {}, {mio::abm::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedNoSymptoms}); @@ -967,16 +986,16 @@ TEST_F(TestModel, mobilityTripWithAppliedNPIs) .WillRepeatedly(testing::Return(0.9)); // draw that satisfies all pre-conditions of NPIs // Since tests are performed before t, the InfectionState of all the Person have to take into account test_time - auto p_id_compliant_go_to_work = - add_test_person(model, home_id, age_group_15_to_34, mio::abm::InfectionState::Susceptible, t - test_time); - auto p_id_compliant_go_to_school = - add_test_person(model, home_id, age_group_5_to_14, mio::abm::InfectionState::Susceptible, t - test_time); - auto p_id_no_mask = - add_test_person(model, home_id, age_group_15_to_34, mio::abm::InfectionState::Susceptible, t - test_time); - auto p_id_no_test = add_test_person(model, home_id, age_group_15_to_34, - mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); - auto p_id_no_isolation = add_test_person(model, home_id, age_group_15_to_34, - mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); + auto p_id_compliant_go_to_work = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Susceptible, t - test_time); + auto p_id_compliant_go_to_school = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_5_to_14, + mio::abm::InfectionState::Susceptible, t - test_time); + auto p_id_no_mask = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Susceptible, t - test_time); + auto p_id_no_test = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); + auto p_id_no_isolation = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, t - test_time); auto& p_compliant_go_to_work = model.get_person(p_id_compliant_go_to_work); auto& p_compliant_go_to_school = model.get_person(p_id_compliant_go_to_school); @@ -984,17 +1003,17 @@ TEST_F(TestModel, mobilityTripWithAppliedNPIs) auto& p_no_test = model.get_person(p_id_no_test); auto& p_no_isolation = model.get_person(p_id_no_isolation); - p_compliant_go_to_work.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_compliant_go_to_work.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_compliant_go_to_work.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_compliant_go_to_school.set_assigned_location(mio::abm::LocationType::School, school_id, model.get_id()); - p_compliant_go_to_school.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_no_mask.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_no_mask.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_no_test.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_no_test.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_no_isolation.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); - p_no_isolation.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); + p_compliant_go_to_work.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_compliant_go_to_work.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_compliant_go_to_work.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_compliant_go_to_school.set_assigned_location(mio::abm::ActivityType::School, school_id, model.get_id()); + p_compliant_go_to_school.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_no_mask.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_no_mask.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_no_test.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_no_test.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_no_isolation.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); + p_no_isolation.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); auto testing_criteria = mio::abm::TestingCriteria( {}, {mio::abm::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedNoSymptoms}); @@ -1019,11 +1038,11 @@ TEST_F(TestModel, mobilityTripWithAppliedNPIs) // Using trip list mio::abm::TripList& trip_list = model.get_trip_list(); - mio::abm::Trip trip1(p_compliant_go_to_work.get_id(), t, work_id); - mio::abm::Trip trip2(p_compliant_go_to_school.get_id(), t, school_id); - mio::abm::Trip trip3(p_no_mask.get_id(), t, work_id); - mio::abm::Trip trip4(p_no_test.get_id(), t, work_id); - mio::abm::Trip trip5(p_no_isolation.get_id(), t, work_id); + mio::abm::Trip trip1(p_compliant_go_to_work.get_id(), t, work_id, mio::abm::ActivityType::Work); + mio::abm::Trip trip2(p_compliant_go_to_school.get_id(), t, school_id, mio::abm::ActivityType::School); + mio::abm::Trip trip3(p_no_mask.get_id(), t, work_id, mio::abm::ActivityType::Work); + mio::abm::Trip trip4(p_no_test.get_id(), t, work_id, mio::abm::ActivityType::Work); + mio::abm::Trip trip5(p_no_isolation.get_id(), t, work_id, mio::abm::ActivityType::Work); trip_list.add_trips({trip1, trip2, trip3, trip4, trip5}); model.use_mobility_rules(false); model.evolve(t, dt); @@ -1087,13 +1106,14 @@ TEST_F(TestModel, personCanDieInHospital) EXPECT_CALL(mock_uniform_dist.get_mock(), invoke).WillRepeatedly(testing::Return(0.09)); // Create a person that has InfectedSymptoms at time t - dt. The person is dead at time t + dt - add_test_person(model, home_id, age_group_60_to_79, mio::abm::InfectionState::Dead, t + dt); + add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_60_to_79, mio::abm::InfectionState::Dead, + t + dt); auto& p_severe = model.get_persons()[0]; - p_severe.set_assigned_location(mio::abm::LocationType::Hospital, hospital_id, model.get_id()); - p_severe.set_assigned_location(mio::abm::LocationType::ICU, icu_id, model.get_id()); - p_severe.set_assigned_location(mio::abm::LocationType::Home, home_id, model.get_id()); - p_severe.set_assigned_location(mio::abm::LocationType::Work, work_id, model.get_id()); + p_severe.set_assigned_location(mio::abm::ActivityType::Hospital, hospital_id, model.get_id()); + p_severe.set_assigned_location(mio::abm::ActivityType::ICU, icu_id, model.get_id()); + p_severe.set_assigned_location(mio::abm::ActivityType::Home, home_id, model.get_id()); + p_severe.set_assigned_location(mio::abm::ActivityType::Work, work_id, model.get_id()); // Check the infection course goes from InfectedSymptoms to Severe to Dead and skips Critical EXPECT_EQ(p_severe.get_infection_state(t - dt), mio::abm::InfectionState::InfectedSymptoms); @@ -1118,7 +1138,7 @@ TEST_F(TestModel, reset_rng) { // use DefaultFactory to avoid using the RNG in the Person ctor auto p = mio::DefaultFactory::create(); - p.set_location(mio::abm::LocationType::Cemetery, mio::abm::LocationId(0), 0); + p.set_location(mio::abm::ActivityType::Cemetery, mio::abm::LocationType::Cemetery, mio::abm::LocationId(0), 0); model.add_person(mio::abm::Person(p, mio::abm::PersonId(0))); model.add_person(mio::abm::Person(p, mio::abm::PersonId(1))); } diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index 9bc2cabc40..9cf8e1eec8 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/location_id.h" #include "abm/model_functions.h" #include "abm/location_type.h" @@ -38,8 +39,8 @@ TEST_F(TestPerson, init) { mio::abm::Location location(mio::abm::LocationType::Work, 7, num_age_groups); auto t = mio::abm::TimePoint(0); - auto person = mio::abm::Person(this->get_rng(), location.get_type(), location.get_id(), location.get_model_id(), - age_group_60_to_79); + auto person = mio::abm::Person(this->get_rng(), location.get_type(), mio::abm::ActivityType::Work, + location.get_id(), location.get_model_id(), age_group_60_to_79); // Verify default state and location assignments. EXPECT_EQ(person.get_infection_state(t), mio::abm::InfectionState::Susceptible); @@ -61,27 +62,31 @@ TEST_F(TestPerson, change_location) mio::abm::Location loc1(mio::abm::LocationType::PublicTransport, 1, 6, 0, 1); mio::abm::Location loc2(mio::abm::LocationType::School, 2, num_age_groups); mio::abm::Location loc3(mio::abm::LocationType::PublicTransport, 3, 6, 0, 2); - auto person = make_test_person(this->get_rng(), home, age_group_0_to_4, mio::abm::InfectionState::Recovered); + auto person = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_0_to_4, + mio::abm::InfectionState::Recovered); // Check that a person does not change location to its current location person.add_time_at_location(mio::abm::hours(1)); - EXPECT_FALSE(mio::abm::change_location(person, home)); + EXPECT_FALSE(mio::abm::change_location(person, home, mio::abm::ActivityType::Home)); EXPECT_EQ(person.get_time_at_location(), mio::abm::hours(1)); EXPECT_EQ(person.get_location(), home.get_id()); // Change the location of the person a couple of times - EXPECT_TRUE(mio::abm::change_location(person, loc1, mio::abm::TransportMode::Unknown, {0})); + EXPECT_TRUE(mio::abm::change_location(person, loc1, mio::abm::ActivityType::Invalid, + mio::abm::TransportMode::Unknown, {0})); EXPECT_EQ(person.get_time_at_location(), mio::abm::TimeSpan(0)); EXPECT_EQ(person.get_location(), loc1.get_id()); EXPECT_EQ(person.get_last_transport_mode(), mio::abm::TransportMode::Unknown); - EXPECT_TRUE(mio::abm::change_location(person, loc2, mio::abm::TransportMode::Walking, {0})); + EXPECT_TRUE(mio::abm::change_location(person, loc2, mio::abm::ActivityType::Invalid, + mio::abm::TransportMode::Walking, {0})); EXPECT_EQ(person.get_time_at_location(), mio::abm::TimeSpan(0)); EXPECT_EQ(person.get_location(), loc2.get_id()); EXPECT_EQ(person.get_last_transport_mode(), mio::abm::TransportMode::Walking); // Test changing location with cell indices. - EXPECT_TRUE(mio::abm::change_location(person, loc3, mio::abm::TransportMode::Bike, {0, 1})); + EXPECT_TRUE(mio::abm::change_location(person, loc3, mio::abm::ActivityType::Invalid, mio::abm::TransportMode::Bike, + {0, 1})); EXPECT_EQ(person.get_time_at_location(), mio::abm::TimeSpan(0)); EXPECT_EQ(person.get_location(), loc3.get_id()); EXPECT_EQ(person.get_last_transport_mode(), mio::abm::TransportMode::Bike); @@ -96,30 +101,32 @@ TEST_F(TestPerson, change_location) TEST_F(TestPerson, setGetAssignedLocation) { mio::abm::Location location(mio::abm::LocationType::Work, 2, num_age_groups); - auto person = mio::abm::Person(this->get_rng(), location.get_type(), location.get_id(), location.get_model_id(), - age_group_35_to_59); + auto person = mio::abm::Person(this->get_rng(), location.get_type(), mio::abm::ActivityType::Work, + location.get_id(), location.get_model_id(), age_group_35_to_59); + auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); // Assign and verify a location for the person. - person.set_assigned_location(location.get_type(), location.get_id(), location.get_model_id()); - EXPECT_EQ(person.get_assigned_location(mio::abm::LocationType::Work), mio::abm::LocationId(2)); + person.set_assigned_location(mio::abm::ActivityType::Work, location.get_id(), location.get_model_id()); + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), mio::abm::LocationId(2)); // Change the assigned location and verify. - person.set_assigned_location(mio::abm::LocationType::Work, mio::abm::LocationId(4), 0); - EXPECT_EQ(person.get_assigned_location(mio::abm::LocationType::Work), mio::abm::LocationId(4)); + person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(4), 0); + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), mio::abm::LocationId(4)); // Fuzzing: assign random valid LocationId values and verify correctness. for (int i = 0; i < 100; ++i) { auto random_id = this->random_integer(0, std::numeric_limits::max()); - auto random_type = this->random_integer(0, (int)mio::abm::LocationType::Count - 1); - person.set_assigned_location((mio::abm::LocationType)random_type, mio::abm::LocationId(random_id), 0); - EXPECT_EQ(person.get_assigned_location((mio::abm::LocationType)random_type), mio::abm::LocationId(random_id)); + auto random_type = this->random_integer(0, (int)mio::abm::ActivityType::Count - 1); + person.set_assigned_location((mio::abm::ActivityType)random_type, mio::abm::LocationId(random_id), 0); + EXPECT_EQ(person.get_assigned_location((mio::abm::ActivityType)random_type, p_rng), + mio::abm::LocationId(random_id)); } // Boundary test cases: test with boundary LocationIds. - person.set_assigned_location(mio::abm::LocationType::Work, mio::abm::LocationId(0), 0); - EXPECT_EQ(person.get_assigned_location(mio::abm::LocationType::Work), mio::abm::LocationId(0)); + person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(0), 0); + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), mio::abm::LocationId(0)); - person.set_assigned_location(mio::abm::LocationType::Work, mio::abm::LocationId(std::numeric_limits::max()), + person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(std::numeric_limits::max()), 0); - EXPECT_EQ(person.get_assigned_location(mio::abm::LocationType::Work), + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), mio::abm::LocationId(std::numeric_limits::max())); } @@ -160,7 +167,7 @@ TEST_F(TestPerson, quarantine) infection_parameters.get().set_multiple({age_group_5_to_14}, true); infection_parameters.get().set_multiple({age_group_15_to_34, age_group_35_to_59}, true); - auto person = make_test_person(this->get_rng(), home, age_group_35_to_59, + auto person = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_35_to_59, mio::abm::InfectionState::InfectedSymptoms, t_morning, infection_parameters); auto rng_person = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); @@ -187,11 +194,11 @@ TEST_F(TestPerson, get_tested) mio::abm::TimePoint t(0); mio::abm::Location loc(mio::abm::LocationType::Home, 0, num_age_groups); - auto infected = - make_test_person(this->get_rng(), loc, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); - auto rng_infected = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), infected); - auto susceptible = - mio::abm::Person(this->get_rng(), loc.get_type(), loc.get_id(), loc.get_model_id(), age_group_15_to_34); + auto infected = make_test_person(this->get_rng(), loc, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms); + auto rng_infected = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), infected); + auto susceptible = mio::abm::Person(this->get_rng(), loc.get_type(), mio::abm::ActivityType::Home, loc.get_id(), + loc.get_model_id(), age_group_15_to_34); auto rng_suscetible = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), susceptible); auto pcr_parameters = params.get()[mio::abm::TestType::PCR]; @@ -253,11 +260,12 @@ TEST_F(TestPerson, getCells) mio::abm::Location home(mio::abm::LocationType::Home, 0, 6, 1); mio::abm::Location location(mio::abm::LocationType::PublicTransport, 1, 6, 0, 7); // Create a test person at the home location. - auto person = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); + auto person = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms); // Move the person to a new location with specified cells (3, 5). - EXPECT_TRUE(mio::abm::change_location(person, location, mio::abm::TransportMode::Unknown, {3, 5})); + EXPECT_TRUE(mio::abm::change_location(person, location, mio::abm::ActivityType::Invalid, + mio::abm::TransportMode::Unknown, {3, 5})); // Check that the person's cell indices have been updated correctly. EXPECT_EQ(person.get_cells().size(), 2); @@ -276,8 +284,8 @@ TEST_F(TestPerson, interact) mio::abm::Location loc(mio::abm::LocationType::Home, 0, num_age_groups); mio::abm::TimePoint t(0); // Create a person and set up a random number generator specific to that person. - auto person = - mio::abm::Person(this->get_rng(), loc.get_type(), loc.get_id(), loc.get_model_id(), age_group_15_to_34); + auto person = mio::abm::Person(this->get_rng(), loc.get_type(), mio::abm::ActivityType::Home, loc.get_id(), + loc.get_model_id(), age_group_15_to_34); auto rng_person = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); auto dt = mio::abm::seconds(8640); //0.1 days // Simulate interaction and check that the person accumulates time at the location. @@ -309,13 +317,13 @@ TEST_F(TestPerson, getMaskProtectiveFactor) { auto t = mio::abm::TimePoint(0); mio::abm::Location location(mio::abm::LocationType::School, 0, 6); - auto person_community = make_test_person(this->get_rng(), location); + auto person_community = make_test_person(this->get_rng(), location, mio::abm::ActivityType::School); person_community.set_mask(mio::abm::MaskType::Community, t); - auto person_surgical = make_test_person(this->get_rng(), location); + auto person_surgical = make_test_person(this->get_rng(), location, mio::abm::ActivityType::School); person_surgical.set_mask(mio::abm::MaskType::Surgical, t); - auto person_ffp2 = make_test_person(this->get_rng(), location); + auto person_ffp2 = make_test_person(this->get_rng(), location, mio::abm::ActivityType::School); person_ffp2.set_mask(mio::abm::MaskType::FFP2, t); - auto person_without = make_test_person(this->get_rng(), location); + auto person_without = make_test_person(this->get_rng(), location, mio::abm::ActivityType::School); person_without.set_mask(mio::abm::MaskType::None, t); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); @@ -335,10 +343,10 @@ TEST_F(TestPerson, getMaskProtectiveFactor) */ TEST_F(TestPerson, getLatestProtection) { - auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); - auto person = mio::abm::Person(this->get_rng(), location.get_type(), location.get_id(), location.get_model_id(), - age_group_15_to_34); - auto prng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); + auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); + auto person = mio::abm::Person(this->get_rng(), location.get_type(), mio::abm::ActivityType::School, + location.get_id(), location.get_model_id(), age_group_15_to_34); + auto prng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); auto t = mio::abm::TimePoint(0); @@ -362,7 +370,8 @@ TEST_F(TestPerson, getLatestProtection) */ TEST_F(TestPerson, rng) { - auto p = mio::abm::Person(this->get_rng(), mio::abm::LocationType::Home, 0, 0, age_group_35_to_59, 13); + auto p = mio::abm::Person(this->get_rng(), mio::abm::LocationType::Home, mio::abm::ActivityType::Home, 0, 0, + age_group_35_to_59, 13); EXPECT_EQ(p.get_rng_counter(), mio::Counter(0)); @@ -381,7 +390,7 @@ TEST_F(TestPerson, rng) TEST_F(TestPerson, addAndGetTestResult) { mio::abm::Location location(mio::abm::LocationType::School, 0, num_age_groups); - auto person = make_test_person(this->get_rng(), location); + auto person = make_test_person(this->get_rng(), location, mio::abm::ActivityType::School); auto t = mio::abm::TimePoint(0); // Tests if m_test_results initialized correctly EXPECT_EQ(person.get_test_result(mio::abm::TestType::Generic).time_of_testing, @@ -409,7 +418,7 @@ TEST_F(TestPerson, isCompliant) mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); // Create test person and associated random number generator - auto person = make_test_person(this->get_rng(), home); + auto person = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home); auto rng_person = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); // Test cases with a complete truth table for compliance levels diff --git a/cpp/tests/test_abm_simulation.cpp b/cpp/tests/test_abm_simulation.cpp index 8fd25b66aa..5bef2c7072 100644 --- a/cpp/tests/test_abm_simulation.cpp +++ b/cpp/tests/test_abm_simulation.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/location_type.h" #include "abm/simulation.h" #include "abm/result_simulation.h" @@ -33,15 +34,15 @@ TEST(TestSimulation, advance_random) auto model = mio::abm::Model(num_age_groups); auto location1 = model.add_location(mio::abm::LocationType::School); auto location2 = model.add_location(mio::abm::LocationType::School); - auto p1 = model.add_person(location1, age_group_5_to_14); - auto p2 = model.add_person(location1, age_group_5_to_14); - auto p3 = model.add_person(location2, age_group_5_to_14); - auto p4 = model.add_person(location2, age_group_5_to_14); + auto p1 = model.add_person(location1, age_group_5_to_14, mio::abm::ActivityType::School); + auto p2 = model.add_person(location1, age_group_5_to_14, mio::abm::ActivityType::School); + auto p3 = model.add_person(location2, age_group_5_to_14, mio::abm::ActivityType::School); + auto p4 = model.add_person(location2, age_group_5_to_14, mio::abm::ActivityType::School); - model.assign_location(p1, location1); - model.assign_location(p2, location1); - model.assign_location(p3, location2); - model.assign_location(p4, location2); + model.assign_location(p1, location1, mio::abm::ActivityType::School); + model.assign_location(p2, location1, mio::abm::ActivityType::School); + model.assign_location(p3, location2, mio::abm::ActivityType::School); + model.assign_location(p4, location2, mio::abm::ActivityType::School); auto sim = mio::abm::Simulation(mio::abm::TimePoint(0), std::move(model)); @@ -78,39 +79,49 @@ TEST(TestSimulation, advanceWithCommonHistory) auto icu_id = model.add_location(mio::abm::LocationType::ICU); auto hospital_id = model.add_location(mio::abm::LocationType::Hospital); auto school_id = model.add_location(mio::abm::LocationType::School); - auto social_id = model.add_location(mio::abm::LocationType::SocialEvent); + auto social_id = model.add_location(mio::abm::LocationType::Recreation); auto basics_id = model.add_location(mio::abm::LocationType::BasicsShop); auto public_id = model.add_location(mio::abm::LocationType::PublicTransport); - auto person1 = add_test_person(model, home_id, age_group_5_to_14, mio::abm::InfectionState::Exposed); - auto person2 = add_test_person(model, home_id, age_group_15_to_34, mio::abm::InfectionState::Exposed); - auto person3 = add_test_person(model, home_id, age_group_35_to_59, mio::abm::InfectionState::Dead); - - model.assign_location(person1, home_id); - model.assign_location(person2, home_id); - model.assign_location(person3, home_id); - model.assign_location(person1, school_id); - model.assign_location(person2, work_id); - model.assign_location(person2, icu_id); - model.assign_location(person2, hospital_id); - model.assign_location(person1, social_id); - model.assign_location(person2, social_id); - model.assign_location(person3, social_id); - model.assign_location(person1, basics_id); - model.assign_location(person2, basics_id); - model.assign_location(person3, basics_id); - model.assign_location(person2, public_id); + auto person1 = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_5_to_14, + mio::abm::InfectionState::Exposed); + auto person2 = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Exposed); + auto person3 = add_test_person(model, home_id, mio::abm::ActivityType::Home, age_group_35_to_59, + mio::abm::InfectionState::Dead); + + model.assign_location(person1, home_id, mio::abm::ActivityType::Home); + model.assign_location(person2, home_id, mio::abm::ActivityType::Home); + model.assign_location(person3, home_id, mio::abm::ActivityType::Home); + model.assign_location(person1, school_id, mio::abm::ActivityType::School); + model.assign_location(person2, work_id, mio::abm::ActivityType::Work); + model.assign_location(person2, icu_id, mio::abm::ActivityType::ICU); + model.assign_location(person2, hospital_id, mio::abm::ActivityType::Hospital); + model.assign_location(person1, social_id, mio::abm::ActivityType::Recreation); + model.assign_location(person2, social_id, mio::abm::ActivityType::Recreation); + model.assign_location(person3, social_id, mio::abm::ActivityType::Recreation); + model.assign_location(person1, basics_id, mio::abm::ActivityType::BasicsShop); + model.assign_location(person2, basics_id, mio::abm::ActivityType::BasicsShop); + model.assign_location(person3, basics_id, mio::abm::ActivityType::BasicsShop); + model.assign_location(person2, public_id, mio::abm::ActivityType::Invalid); mio::abm::TripList& trip_list = model.get_trip_list(); // We add trips for person two to test the history and if it is working correctly - mio::abm::Trip trip1(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(2), home_id); - mio::abm::Trip trip2(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(3), home_id); - mio::abm::Trip trip3(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(4), home_id); - mio::abm::Trip trip4(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(5), home_id); - mio::abm::Trip trip5(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(6), home_id); - mio::abm::Trip trip6(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(7), home_id); - mio::abm::Trip trip7(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(8), home_id); + mio::abm::Trip trip1(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(2), home_id, + mio::abm::ActivityType::Home); + mio::abm::Trip trip2(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(3), home_id, + mio::abm::ActivityType::Home); + mio::abm::Trip trip3(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(4), home_id, + mio::abm::ActivityType::Home); + mio::abm::Trip trip4(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(5), home_id, + mio::abm::ActivityType::Home); + mio::abm::Trip trip5(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(6), home_id, + mio::abm::ActivityType::Home); + mio::abm::Trip trip6(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(7), home_id, + mio::abm::ActivityType::Home); + mio::abm::Trip trip7(static_cast(person2.get()), mio::abm::TimePoint(0) + mio::abm::hours(8), home_id, + mio::abm::ActivityType::Home); // Add to one vector auto trips = std::vector{trip1, trip2, trip3, trip4, trip5, trip6, trip7}; @@ -153,9 +164,9 @@ TEST(TestSimulation, ResultSimulation) // run a ResultSimulation on a minimal setup auto model = mio::abm::Model(num_age_groups); auto location = model.add_location(mio::abm::LocationType::Home); - auto person = model.add_person(location, age_group_15_to_34); + auto person = model.add_person(location, age_group_15_to_34, mio::abm::ActivityType::Home); - model.assign_location(person, location); + model.assign_location(person, location, mio::abm::ActivityType::Home); const auto t0 = mio::abm::TimePoint(0) + mio::abm::hours(100); const auto tmax = t0 + mio::abm::hours(50); diff --git a/cpp/tests/test_abm_testing_strategy.cpp b/cpp/tests/test_abm_testing_strategy.cpp index 64cbb88fc8..5a850cef48 100644 --- a/cpp/tests/test_abm_testing_strategy.cpp +++ b/cpp/tests/test_abm_testing_strategy.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/testing_strategy.h" #include "abm_helpers.h" #include "random_number_test.h" @@ -30,8 +31,8 @@ TEST_F(TestTestingCriteria, addRemoveAndEvaluateTestCriteria) // Create test locations and a person in a specific infection state. mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); mio::abm::Location work(mio::abm::LocationType::Work, 0, num_age_groups); - auto person = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); + auto person = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms); mio::abm::TimePoint t{0}; // Initialize testing criteria with no age group or infection state set. @@ -105,8 +106,8 @@ TEST_F(TestTestingScheme, runScheme) make_test_person(this->get_rng(), loc_home, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, start_date - test_params_pcr.required_time); auto rng_person1 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person1); - auto person2 = make_test_person(this->get_rng(), loc_home, age_group_15_to_34, mio::abm::InfectionState::Recovered, - start_date - test_params_pcr.required_time); + auto person2 = make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Recovered, start_date - test_params_pcr.required_time); auto rng_person2 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person2); // Mock uniform distribution to control random behavior in testing. @@ -154,8 +155,8 @@ TEST_F(TestTestingScheme, initAndRunTestingStrategy) make_test_person(this->get_rng(), loc_work, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, start_date - test_params_pcr.required_time); auto rng_person1 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person1); - auto person2 = make_test_person(this->get_rng(), loc_work, age_group_15_to_34, mio::abm::InfectionState::Recovered, - start_date - test_params_pcr.required_time); + auto person2 = make_test_person(this->get_rng(), loc_work, mio::abm::ActivityType::Work, age_group_15_to_34, + mio::abm::InfectionState::Recovered, start_date - test_params_pcr.required_time); auto rng_person2 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person2); // Mock uniform distribution to control random behavior in testing. @@ -190,14 +191,14 @@ TEST_F(TestTestingCriteria, testingCriteriaEdgeCases) mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); // Test with various infection states - auto person_exposed = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::Exposed); - auto person_symptoms = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); - auto person_no_symptoms = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); - auto person_recovered = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::Recovered); + auto person_exposed = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Exposed); + auto person_symptoms = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedSymptoms); + auto person_no_symptoms = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms); + auto person_recovered = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Recovered); mio::abm::TimePoint t{0}; @@ -217,14 +218,14 @@ TEST_F(TestTestingCriteria, testingCriteriaEdgeCases) auto testing_criteria_age = mio::abm::TestingCriteria(test_age_groups, {}); // Create persons with different age groups - auto person_young = - make_test_person(this->get_rng(), home, age_group_5_to_14, mio::abm::InfectionState::Susceptible); - auto person_adult = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::Susceptible); - auto person_older = - make_test_person(this->get_rng(), home, age_group_35_to_59, mio::abm::InfectionState::Susceptible); - auto person_senior = - make_test_person(this->get_rng(), home, age_group_60_to_79, mio::abm::InfectionState::Susceptible); + auto person_young = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_5_to_14, + mio::abm::InfectionState::Susceptible); + auto person_adult = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Susceptible); + auto person_older = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_35_to_59, + mio::abm::InfectionState::Susceptible); + auto person_senior = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_60_to_79, + mio::abm::InfectionState::Susceptible); // Should match only specified age groups EXPECT_EQ(testing_criteria_age.evaluate(person_young, t), false); @@ -236,12 +237,12 @@ TEST_F(TestTestingCriteria, testingCriteriaEdgeCases) auto testing_criteria_both = mio::abm::TestingCriteria(test_age_groups, test_infection_states); // Should match only when both criteria are met - auto person_adult_infected = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); - auto person_young_infected = - make_test_person(this->get_rng(), home, age_group_5_to_14, mio::abm::InfectionState::InfectedSymptoms); - auto person_adult_recovered = - make_test_person(this->get_rng(), home, age_group_15_to_34, mio::abm::InfectionState::Recovered); + auto person_adult_infected = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, + age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); + auto person_young_infected = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, + age_group_5_to_14, mio::abm::InfectionState::InfectedSymptoms); + auto person_adult_recovered = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, + age_group_15_to_34, mio::abm::InfectionState::Recovered); EXPECT_EQ(testing_criteria_both.evaluate(person_adult_infected, t), true); EXPECT_EQ(testing_criteria_both.evaluate(person_young_infected, t), false); @@ -289,7 +290,7 @@ TEST_F(TestTestingScheme, testingSchemeResultCaching) // Create test person and location mio::abm::Location loc_home(mio::abm::LocationType::Home, 0, num_age_groups); - auto person = make_test_person(this->get_rng(), loc_home, age_group_15_to_34, + auto person = make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, start_date); auto rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); @@ -342,13 +343,13 @@ TEST_F(TestTestingScheme, differentTestTypes) // Create test persons with different infection states mio::abm::Location loc_home(mio::abm::LocationType::Home, 0, num_age_groups); auto person_infected = - make_test_person(this->get_rng(), loc_home, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, - start_date - test_params_pcr.required_time); + make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, start_date - test_params_pcr.required_time); auto rng_infected = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person_infected); auto person_healthy = - make_test_person(this->get_rng(), loc_home, age_group_15_to_34, mio::abm::InfectionState::Susceptible, - start_date - test_params_pcr.required_time); + make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::Susceptible, start_date - test_params_pcr.required_time); auto rng_healthy = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person_healthy); // Mock uniform distribution to control test results @@ -420,11 +421,11 @@ TEST_F(TestTestingScheme, multipleSchemesCombination) // Add schemes to different location types test_strategy.add_scheme(mio::abm::LocationType::School, testing_scheme_children); test_strategy.add_scheme(mio::abm::LocationType::Work, testing_scheme_adults); - test_strategy.add_scheme(mio::abm::LocationType::SocialEvent, testing_scheme_seniors); + test_strategy.add_scheme(mio::abm::LocationType::Recreation, testing_scheme_seniors); // Also add multiple location types at once std::vector public_locations = {mio::abm::LocationType::BasicsShop, - mio::abm::LocationType::SocialEvent}; + mio::abm::LocationType::Recreation}; test_strategy.add_scheme(public_locations, testing_scheme_adults); // Create locations @@ -434,10 +435,10 @@ TEST_F(TestTestingScheme, multipleSchemesCombination) mio::abm::Location loc_shop(mio::abm::LocationType::BasicsShop, 3, num_age_groups); // Create persons of different age groups - auto child = make_test_person(this->get_rng(), loc_home, age_group_5_to_14, mio::abm::InfectionState::Susceptible, - start_date); - auto adult = make_test_person(this->get_rng(), loc_home, age_group_35_to_59, mio::abm::InfectionState::Susceptible, - start_date); + auto child = make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_5_to_14, + mio::abm::InfectionState::Susceptible, start_date); + auto adult = make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_35_to_59, + mio::abm::InfectionState::Susceptible, start_date); auto rng_child = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), child); auto rng_adult = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), adult); @@ -493,9 +494,9 @@ TEST_F(TestTestingScheme, locationSpecificSchemes) mio::abm::Location shop2(mio::abm::LocationType::BasicsShop, 43, num_age_groups); // Different ID // Create a test person - auto person = - make_test_person(this->get_rng(), shop1, age_group_15_to_34, mio::abm::InfectionState::Susceptible, start_date); - auto rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); + auto person = make_test_person(this->get_rng(), shop1, mio::abm::ActivityType::BasicsShop, age_group_15_to_34, + mio::abm::InfectionState::Susceptible, start_date); + auto rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); // Mock uniform distribution to control test results ScopedMockDistribution>>> mock_uniform_dist; @@ -539,9 +540,9 @@ TEST_F(TestTestingScheme, testCompliance) mio::abm::Location shop1(mio::abm::LocationType::BasicsShop, 42, num_age_groups); // Has the specific ID // Create a test person - auto person = - make_test_person(this->get_rng(), shop1, age_group_15_to_34, mio::abm::InfectionState::Susceptible, start_date); - auto rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); + auto person = make_test_person(this->get_rng(), shop1, mio::abm::ActivityType::BasicsShop, age_group_15_to_34, + mio::abm::InfectionState::Susceptible, start_date); + auto rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); person.set_compliance(mio::abm::InterventionType::Testing, 0.1); // Set compliance for testing // Mock uniform distribution to control test results diff --git a/cpp/tests/test_graph_abm.cpp b/cpp/tests/test_graph_abm.cpp index e26fd7f6b6..40ed67981d 100644 --- a/cpp/tests/test_graph_abm.cpp +++ b/cpp/tests/test_graph_abm.cpp @@ -18,6 +18,7 @@ * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/location.h" #include "abm/location_id.h" #include "abm/mobility_data.h" @@ -52,11 +53,11 @@ TEST(TestGraphAbm, test_advance_node) auto home_id = model.add_location(mio::abm::LocationType::Home); auto& home = model.get_location(home_id); auto work = mio::abm::Location(mio::abm::LocationType::Work, mio::abm::LocationId(0), size_t(1), 2); - auto pid = model.add_person(home_id, mio::AgeGroup(0)); + auto pid = model.add_person(home_id, mio::AgeGroup(0), mio::abm::ActivityType::Home); auto index = model.get_person_index(pid); auto& p = model.get_person(pid); - p.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p.set_assigned_location(work.get_type(), work.get_id(), 2); + p.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p.set_assigned_location(mio::abm::ActivityType::Work, work.get_id(), 2); mio::ABMSimulationNode node(MockHistory{}, t, std::move(model)); EXPECT_EQ(node.get_simulation().get_model().get_activeness_statuses()[index], true); node.advance(t, dt); @@ -87,8 +88,8 @@ TEST(TestGraphAbm, test_apply_mobility) auto home_id = model1.add_location(mio::abm::LocationType::Home); auto work_id_2 = model2.add_location(mio::abm::LocationType::Work); auto work_id_3 = model3.add_location(mio::abm::LocationType::Work); - auto event_id_1 = model1.add_location(mio::abm::LocationType::SocialEvent); - auto event_id_2 = model2.add_location(mio::abm::LocationType::SocialEvent); + auto event_id_1 = model1.add_location(mio::abm::LocationType::Recreation); + auto event_id_2 = model2.add_location(mio::abm::LocationType::Recreation); auto& work_1 = model1.get_location(work_id_1); auto& work_2 = model2.get_location(work_id_2); auto& work_3 = model3.get_location(work_id_3); @@ -100,32 +101,31 @@ TEST(TestGraphAbm, test_apply_mobility) EXPECT_EQ(work_2.get_model_id(), 2); EXPECT_EQ(work_3.get_model_id(), 3); - auto p1_id = model1.add_person(home_id, mio::AgeGroup(0)); - auto p2_id = model1.add_person(home_id, mio::AgeGroup(0)); - auto p3_id = model1.add_person(home_id, mio::AgeGroup(1)); - auto p4_id = model1.add_person(home_id, mio::AgeGroup(1)); - auto p5_id = model1.add_person(home_id, mio::AgeGroup(0)); + auto p1_id = model1.add_person(home_id, mio::AgeGroup(0), mio::abm::ActivityType::Home); + auto p2_id = model1.add_person(home_id, mio::AgeGroup(0), mio::abm::ActivityType::Home); + auto p3_id = model1.add_person(home_id, mio::AgeGroup(1), mio::abm::ActivityType::Home); + auto p4_id = model1.add_person(home_id, mio::AgeGroup(1), mio::abm::ActivityType::Home); + auto p5_id = model1.add_person(home_id, mio::AgeGroup(0), mio::abm::ActivityType::Home); auto& p1 = model1.get_person(p1_id); auto& p2 = model1.get_person(p2_id); auto& p3 = model1.get_person(p3_id); auto& p4 = model1.get_person(p4_id); auto& p5 = model1.get_person(p5_id); - p1.set_assigned_location(work_1.get_type(), work_1.get_id(), work_1.get_model_id()); - p2.set_assigned_location(work_2.get_type(), work_2.get_id(), work_2.get_model_id()); - p5.set_assigned_location(work_3.get_type(), work_3.get_id(), work_3.get_model_id()); - p1.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p2.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p3.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p4.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p5.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p3.set_assigned_location(event_1.get_type(), event_1.get_id(), event_1.get_model_id()); - p4.set_assigned_location(event_2.get_type(), event_2.get_id(), event_2.get_model_id()); - + p1.set_assigned_location(mio::abm::ActivityType::Work, work_1.get_id(), work_1.get_model_id()); + p2.set_assigned_location(mio::abm::ActivityType::Work, work_2.get_id(), work_2.get_model_id()); + p5.set_assigned_location(mio::abm::ActivityType::Work, work_3.get_id(), work_3.get_model_id()); + p1.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p2.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p3.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p4.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p5.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p3.set_assigned_location(mio::abm::ActivityType::Recreation, event_1.get_id(), event_1.get_model_id()); + p4.set_assigned_location(mio::abm::ActivityType::Recreation, event_2.get_id(), event_2.get_model_id()); mio::abm::TripList& trips = model1.get_trip_list(); - mio::abm::Trip trip1(p3.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(8), event_id_1, model1.get_id(), - mio::abm::TransportMode::Unknown, {}); - mio::abm::Trip trip2(p4.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(8), event_id_2, model2.get_id(), - mio::abm::TransportMode::Unknown, {}); + mio::abm::Trip trip1(p3.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(8), event_id_1, + mio::abm::ActivityType::Recreation, model1.get_id(), mio::abm::TransportMode::Unknown, {}); + mio::abm::Trip trip2(p4.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(8), event_id_2, + mio::abm::ActivityType::Recreation, model2.get_id(), mio::abm::TransportMode::Unknown, {}); auto tripsvec = std::vector{trip1, trip2}; trips.add_trips(tripsvec); @@ -201,22 +201,22 @@ TEST(TestGraphABM, mask_compliance) //school and work require FFP2 masks school.set_required_mask(mio::abm::MaskType::FFP2); work.set_required_mask(mio::abm::MaskType::FFP2); - auto p_id1 = model.add_person(home_id, mio::AgeGroup(1)); - auto p_id2 = model.add_person(home_id, mio::AgeGroup(0)); + auto p_id1 = model.add_person(home_id, mio::AgeGroup(1), mio::abm::ActivityType::Home); + auto p_id2 = model.add_person(home_id, mio::AgeGroup(0), mio::abm::ActivityType::Home); auto& p1 = model.get_person(p_id1); auto& p2 = model.get_person(p_id2); - p1.set_assigned_location(work.get_type(), work.get_id(), work.get_model_id()); - p1.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); - p2.set_assigned_location(school.get_type(), school.get_id(), school.get_model_id()); - p2.set_assigned_location(home.get_type(), home.get_id(), home.get_model_id()); + p1.set_assigned_location(mio::abm::ActivityType::Work, work.get_id(), work.get_model_id()); + p1.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); + p2.set_assigned_location(mio::abm::ActivityType::School, school.get_id(), school.get_model_id()); + p2.set_assigned_location(mio::abm::ActivityType::Home, home.get_id(), home.get_model_id()); //person is not compliant with mask p1.set_compliance(mio::abm::InterventionType::Mask, 0.0); p2.set_compliance(mio::abm::InterventionType::Mask, 0.0); //add trips for p2 mio::abm::TripList& trips = model.get_trip_list(); - mio::abm::Trip trip1(p2.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(8), school_id, model.get_id(), - mio::abm::TransportMode::Unknown, {}); + mio::abm::Trip trip1(p2.get_id(), mio::abm::TimePoint(0) + mio::abm::hours(8), school_id, + mio::abm::ActivityType::School, model.get_id(), mio::abm::TransportMode::Unknown, {}); trips.add_trips({trip1}); @@ -244,8 +244,8 @@ TEST(TestGraphABM, test_get_person) auto model = mio::GraphABModel(size_t(2), 0, std::vector{&mio::abm::go_to_work}); auto home = model.add_location(mio::abm::LocationType::Home); auto work = model.add_location(mio::abm::LocationType::Work); - auto pid1 = model.add_person(home, mio::AgeGroup(0)); - auto pid2 = model.add_person(work, mio::AgeGroup(1)); + auto pid1 = model.add_person(home, mio::AgeGroup(0), mio::abm::ActivityType::Home); + auto pid2 = model.add_person(work, mio::AgeGroup(1), mio::abm::ActivityType::Work); auto& p1 = model.get_person(pid1); EXPECT_EQ(p1.get_location(), home); From f9f7b35dad5afe7386cdbd6af08c8634df172a09 Mon Sep 17 00:00:00 2001 From: jubicker <113909589+jubicker@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:37:19 +0200 Subject: [PATCH 2/5] fix build bugs --- cpp/examples/abm_parameter_study.cpp | 13 ++-- cpp/models/graph_abm/graph_abm_mobility.h | 2 +- cpp/tests/test_abm_lockdown_rules.cpp | 12 ++-- cpp/tests/test_abm_mobility_rules.cpp | 88 +++++++++++------------ cpp/tests/test_abm_person.cpp | 16 ++--- cpp/tests/test_abm_serialization.cpp | 25 ++++--- cpp/tests/test_abm_testing_strategy.cpp | 8 +-- 7 files changed, 86 insertions(+), 78 deletions(-) diff --git a/cpp/examples/abm_parameter_study.cpp b/cpp/examples/abm_parameter_study.cpp index 1f8627532a..4c3996a38e 100644 --- a/cpp/examples/abm_parameter_study.cpp +++ b/cpp/examples/abm_parameter_study.cpp @@ -17,6 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/result_simulation.h" #include "abm/household.h" #include "abm/lockdown_rules.h" @@ -143,17 +144,17 @@ mio::abm::Model make_model(const mio::RandomNumberGenerator& rng) for (auto& person : model.get_persons()) { const auto id = person.get_id(); //assign shop and event - model.assign_location(id, event); - model.assign_location(id, shop); + model.assign_location(id, event, mio::abm::ActivityType::Recreation); + model.assign_location(id, shop, mio::abm::ActivityType::BasicsShop); //assign hospital and ICU - model.assign_location(id, hospital); - model.assign_location(id, icu); + model.assign_location(id, hospital, mio::abm::ActivityType::Hospital); + model.assign_location(id, icu, mio::abm::ActivityType::ICU); //assign work/school to people depending on their age if (person.get_age() == age_group_5_to_14) { - model.assign_location(id, school); + model.assign_location(id, school, mio::abm::ActivityType::School); } if (person.get_age() == age_group_15_to_34 || person.get_age() == age_group_35_to_59) { - model.assign_location(id, work); + model.assign_location(id, work, mio::abm::ActivityType::Work); } } diff --git a/cpp/models/graph_abm/graph_abm_mobility.h b/cpp/models/graph_abm/graph_abm_mobility.h index f4b8e62218..f36f7f82f0 100644 --- a/cpp/models/graph_abm/graph_abm_mobility.h +++ b/cpp/models/graph_abm/graph_abm_mobility.h @@ -132,7 +132,7 @@ class ABMMobilityEdge target_type = model_to.get_location(target_id).get_type(); } //set correct location for person - person.set_location(target_type, target_id, model_to.get_id()); + person.set_location(person.get_activity_type(), target_type, target_id, model_to.get_id()); //add person to model_to model_to.add_person(std::move(person)); //remove person from model_from diff --git a/cpp/tests/test_abm_lockdown_rules.cpp b/cpp/tests/test_abm_lockdown_rules.cpp index d0de9c3a22..e004b95375 100644 --- a/cpp/tests/test_abm_lockdown_rules.cpp +++ b/cpp/tests/test_abm_lockdown_rules.cpp @@ -75,9 +75,9 @@ TEST_F(TestLockdownRules, school_closure) // Test that p1 stays home and p2 goes to school auto p1_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p1); - EXPECT_EQ(mio::abm::go_to_school(p1_rng, p1, t_morning, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_school(p1_rng, p1, t_morning, dt, params), mio::abm::ActivityType::Home); auto p2_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p2); - EXPECT_EQ(mio::abm::go_to_school(p2_rng, p2, t_morning, dt, params), mio::abm::LocationType::School); + EXPECT_EQ(mio::abm::go_to_school(p2_rng, p2, t_morning, dt, params), mio::abm::ActivityType::School); } /** @@ -124,7 +124,7 @@ TEST_F(TestLockdownRules, school_opening) // Test that after reopening, the person goes to school auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p); - EXPECT_EQ(mio::abm::go_to_school(p_rng, p, t_morning, dt, params), mio::abm::LocationType::School); + EXPECT_EQ(mio::abm::go_to_school(p_rng, p, t_morning, dt, params), mio::abm::ActivityType::School); } /** @@ -172,9 +172,9 @@ TEST_F(TestLockdownRules, home_office) // Check that person1 goes to work and person2 stays at home. auto p1_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person1); - EXPECT_EQ(mio::abm::go_to_work(p1_rng, person1, t_morning, dt, params), mio::abm::LocationType::Work); + EXPECT_EQ(mio::abm::go_to_work(p1_rng, person1, t_morning, dt, params), mio::abm::ActivityType::Work); auto p2_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person2); - EXPECT_EQ(mio::abm::go_to_work(p2_rng, person2, t_morning, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_work(p2_rng, person2, t_morning, dt, params), mio::abm::ActivityType::Home); } /** @@ -218,7 +218,7 @@ TEST_F(TestLockdownRules, no_home_office) // Test that after removing the home office rules, p goes back to the office. auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p); - EXPECT_EQ(mio::abm::go_to_work(p_rng, p, t_morning, dt, params), mio::abm::LocationType::Work); + EXPECT_EQ(mio::abm::go_to_work(p_rng, p, t_morning, dt, params), mio::abm::ActivityType::Work); } /** diff --git a/cpp/tests/test_abm_mobility_rules.cpp b/cpp/tests/test_abm_mobility_rules.cpp index 2280df17e7..08aed7d2b9 100644 --- a/cpp/tests/test_abm_mobility_rules.cpp +++ b/cpp/tests/test_abm_mobility_rules.cpp @@ -32,9 +32,9 @@ using TestMobilityRules = RandomNumberTest; TEST_F(TestMobilityRules, random_mobility) { int t = 0, dt = 1; - auto default_type = mio::abm::LocationType::Cemetery; - auto person = - mio::abm::Person(this->get_rng(), default_type, mio::abm::ActivityType::Cemetery, 0, 0, age_group_15_to_34); + auto default_type = mio::abm::ActivityType::Cemetery; + auto person = mio::abm::Person(this->get_rng(), mio::abm::LocationType::Cemetery, mio::abm::ActivityType::Cemetery, + 0, 0, age_group_15_to_34); auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); auto params = mio::abm::Parameters(num_age_groups); @@ -106,11 +106,11 @@ TEST_F(TestMobilityRules, student_goes_to_school) params.get()[age_group_35_to_59] = true; // Test that child goes to school - EXPECT_EQ(mio::abm::go_to_school(child_rng, p_child, t_morning, dt, params), mio::abm::LocationType::School); + EXPECT_EQ(mio::abm::go_to_school(child_rng, p_child, t_morning, dt, params), mio::abm::ActivityType::School); // Test that adult does not go to school - EXPECT_EQ(mio::abm::go_to_school(adult_rng, p_adult, t_morning, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_school(adult_rng, p_adult, t_morning, dt, params), mio::abm::ActivityType::Home); // Test that child goes back home after school - EXPECT_EQ(mio::abm::go_to_school(child_rng, p_child, t_weekend, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_school(child_rng, p_child, t_weekend, dt, params), mio::abm::ActivityType::Home); } /** @@ -161,16 +161,16 @@ TEST_F(TestMobilityRules, students_go_to_school_in_different_times) // Mock randomness ensures children leave home at various school start times. EXPECT_EQ( mio::abm::go_to_school(rng_child_goes_to_school_at_6, p_child_goes_to_school_at_6, t_morning_6, dt, params), - mio::abm::LocationType::School); + mio::abm::ActivityType::School); EXPECT_EQ( mio::abm::go_to_school(rng_child_goes_to_school_at_6, p_child_goes_to_school_at_6, t_morning_8, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); EXPECT_EQ( mio::abm::go_to_school(rng_child_goes_to_school_at_8, p_child_goes_to_school_at_8, t_morning_6, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); EXPECT_EQ( mio::abm::go_to_school(rng_child_goes_to_school_at_8, p_child_goes_to_school_at_8, t_morning_8, dt, params), - mio::abm::LocationType::School); + mio::abm::ActivityType::School); } /** @@ -230,17 +230,17 @@ TEST_F(TestMobilityRules, students_go_to_school_in_different_times_with_smaller_ // Check that the first student goes to school at 6:00 AM EXPECT_EQ( mio::abm::go_to_school(rng_child_goes_to_school_at_6, p_child_goes_to_school_at_6, t_morning_6, dt, params), - mio::abm::LocationType::School); + mio::abm::ActivityType::School); EXPECT_EQ( mio::abm::go_to_school(rng_child_goes_to_school_at_6, p_child_goes_to_school_at_6, t_morning_8_30, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); // Check that the second student goes to school at 8:30 AM EXPECT_EQ(mio::abm::go_to_school(rng_child_goes_to_school_at_8_30, p_child_goes_to_school_at_8_30, t_morning_6, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); EXPECT_EQ(mio::abm::go_to_school(rng_child_goes_to_school_at_8_30, p_child_goes_to_school_at_8_30, t_morning_8_30, dt, params), - mio::abm::LocationType::School); + mio::abm::ActivityType::School); } /** * @brief Test return home from school. @@ -258,7 +258,7 @@ TEST_F(TestMobilityRules, school_return) // Ensure that the child returns home after school is over EXPECT_EQ(mio::abm::go_to_school(rng_child, p_child, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); } /** @@ -302,11 +302,11 @@ TEST_F(TestMobilityRules, worker_goes_to_work) params.get()[age_group_35_to_59] = true; // Check that the retiree (age group 60-79) should stay home and not go to work. - EXPECT_EQ(mio::abm::go_to_work(rng_retiree, p_retiree, t_morning, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_work(rng_retiree, p_retiree, t_morning, dt, params), mio::abm::ActivityType::Home); // Check that the adult (age group 15-34) should go to work at 8:00 AM. - EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_morning, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_morning, dt, params), mio::abm::ActivityType::Home); // Check that during the night (4:00 AM), the adult should stay home and not go to work. - EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_night, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_night, dt, params), mio::abm::ActivityType::Home); } /** @@ -352,11 +352,11 @@ TEST_F(TestMobilityRules, worker_goes_to_work_with_non_dividable_timespan) params.get()[age_group_35_to_59] = true; // Check that the retiree (age group 60-79) should stay home and not go to work even with non-dividable time step. - EXPECT_EQ(mio::abm::go_to_work(rng_retiree, p_retiree, t_morning, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_work(rng_retiree, p_retiree, t_morning, dt, params), mio::abm::ActivityType::Home); // Check that the adult (age group 15-34) should still go to work at 8:00 AM even with the non-dividable time step. - EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_morning, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_morning, dt, params), mio::abm::ActivityType::Home); // Check that during the night (4:00 AM), the adult should stay home and not go to work even with the non-dividable time step. - EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_night, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t_night, dt, params), mio::abm::ActivityType::Home); } /** @@ -410,22 +410,22 @@ TEST_F(TestMobilityRules, workers_go_to_work_in_different_times) // Check that the worker going to work at 6 AM goes to work EXPECT_EQ(mio::abm::go_to_work(rng_adult_goes_to_work_at_6, p_adult_goes_to_work_at_6, t_morning_6, dt, params), - mio::abm::LocationType::Work); + mio::abm::ActivityType::Work); // Check that the worker going to work at 6 AM stays home at 8 AM (since they are already at work) EXPECT_EQ(mio::abm::go_to_work(rng_adult_goes_to_work_at_6, p_adult_goes_to_work_at_6, t_morning_8, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); // Check that the worker going to work at 6 AM returns home at night EXPECT_EQ(mio::abm::go_to_work(rng_adult_goes_to_work_at_6, p_adult_goes_to_work_at_6, t_night, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); // Check that the worker going to work at 8 AM stays home at 6 AM EXPECT_EQ(mio::abm::go_to_work(rng_adult_goes_to_work_at_8, p_adult_goes_to_work_at_8, t_morning_6, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); // Check that the worker going to work at 8 AM goes to work at 8 AM EXPECT_EQ(mio::abm::go_to_work(rng_adult_goes_to_work_at_8, p_adult_goes_to_work_at_8, t_morning_8, dt, params), - mio::abm::LocationType::Work); + mio::abm::ActivityType::Work); // Check that the worker going to work at 8 AM returns home at night EXPECT_EQ(mio::abm::go_to_work(rng_adult_goes_to_work_at_8, p_adult_goes_to_work_at_8, t_night, dt, params), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); } /** @@ -443,7 +443,7 @@ TEST_F(TestMobilityRules, work_return) auto dt = mio::abm::hours(1); // Test that the worker, who is currently at work, goes home after 5 PM EXPECT_EQ(mio::abm::go_to_work(rng_adult, p_adult, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); } /** @@ -464,14 +464,14 @@ TEST_F(TestMobilityRules, quarantine) p_inf1.get_tested(rng_inf1, t, test_params); // Check detected infected person quarantines at home EXPECT_EQ(mio::abm::go_to_quarantine(rng_inf1, p_inf1, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); auto p_inf2 = make_test_person(this->get_rng(), work, mio::abm::ActivityType::Work, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms, t); auto rng_inf2 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_inf2); // Check that undetected infected person does not quaratine EXPECT_EQ(mio::abm::go_to_quarantine(rng_inf2, p_inf2, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Work); + mio::abm::ActivityType::Work); auto p_inf3 = make_test_person(this->get_rng(), hospital, mio::abm::ActivityType::Hospital, age_group_15_to_34, mio::abm::InfectionState::InfectedSevere, t); @@ -479,7 +479,7 @@ TEST_F(TestMobilityRules, quarantine) p_inf1.get_tested(rng_inf3, t, test_params); // Check that detected infected person does not leave hospital to quarantine EXPECT_EQ(mio::abm::go_to_quarantine(rng_inf3, p_inf3, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Hospital); + mio::abm::ActivityType::Hospital); } /** @@ -496,14 +496,14 @@ TEST_F(TestMobilityRules, hospital) // Ensure person goes to the hospital when severely infected EXPECT_EQ(mio::abm::go_to_hospital(rng_inf, p_inf, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Hospital); + mio::abm::ActivityType::Hospital); auto p_car = make_test_person(this->get_rng(), home, mio::abm::ActivityType::Home, age_group_15_to_34, mio::abm::InfectionState::InfectedSymptoms); auto rng_car = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_car); // Ensure person has infection symptoms still stay at home EXPECT_EQ(mio::abm::go_to_hospital(rng_car, p_car, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); } /** @@ -530,13 +530,13 @@ TEST_F(TestMobilityRules, go_shopping) // Check that an infected person stays in the hospital and doesn't go shopping EXPECT_EQ(mio::abm::go_to_shop(rng_hosp, p_hosp, t_weekday, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Hospital); + mio::abm::ActivityType::Hospital); // Check that a person at home doesn't go shopping on a Sunday EXPECT_EQ(mio::abm::go_to_shop(rng_home, p_home, t_sunday, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); // Check that a person at home doesn't go shopping on a Sunday EXPECT_EQ(mio::abm::go_to_shop(rng_home, p_home, t_night, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); // Mocking the random distribution to simulate a person going shopping on a weekday ScopedMockDistribution>>> @@ -544,7 +544,7 @@ TEST_F(TestMobilityRules, go_shopping) EXPECT_CALL(mock_exponential_dist.get_mock(), invoke).Times(1).WillOnce(testing::Return(0.01)); // Test that a person goes to a basic shop on a weekday at 9 AM EXPECT_EQ(mio::abm::go_to_shop(rng_home, p_home, t_weekday, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::BasicsShop); + mio::abm::ActivityType::BasicsShop); } /** @@ -566,7 +566,7 @@ TEST_F(TestMobilityRules, shop_return) // After spending sufficient time at the shop, the person should return home EXPECT_EQ(mio::abm::go_to_shop(rng_p, p, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); } /** @@ -627,7 +627,7 @@ TEST_F(TestMobilityRules, event_return) // Simulate the person spending 3 hours at the social event p.add_time_at_location(dt); // After spending the time at the social event, the person should return home - EXPECT_EQ(mio::abm::go_to_recreation(rng_p, p, t, dt, params), mio::abm::LocationType::Home); + EXPECT_EQ(mio::abm::go_to_recreation(rng_p, p, t, dt, params), mio::abm::ActivityType::Home); } /** @@ -644,7 +644,7 @@ TEST_F(TestMobilityRules, icu) // Ensure critically infected person goes to the ICU EXPECT_EQ(mio::abm::go_to_icu(rng_hosp, p_hosp, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::ICU); + mio::abm::ActivityType::ICU); mio::abm::Location work(mio::abm::LocationType::Work, 1, num_age_groups); auto p_work = make_test_person(this->get_rng(), work, mio::abm::ActivityType::Work, age_group_15_to_34, @@ -652,7 +652,7 @@ TEST_F(TestMobilityRules, icu) auto rng_work = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_work); // Ensure infected with symptions person can still go to work EXPECT_EQ(mio::abm::go_to_icu(rng_work, p_work, t, dt, mio::abm::Parameters(num_age_groups)), - mio::abm::LocationType::Work); + mio::abm::ActivityType::Work); } /** @@ -671,9 +671,9 @@ TEST_F(TestMobilityRules, recover) auto rng_inf = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_inf); // Ensure recovered person returns home and infected severe person stay in hospital EXPECT_EQ(mio::abm::return_home_when_recovered(rng_rec, p_rec, t, dt, {num_age_groups}), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); EXPECT_EQ(mio::abm::return_home_when_recovered(rng_inf, p_inf, t, dt, {num_age_groups}), - mio::abm::LocationType::Hospital); + mio::abm::ActivityType::Hospital); } /** @@ -688,5 +688,5 @@ TEST_F(TestMobilityRules, dead) mio::abm::InfectionState::Dead, t); auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), p_dead); - EXPECT_EQ(mio::abm::get_buried(p_rng, p_dead, t, dt, {num_age_groups}), mio::abm::LocationType::Cemetery); + EXPECT_EQ(mio::abm::get_buried(p_rng, p_dead, t, dt, {num_age_groups}), mio::abm::ActivityType::Cemetery); } diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index 9cf8e1eec8..0c2aa65acb 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -106,27 +106,27 @@ TEST_F(TestPerson, setGetAssignedLocation) auto p_rng = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person); // Assign and verify a location for the person. person.set_assigned_location(mio::abm::ActivityType::Work, location.get_id(), location.get_model_id()); - EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), mio::abm::LocationId(2)); + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, mio::abm::LocationId(2)); // Change the assigned location and verify. person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(4), 0); - EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), mio::abm::LocationId(4)); + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, mio::abm::LocationId(4)); // Fuzzing: assign random valid LocationId values and verify correctness. for (int i = 0; i < 100; ++i) { auto random_id = this->random_integer(0, std::numeric_limits::max()); auto random_type = this->random_integer(0, (int)mio::abm::ActivityType::Count - 1); person.set_assigned_location((mio::abm::ActivityType)random_type, mio::abm::LocationId(random_id), 0); - EXPECT_EQ(person.get_assigned_location((mio::abm::ActivityType)random_type, p_rng), + EXPECT_EQ(person.get_assigned_location((mio::abm::ActivityType)random_type, p_rng).first, mio::abm::LocationId(random_id)); } // Boundary test cases: test with boundary LocationIds. person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(0), 0); - EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), mio::abm::LocationId(0)); + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, mio::abm::LocationId(0)); person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(std::numeric_limits::max()), 0); - EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng), + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, mio::abm::LocationId(std::numeric_limits::max())); } @@ -175,13 +175,13 @@ TEST_F(TestPerson, quarantine) person.get_tested(rng_person, t_morning, test_params); EXPECT_EQ(person.get_infection_state(t_morning), mio::abm::InfectionState::InfectedSymptoms); EXPECT_EQ(mio::abm::go_to_work(rng_person, person, t_morning, dt, infection_parameters), - mio::abm::LocationType::Home); + mio::abm::ActivityType::Home); EXPECT_EQ(person.get_infection_state(t_morning + dt), mio::abm::InfectionState::Recovered); // Test removal from quarantine. person.remove_quarantine(); EXPECT_EQ(mio::abm::go_to_work(rng_person, person, t_morning, dt, infection_parameters), - mio::abm::LocationType::Work); + mio::abm::ActivityType::Work); } /** @@ -300,7 +300,7 @@ TEST_F(TestPerson, setWearMask) { auto t = mio::abm::TimePoint(0); mio::abm::Location location(mio::abm::LocationType::School, 0, num_age_groups); - auto person = make_test_person(this->get_rng(), location); + auto person = make_test_person(this->get_rng(), location, mio::abm::ActivityType::School); // Test setting and verifying different mask types. person.set_mask(mio::abm::MaskType::None, t); diff --git a/cpp/tests/test_abm_serialization.cpp b/cpp/tests/test_abm_serialization.cpp index 7fd48dda52..dffa6e7495 100644 --- a/cpp/tests/test_abm_serialization.cpp +++ b/cpp/tests/test_abm_serialization.cpp @@ -35,6 +35,7 @@ #include "models/abm/model.h" #include #include +#include #ifdef MEMILIO_HAS_JSONCPP @@ -83,6 +84,7 @@ TEST(TestAbmSerialization, Trip) reference_json["destination"] = Json::UInt(i++); reference_json["model_id"] = Json::Int(i++); reference_json["trip_mode"] = Json::UInt(i++); + reference_json["activity"] = Json::UInt(i++); test_json_serialization(reference_json); } @@ -190,18 +192,23 @@ TEST(TestAbmSerialization, Person) return mio::serialize_json(values).value(); }; + auto json_uint_array_array = [](std::vector> values) { + return mio::serialize_json(values).value(); + }; + unsigned i = 1; // counter s.t. members have different values Json::Value reference_json; - reference_json["age_group"] = Json::UInt(i++); - reference_json["assigned_locations"] = json_uint_array({i++, i++, i++, i++, i++, i++, i++, i++, i++, i++, i++}); - reference_json["cells"] = json_uint_array({i++}); - reference_json["compliance"] = json_double_array({(double)i++, (double)i++, (double)i++}); - reference_json["infections"] = Json::Value(Json::arrayValue); - reference_json["last_transport_mode"] = Json::UInt(i++); - reference_json["location"] = Json::UInt(i++); - reference_json["location_type"] = Json::UInt(0); - reference_json["mask"]["mask_type"] = Json::UInt(0); + reference_json["age_group"] = Json::UInt(i++); + reference_json["assigned_locations"] = + json_uint_array_array({{i++, i++, i++, i++, i++, i++, i++, i++, i++, i++, i++}}); + reference_json["cells"] = json_uint_array({i++}); + reference_json["compliance"] = json_double_array({(double)i++, (double)i++, (double)i++}); + reference_json["infections"] = Json::Value(Json::arrayValue); + reference_json["last_transport_mode"] = Json::UInt(i++); + reference_json["location"] = Json::UInt(i++); + reference_json["location_type"] = Json::UInt(0); + reference_json["mask"]["mask_type"] = Json::UInt(0); reference_json["mask"]["time_first_used"]["seconds"] = Json::Int(i++); reference_json["home_isolation_start"]["seconds"] = Json::Int(i++); reference_json["rnd_go_to_school_hour"] = Json::Value((double)i++); diff --git a/cpp/tests/test_abm_testing_strategy.cpp b/cpp/tests/test_abm_testing_strategy.cpp index 5a850cef48..4e27d66cb3 100644 --- a/cpp/tests/test_abm_testing_strategy.cpp +++ b/cpp/tests/test_abm_testing_strategy.cpp @@ -103,8 +103,8 @@ TEST_F(TestTestingScheme, runScheme) mio::abm::Location loc_work(mio::abm::LocationType::Work, 0, num_age_groups); // Since tests are performed before start_date, the InfectionState of all the Person have to take into account the test's required_time auto person1 = - make_test_person(this->get_rng(), loc_home, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, - start_date - test_params_pcr.required_time); + make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, start_date - test_params_pcr.required_time); auto rng_person1 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person1); auto person2 = make_test_person(this->get_rng(), loc_home, mio::abm::ActivityType::Home, age_group_15_to_34, mio::abm::InfectionState::Recovered, start_date - test_params_pcr.required_time); @@ -152,8 +152,8 @@ TEST_F(TestTestingScheme, initAndRunTestingStrategy) mio::abm::Location loc_work(mio::abm::LocationType::Work, 0); // Since tests are performed before start_date, the InfectionState of all the Person have to take into account the test's required_time auto person1 = - make_test_person(this->get_rng(), loc_work, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms, - start_date - test_params_pcr.required_time); + make_test_person(this->get_rng(), loc_work, mio::abm::ActivityType::Work, age_group_15_to_34, + mio::abm::InfectionState::InfectedNoSymptoms, start_date - test_params_pcr.required_time); auto rng_person1 = mio::abm::PersonalRandomNumberGenerator(this->get_rng(), person1); auto person2 = make_test_person(this->get_rng(), loc_work, mio::abm::ActivityType::Work, age_group_15_to_34, mio::abm::InfectionState::Recovered, start_date - test_params_pcr.required_time); From 471618011d4a756da7cfbec8f9fa7b20b5b0d2c6 Mon Sep 17 00:00:00 2001 From: jubicker <113909589+jubicker@users.noreply.github.com> Date: Thu, 23 Apr 2026 11:21:43 +0200 Subject: [PATCH 3/5] fix tests --- cpp/models/abm/activity_type.h | 1 + cpp/models/abm/person.h | 1 + cpp/tests/test_abm_person.cpp | 31 ++++++++++++++++++++-------- cpp/tests/test_abm_serialization.cpp | 1 + cpp/tests/test_abm_simulation.cpp | 2 +- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/cpp/models/abm/activity_type.h b/cpp/models/abm/activity_type.h index 891e50e51c..ee6b174437 100644 --- a/cpp/models/abm/activity_type.h +++ b/cpp/models/abm/activity_type.h @@ -40,6 +40,7 @@ enum class ActivityType : std::uint32_t Hospital, ICU, Cemetery, // Location for all the dead persons. It is created once for the Model. + PublicTransport, Count, //last! Invalid diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index c799974528..e1a06b3ebe 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -419,6 +419,7 @@ class Person return Members("Person") .add("location", m_location) .add("location_type", m_location_type) + .add("activity_type", m_activity_type) .add("assigned_locations", m_assigned_locations) .add("vaccinations", m_vaccinations) .add("infections", m_infections) diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index 0c2aa65acb..a4b66a78c2 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -28,6 +28,7 @@ #include "abm_helpers.h" #include "random_number_test.h" +#include "gmock/gmock.h" #include using TestPerson = RandomNumberTest; @@ -100,6 +101,16 @@ TEST_F(TestPerson, change_location) */ TEST_F(TestPerson, setGetAssignedLocation) { + // Mock assigned location draws + ScopedMockDistribution>>> + mock_uniform_dist; + EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) + .Times(testing::Exactly(4)) // 1 draw per get_assigned_location_draw + .WillOnce(testing::Return(0)) // LocationId(2) + .WillOnce(testing::Return(1)) // LocationId(4) + .WillOnce(testing::Return(2)) // LocationId(0) + .WillOnce(testing::Return(3)); // LocationId(max) + mio::abm::Location location(mio::abm::LocationType::Work, 2, num_age_groups); auto person = mio::abm::Person(this->get_rng(), location.get_type(), mio::abm::ActivityType::Work, location.get_id(), location.get_model_id(), age_group_35_to_59); @@ -111,15 +122,6 @@ TEST_F(TestPerson, setGetAssignedLocation) person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(4), 0); EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, mio::abm::LocationId(4)); - // Fuzzing: assign random valid LocationId values and verify correctness. - for (int i = 0; i < 100; ++i) { - auto random_id = this->random_integer(0, std::numeric_limits::max()); - auto random_type = this->random_integer(0, (int)mio::abm::ActivityType::Count - 1); - person.set_assigned_location((mio::abm::ActivityType)random_type, mio::abm::LocationId(random_id), 0); - EXPECT_EQ(person.get_assigned_location((mio::abm::ActivityType)random_type, p_rng).first, - mio::abm::LocationId(random_id)); - } - // Boundary test cases: test with boundary LocationIds. person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(0), 0); EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, mio::abm::LocationId(0)); @@ -128,6 +130,17 @@ TEST_F(TestPerson, setGetAssignedLocation) 0); EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, mio::abm::LocationId(std::numeric_limits::max())); + + // Fuzzing: assign random valid LocationId values and verify correctness. + for (int i = 0; i < 100; ++i) { + + EXPECT_CALL(mock_uniform_dist.get_mock(), invoke).Times(testing::Exactly(1)).WillOnce(testing::Return(i + 4)); + + auto random_id = this->random_integer(0, std::numeric_limits::max()); + person.set_assigned_location(mio::abm::ActivityType::Work, mio::abm::LocationId(random_id), 0); + EXPECT_EQ(person.get_assigned_location(mio::abm::ActivityType::Work, p_rng).first, + mio::abm::LocationId(random_id)); + } } /** diff --git a/cpp/tests/test_abm_serialization.cpp b/cpp/tests/test_abm_serialization.cpp index dffa6e7495..41275577a7 100644 --- a/cpp/tests/test_abm_serialization.cpp +++ b/cpp/tests/test_abm_serialization.cpp @@ -208,6 +208,7 @@ TEST(TestAbmSerialization, Person) reference_json["last_transport_mode"] = Json::UInt(i++); reference_json["location"] = Json::UInt(i++); reference_json["location_type"] = Json::UInt(0); + reference_json["activity_type"] = Json::UInt(0); reference_json["mask"]["mask_type"] = Json::UInt(0); reference_json["mask"]["time_first_used"]["seconds"] = Json::Int(i++); reference_json["home_isolation_start"]["seconds"] = Json::Int(i++); diff --git a/cpp/tests/test_abm_simulation.cpp b/cpp/tests/test_abm_simulation.cpp index 5bef2c7072..58afd6dbfd 100644 --- a/cpp/tests/test_abm_simulation.cpp +++ b/cpp/tests/test_abm_simulation.cpp @@ -103,7 +103,7 @@ TEST(TestSimulation, advanceWithCommonHistory) model.assign_location(person1, basics_id, mio::abm::ActivityType::BasicsShop); model.assign_location(person2, basics_id, mio::abm::ActivityType::BasicsShop); model.assign_location(person3, basics_id, mio::abm::ActivityType::BasicsShop); - model.assign_location(person2, public_id, mio::abm::ActivityType::Invalid); + model.assign_location(person2, public_id, mio::abm::ActivityType::PublicTransport); mio::abm::TripList& trip_list = model.get_trip_list(); From 65e10d93278a25e78853b55015e5e9b32ecb91ce Mon Sep 17 00:00:00 2001 From: jubicker <113909589+jubicker@users.noreply.github.com> Date: Thu, 23 Apr 2026 11:24:46 +0200 Subject: [PATCH 4/5] Remove old ActivityType struct --- cpp/models/abm/mobility_data.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/cpp/models/abm/mobility_data.h b/cpp/models/abm/mobility_data.h index 0d19d46a52..2fafb67106 100644 --- a/cpp/models/abm/mobility_data.h +++ b/cpp/models/abm/mobility_data.h @@ -43,21 +43,6 @@ enum class TransportMode : uint32_t Count //last!! }; -// /** -// * @brief Type of the activity. -// */ -// enum class ActivityType : uint32_t -// { -// Workplace, -// Education, -// Shopping, -// Leisure, -// PrivateMatters, -// OtherActivity, -// Home, -// UnknownActivity -// }; - } // namespace abm } // namespace mio From f69ee3cfc16c1551f220e057e306f66392a74cc3 Mon Sep 17 00:00:00 2001 From: jubicker <113909589+jubicker@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:33:38 +0200 Subject: [PATCH 5/5] fix benchmark --- cpp/benchmarks/abm.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index 70e4f9e494..109806c08c 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -17,9 +17,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "abm/activity_type.h" #include "abm/simulation.h" #include "benchmark/benchmark.h" +#include mio::abm::Simulation<> make_simulation(size_t num_persons, std::initializer_list seeds) { @@ -44,25 +46,28 @@ mio::abm::Simulation<> make_simulation(size_t num_persons, std::initializer_list auto age = mio::AgeGroup(mio::UniformIntDistribution::get_instance()( model.get_rng(), size_t(0), model.parameters.get_num_groups() - 1)); - auto person = model.add_person(home, age); - model.assign_location(uint32_t(i), home); + auto person = model.add_person(home, age, mio::abm::ActivityType::Home); + model.assign_location(uint32_t(i), home, mio::abm::ActivityType::Home); home_size++; } //create other locations - for (auto loc_type : - {mio::abm::LocationType::School, mio::abm::LocationType::Work, mio::abm::LocationType::Recreation, - mio::abm::LocationType::BasicsShop, mio::abm::LocationType::Hospital, mio::abm::LocationType::ICU}) { + for (auto types : {std::make_pair(mio::abm::LocationType::School, mio::abm::ActivityType::School), + std::make_pair(mio::abm::LocationType::Work, mio::abm::ActivityType::Work), + std::make_pair(mio::abm::LocationType::Recreation, mio::abm::ActivityType::Recreation), + std::make_pair(mio::abm::LocationType::BasicsShop, mio::abm::ActivityType::BasicsShop), + std::make_pair(mio::abm::LocationType::Hospital, mio::abm::ActivityType::Hospital), + std::make_pair(mio::abm::LocationType::ICU, mio::abm::ActivityType::ICU)}) { const auto num_locs = std::max(size_t(1), num_persons / 2'000); std::vector locs(num_locs); std::generate(locs.begin(), locs.end(), [&] { - return model.add_location(loc_type); + return model.add_location(types.first); }); for (size_t p = 0; p < num_persons; ++p) { auto loc_idx = mio::UniformIntDistribution::get_instance()(model.get_rng(), size_t(0), num_locs - 1); - model.assign_location(uint32_t(p), locs[loc_idx]); + model.assign_location(uint32_t(p), locs[loc_idx], types.second); } }