Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d132c18
first draft
xsaschako Jul 30, 2022
0852b20
enhance world by testing scheme
Jul 30, 2022
a4b6703
First draft
DavidKerkmann Aug 1, 2022
1579c70
resolved merge conflict
DavidKerkmann Aug 1, 2022
e45edad
enhance testing_scheme
xsaschako Aug 2, 2022
21f8b0f
fixed old testing_scheme implementation
xsaschako Aug 2, 2022
8577add
change cstors and update_testing_schems
xsaschako Aug 2, 2022
00a8e8b
further enhancements
Aug 4, 2022
e4bbe24
Added comments
DavidKerkmann Aug 5, 2022
e1af4ab
add unit tests, formatting and some fixes
Aug 9, 2022
5d3a5a4
update abm example
Aug 9, 2022
322a375
Fix abm example and tests
xsaschako Aug 10, 2022
4dea8ee
Merge rule and scheme
DavidKerkmann Aug 10, 2022
09c452a
Merge branch '326-add-extensive-testing-scheme-to-abm-modell' of http…
DavidKerkmann Aug 10, 2022
5fc2df0
change CMake
DavidKerkmann Aug 10, 2022
693a6de
add some more improvments to == and adder
Aug 10, 2022
5341e1b
Added Authors
Aug 11, 2022
f36e2c9
Unittest skip for CI
Aug 15, 2022
085941c
changed testing_scheme to testing strategy, added some tests
Aug 20, 2022
c1668b2
some minor fixes
Sep 1, 2022
38d05e7
ctor fix
Sep 1, 2022
bd17cf1
fix further things from the code review
Sep 1, 2022
453ceac
add final remarks of code review
Sep 2, 2022
dd8e25c
Merge remote-tracking branch 'origin/main' into 326-add-extensive-tes…
Sep 2, 2022
dca3c26
Implement review requests
DavidKerkmann Sep 9, 2022
a7e435a
add logic of perosn who tests pos but is not home
Sep 19, 2022
cc03f11
update test
Sep 19, 2022
d8a9fdc
Started with python bindings
DavidKerkmann Sep 21, 2022
beb9528
Merge branch '326-add-extensive-testing-scheme-to-abm-modell' of http…
DavidKerkmann Sep 21, 2022
ea1be12
Update pybindings
DavidKerkmann Sep 21, 2022
c01abc0
Fixes const& in pybind
DavidKerkmann Sep 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 67 additions & 33 deletions cpp/examples/abm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ std::vector<int> last_household_gets_the_rest(int number_of_people, int number_o
* @param number_of_hh The number of households in this household group.
* @return householdGroup A Class Household Group.
*/
mio::abm::HouseholdGroup make_uniform_households(const mio::abm::HouseholdMember& member, int number_of_people, int number_of_hh)
mio::abm::HouseholdGroup make_uniform_households(const mio::abm::HouseholdMember& member, int number_of_people,
int number_of_hh)
{

// The size of each household is calculated in a vector household_size_list.
Expand All @@ -89,10 +90,11 @@ mio::abm::HouseholdGroup make_uniform_households(const mio::abm::HouseholdMember
* @param number_of_other_familes number_of_persons_in_household random persons.
* @return A Household group.
*/
mio::abm::HouseholdGroup make_homes_with_families(const mio::abm::HouseholdMember& child, const mio::abm::HouseholdMember& parent,
const mio::abm::HouseholdMember& random, int number_of_persons_in_household,
int number_of_full_familes, int number_of_half_familes,
int number_of_other_familes)
mio::abm::HouseholdGroup make_homes_with_families(const mio::abm::HouseholdMember& child,
const mio::abm::HouseholdMember& parent,
const mio::abm::HouseholdMember& random,
int number_of_persons_in_household, int number_of_full_familes,
int number_of_half_familes, int number_of_other_familes)
{

auto private_household_group = mio::abm::HouseholdGroup();
Expand Down Expand Up @@ -237,23 +239,23 @@ void create_world_from_statistical_data(mio::abm::World& world)
int two_person_half_families = 1765;
int two_person_other_families = 166;
auto twoPersonHouseholds = make_homes_with_families(child, parent, random, 2, two_person_full_families,
two_person_half_families, two_person_other_families);
two_person_half_families, two_person_other_families);
add_household_group_to_world(world, twoPersonHouseholds);

// Three person households
int three_person_full_families = 4155;
int three_person_half_families = 662;
int three_person_other_families = 175;
auto threePersonHouseholds = make_homes_with_families(child, parent, random, 3, three_person_full_families,
three_person_half_families, three_person_other_families);
three_person_half_families, three_person_other_families);
add_household_group_to_world(world, threePersonHouseholds);

// Four person households
int four_person_full_families = 3551;
int four_person_half_families = 110;
int four_person_other_families = 122;
auto fourPersonHouseholds = make_homes_with_families(child, parent, random, 4, four_person_full_families,
four_person_half_families, four_person_other_families);
four_person_half_families, four_person_other_families);
add_household_group_to_world(world, fourPersonHouseholds);

// Five plus person households
Expand All @@ -276,8 +278,20 @@ void create_assign_locations(mio::abm::World& world)
// People have to get tested in the 2 days before the event
auto event = world.add_location(mio::abm::LocationType::SocialEvent);
world.get_individualized_location(event).get_infection_parameters().set<mio::abm::MaximumContacts>(100);
world.get_individualized_location(event).set_testing_scheme(mio::abm::days(2), 1);

std::vector<mio::abm::LocationType> test_at_social_event = {mio::abm::LocationType::SocialEvent};
auto testing_criteria = std::vector<mio::abm::TestingCriteria> {mio::abm::TestingCriteria({}, test_at_social_event, {})};
auto testing_min_time = mio::abm::days(2);
auto start_date = mio::abm::TimePoint(0);
auto end_date = mio::abm::TimePoint(0) + mio::abm::days(60);
auto probability = 1;
auto test_type = mio::abm::AntigenTest();

auto testing_scheme =
mio::abm::TestingScheme(testing_criteria, testing_min_time, start_date, end_date, test_type, probability);

world.get_testing_strategy().add_testing_scheme(testing_scheme);

// Add hospital and ICU with 5 maximum contacs.
auto hospital = world.add_location(mio::abm::LocationType::Hospital);
world.get_individualized_location(hospital).get_infection_parameters().set<mio::abm::MaximumContacts>(5);
Expand All @@ -295,11 +309,10 @@ void create_assign_locations(mio::abm::World& world)

auto school = world.add_location(mio::abm::LocationType::School);
world.get_individualized_location(school).get_infection_parameters().set<mio::abm::MaximumContacts>(40);
world.get_individualized_location(school).set_testing_scheme(mio::abm::days(7), 1);

auto work = world.add_location(mio::abm::LocationType::Work);
world.get_individualized_location(work).get_infection_parameters().set<mio::abm::MaximumContacts>(40);
world.get_individualized_location(work).set_testing_scheme(mio::abm::days(7), 0.5);

int counter_school = 0;
int counter_work = 0;
int counter_shop = 0;
Expand Down Expand Up @@ -339,6 +352,25 @@ void create_assign_locations(mio::abm::World& world)
world.get_individualized_location(shop).get_infection_parameters().set<mio::abm::MaximumContacts>(20);
}
}

