Skip to content
21 changes: 13 additions & 8 deletions cpp/benchmarks/abm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <utility>

mio::abm::Simulation<> make_simulation(size_t num_persons, std::initializer_list<uint32_t> seeds)
{
Expand All @@ -44,25 +46,28 @@ mio::abm::Simulation<> make_simulation(size_t num_persons, std::initializer_list

auto age = mio::AgeGroup(mio::UniformIntDistribution<size_t>::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::SocialEvent,
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<mio::abm::LocationId> 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<size_t>::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);
}
}

Expand Down Expand Up @@ -112,7 +117,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));
Expand Down
14 changes: 7 additions & 7 deletions cpp/examples/abm_history_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,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<mio::abm::MaximumContacts>(5);
// Add hospital and ICU with 5 maximum contacs.
auto hospital = model.add_location(mio::abm::LocationType::Hospital);
Expand Down Expand Up @@ -158,17 +158,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);
}
}

Expand Down
33 changes: 26 additions & 7 deletions cpp/examples/abm_minimal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "abm/common_abm_loggers.h"
#include "memilio/io/directories.h"

#include <cstddef>
#include <fstream>

int main()
Expand Down Expand Up @@ -80,7 +81,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<mio::abm::MaximumContacts>(5);
// Add hospital and ICU with 5 maximum contacs.
auto hospital = model.add_location(mio::abm::LocationType::Hospital);
Expand Down Expand Up @@ -128,21 +129,39 @@ int main()
}
}

size_t num_teachers = 0;
size_t num_hosp_doctors = 0;
size_t num_icu_doctors = 0;

// Assign locations to the people
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);
if (num_teachers < 3) {
model.assign_location(id, school, mio::abm::ActivityType::Work);
num_teachers++;
}
else if (num_hosp_doctors < 1) {
model.assign_location(id, hospital, mio::abm::ActivityType::Work);
num_hosp_doctors++;
}
else if (num_icu_doctors < 1) {
model.assign_location(id, icu, mio::abm::ActivityType::Work);
num_icu_doctors++;
}
else {
model.assign_location(id, work, mio::abm::ActivityType::Work);
}
}
}

Expand Down
15 changes: 8 additions & 7 deletions cpp/examples/abm_parameter_study.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -91,7 +92,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<mio::abm::MaximumContacts>(5);
// Add hospital and ICU with 5 maximum contacs.
auto hospital = model.add_location(mio::abm::LocationType::Hospital);
Expand Down Expand Up @@ -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);
}
}

Expand Down
33 changes: 17 additions & 16 deletions cpp/examples/graph_abm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<mio::abm::MaximumContacts>(10);
auto hospital_m1 = model1.add_location(mio::abm::LocationType::Hospital);
model1.get_location(hospital_m1).get_infection_parameters().set<mio::abm::MaximumContacts>(10);
Expand All @@ -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<mio::abm::MaximumContacts>(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<mio::abm::MaximumContacts>(10);
auto hospital_m2 = model2.add_location(mio::abm::LocationType::Hospital);
model2.get_location(hospital_m2).get_infection_parameters().set<mio::abm::MaximumContacts>(10);
Expand All @@ -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<size_t>::get_instance()(mio::thread_local_rng(),
std::vector<double>{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());
}
}
}
Expand All @@ -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<size_t>::get_instance()(mio::thread_local_rng(),
std::vector<double>{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());
}
}
}
Expand Down
1 change: 1 addition & 0 deletions cpp/models/abm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_library(abm
model.cpp
model.h
location_type.h
activity_type.h
parameters.h
parameters.cpp
mobility_rules.cpp
Expand Down
52 changes: 52 additions & 0 deletions cpp/models/abm/activity_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2020-2026 MEmilio
*
* Authors: Julia Bicker
*
* Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
*
* 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 <cstdint>

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.
PublicTransport,

Count, //last!
Invalid
};

} // namespace abm
} // namespace mio

#endif
20 changes: 10 additions & 10 deletions cpp/models/abm/common_abm_loggers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions cpp/models/abm/household.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
Loading