// add the testing schemes for school and work
auto test_at_school = std::vector<mio::abm::LocationType> {mio::abm::LocationType::School};
auto testing_criteria_school = std::vector<mio::abm::TestingCriteria> {mio::abm::TestingCriteria({}, test_at_school, {})};

testing_min_time = mio::abm::days(7);
probability = 1;
auto testing_scheme_school =
mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date, end_date, test_type, probability);
world.get_testing_strategy().add_testing_scheme(testing_scheme_school);

auto test_at_work = std::vector<mio::abm::LocationType> {mio::abm::LocationType::Work};
auto testing_criteria_work = std::vector<mio::abm::TestingCriteria> {mio::abm::TestingCriteria({}, test_at_work, {})};

testing_min_time = mio::abm::days(1);
probability = 0.5;
auto testing_scheme_work =
mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, test_type, probability);
world.get_testing_strategy().add_testing_scheme(testing_scheme_work);
}

/**
Expand Down Expand Up @@ -376,31 +408,33 @@ int main()
mio::abm::GlobalInfectionParameters infection_params;

// Set same parameter for all age groups
infection_params.get<mio::abm::IncubationPeriod>() = 4.;
infection_params.get<mio::abm::SusceptibleToExposedByCarrier>() = 0.02;
infection_params.get<mio::abm::IncubationPeriod>() = 4.;
infection_params.get<mio::abm::SusceptibleToExposedByCarrier>() = 0.02;
infection_params.get<mio::abm::SusceptibleToExposedByInfected>() = 0.02;
infection_params.get<mio::abm::CarrierToInfected>() = 0.15;
infection_params.get<mio::abm::CarrierToRecovered>() = 0.15;
infection_params.get<mio::abm::InfectedToRecovered>() = 0.2;
infection_params.get<mio::abm::InfectedToSevere>() = 0.03;
infection_params.get<mio::abm::SevereToRecovered>() = 0.1;
infection_params.get<mio::abm::SevereToCritical>() = 0.1;
infection_params.get<mio::abm::CriticalToRecovered>() = 0.02;
infection_params.get<mio::abm::CriticalToDead>() = 0.06;
infection_params.get<mio::abm::RecoveredToSusceptible>() = 0.1;
infection_params.get<mio::abm::CarrierToInfected>() = 0.15;
infection_params.get<mio::abm::CarrierToRecovered>() = 0.15;
infection_params.get<mio::abm::InfectedToRecovered>() = 0.2;
infection_params.get<mio::abm::InfectedToSevere>() = 0.03;
infection_params.get<mio::abm::SevereToRecovered>() = 0.1;
infection_params.get<mio::abm::SevereToCritical>() = 0.1;
infection_params.get<mio::abm::CriticalToRecovered>() = 0.02;
infection_params.get<mio::abm::CriticalToDead>() = 0.06;
infection_params.get<mio::abm::RecoveredToSusceptible>() = 0.1;

// Set parameters for vaccinated people of all age groups
infection_params.get<mio::abm::IncubationPeriod>().slice(mio::abm::VaccinationState::Vaccinated) = 4.;
infection_params.get<mio::abm::SusceptibleToExposedByCarrier>().slice(mio::abm::VaccinationState::Vaccinated) = 0.02;
infection_params.get<mio::abm::SusceptibleToExposedByInfected>().slice(mio::abm::VaccinationState::Vaccinated) = 0.02;
infection_params.get<mio::abm::CarrierToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.15;
infection_params.get<mio::abm::InfectedToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.15;
infection_params.get<mio::abm::InfectedToSevere>().slice(mio::abm::VaccinationState::Vaccinated) = 0.05;
infection_params.get<mio::abm::SevereToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.05;
infection_params.get<mio::abm::SevereToCritical>().slice(mio::abm::VaccinationState::Vaccinated) = 0.005;
infection_params.get<mio::abm::CriticalToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.5;
infection_params.get<mio::abm::CriticalToDead>().slice(mio::abm::VaccinationState::Vaccinated) = 0.005;
infection_params.get<mio::abm::RecoveredToSusceptible>().slice(mio::abm::VaccinationState::Vaccinated) = 0.05;
infection_params.get<mio::abm::IncubationPeriod>().slice(mio::abm::VaccinationState::Vaccinated) = 4.;
infection_params.get<mio::abm::SusceptibleToExposedByCarrier>().slice(mio::abm::VaccinationState::Vaccinated) =
0.02;
infection_params.get<mio::abm::SusceptibleToExposedByInfected>().slice(mio::abm::VaccinationState::Vaccinated) =
0.02;
infection_params.get<mio::abm::CarrierToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.15;
infection_params.get<mio::abm::InfectedToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.15;
infection_params.get<mio::abm::InfectedToSevere>().slice(mio::abm::VaccinationState::Vaccinated) = 0.05;
infection_params.get<mio::abm::SevereToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.05;
infection_params.get<mio::abm::SevereToCritical>().slice(mio::abm::VaccinationState::Vaccinated) = 0.005;
infection_params.get<mio::abm::CriticalToRecovered>().slice(mio::abm::VaccinationState::Vaccinated) = 0.5;
infection_params.get<mio::abm::CriticalToDead>().slice(mio::abm::VaccinationState::Vaccinated) = 0.005;
infection_params.get<mio::abm::RecoveredToSusceptible>().slice(mio::abm::VaccinationState::Vaccinated) = 0.05;

auto world = mio::abm::World(infection_params);

Expand Down
4 changes: 2 additions & 2 deletions cpp/models/abm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ add_library(abm
simulation.h
person.cpp
person.h
testing_strategy.cpp
testing_strategy.h
world.cpp
world.h
state.h
Expand All @@ -19,8 +21,6 @@ add_library(abm
trip_list.h
lockdown_rules.cpp
lockdown_rules.h
testing_scheme.cpp
testing_scheme.h
)
target_link_libraries(abm PUBLIC memilio)
target_include_directories(abm PUBLIC
Expand Down
2 changes: 1 addition & 1 deletion cpp/models/abm/abm.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
#include "abm/location_type.h"
#include "memilio/utils/random_number_generator.h"
#include "abm/migration_rules.h"
#include "abm/testing_scheme.h"
#include "abm/testing_strategy.h"

#endif
1 change: 0 additions & 1 deletion cpp/models/abm/location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ Location::Location(LocationType type, uint32_t index, uint32_t num_cells)
, m_index(index)
, m_subpopulations{}
, m_cached_exposure_rate({AgeGroup::Count, VaccinationState::Count})
, m_testing_scheme()
, m_cells(std::vector<Cell>(num_cells))
{
}
Expand Down
12 changes: 0 additions & 12 deletions cpp/models/abm/location.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#define EPI_ABM_LOCATION_H

#include "abm/parameters.h"
#include "abm/testing_scheme.h"
#include "abm/state.h"
#include "abm/location_type.h"

Expand Down Expand Up @@ -174,16 +173,6 @@ class Location
return m_parameters;
}

void set_testing_scheme(TimeSpan interval, double probability)
{
m_testing_scheme = TestingScheme(interval, probability);
}

const TestingScheme& get_testing_scheme() const
{
return m_testing_scheme;
}

const std::vector<Cell>& get_cells() const
{
return m_cells;
Expand All @@ -199,7 +188,6 @@ class Location
std::array<int, size_t(InfectionState::Count)> m_subpopulations;
LocalInfectionParameters m_parameters;
CustomIndexArray<double, AgeGroup, VaccinationState> m_cached_exposure_rate;
TestingScheme m_testing_scheme;
std::vector<Cell> m_cells;
};

Expand Down
43 changes: 25 additions & 18 deletions cpp/models/abm/parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,25 +191,13 @@ struct DetectInfection {
}
};

struct TestWhileInfected {
using Type = CustomIndexArray<double, AgeGroup>;
static Type get_default()
{
return Type({AgeGroup::Count}, 0.005);
}
static std::string name()
{
return "TestWhileInfected";
}
};

/**
* parameters of the infection that are the same everywhere within the world.
*/
using GlobalInfectionParameters =
ParameterSet<IncubationPeriod, SusceptibleToExposedByCarrier, SusceptibleToExposedByInfected, CarrierToInfected,
CarrierToRecovered, InfectedToRecovered, InfectedToSevere, SevereToCritical, SevereToRecovered,
CriticalToDead, CriticalToRecovered, RecoveredToSusceptible, DetectInfection, TestWhileInfected>;
CriticalToDead, CriticalToRecovered, RecoveredToSusceptible, DetectInfection>;

struct MaximumContacts {
using Type = double;
Expand All @@ -233,22 +221,41 @@ struct TestParameters {
double specificity;
};

struct AntigenTest {
struct GenericTest {
using Type = TestParameters;
static constexpr Type get_default()
{
return Type{0.9, 0.99};
}
static std::string name()
{
return "GenericTest";
}
};

struct AntigenTest : public GenericTest {
using Type = TestParameters;
static constexpr Type get_default()
{
return Type{0.8, 0.88};
}
static std::string name()
{
return "AntigenTest";
}
};

/**
* parameters of the testing that are the same everywhere in the world.
*/
using GlobalTestingParameters = ParameterSet<AntigenTest>;
struct PCRTest : public GenericTest {
using Type = TestParameters;
static constexpr Type get_default()
{
return Type{0.9, 0.99};
}
static std::string name()
{
return "PCRTest";
}
};

/**
* parameters that govern the migration between locations.
Expand Down
14 changes: 6 additions & 8 deletions cpp/models/abm/person.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ Person::Person(Location& location, InfectionProperties infection_properties, Age
{
}

void Person::interact(TimeSpan dt, const GlobalInfectionParameters& global_infection_params, Location& loc,
const GlobalTestingParameters& global_testing_params)
void Person::interact(TimeSpan dt, const GlobalInfectionParameters& global_infection_params, Location& loc)
{
auto infection_state = m_infection_state;
auto new_infection_state = infection_state;
Expand All @@ -85,12 +84,6 @@ void Person::interact(TimeSpan dt, const GlobalInfectionParameters& global_infec
new_infection_state == InfectionState::Infected_Critical) {
m_quarantine = true;
}
else if (new_infection_state == InfectionState::Infected) {
double rand = UniformDistribution<double>::get_instance()();
if (rand < global_infection_params.get<TestWhileInfected>()[this->m_age] * dt.days()) {
this->get_tested(global_testing_params.get<AntigenTest>());
}
}
else {
m_quarantine = false;
}
Expand Down Expand Up @@ -168,23 +161,28 @@ bool Person::get_tested(const TestParameters& params)
if (m_infection_state == InfectionState::Carrier || m_infection_state == InfectionState::Infected ||
m_infection_state == InfectionState::Infected_Severe ||
m_infection_state == InfectionState::Infected_Critical) {
// true positive
if (random < params.sensitivity) {
m_quarantine = true;
return true;
}
// false negative
else {
m_quarantine = false;
m_time_since_negative_test = days(0);
return false;
}
}
else {
// true negative
if (random < params.specificity) {
m_quarantine = false;
m_time_since_negative_test = days(0);
return false;
}
// false positive
else {
m_quarantine = true;
return true;
}
}
Expand Down
6 changes: 2 additions & 4 deletions cpp/models/abm/person.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
#include "abm/age.h"
#include "abm/time.h"
#include "abm/parameters.h"
#include "abm/world.h"
#include "abm/time.h"
#include "abm/location.h"

#include <functional>

Expand Down Expand Up @@ -97,8 +96,7 @@ class Person
* @param dt length of the current simulation time step
* @param global_infection_parameters infection parameters that are the same in all locations
*/
void interact(TimeSpan dt, const GlobalInfectionParameters& global_infection_parameters, Location& loc,
const GlobalTestingParameters& global_testing_params);
void interact(TimeSpan dt, const GlobalInfectionParameters& global_infection_parameters, Location& loc);

/**
* migrate to a different location.
Expand Down
Loading