Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

466 add delay in testing and planned migration #866

Merged
merged 50 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
b40aedc
Add struct for TestingResult in Person
khoanguyen-dev Nov 2, 2023
1df30bc
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Nov 10, 2023
20ddc7e
Add functions for TestResult in Person
khoanguyen-dev Nov 15, 2023
6513547
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Nov 27, 2023
2cf4afc
Add functions for checking a Person require a test in advance
khoanguyen-dev Nov 27, 2023
c83b092
Fix compilation errors
khoanguyen-dev Nov 28, 2023
fe2ce6e
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Nov 28, 2023
90530ce
Add structures for agents to look ahead for tests
khoanguyen-dev Dec 7, 2023
331848b
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Dec 7, 2023
2513d4e
Resolve compilation error
khoanguyen-dev Dec 11, 2023
0f55433
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Dec 11, 2023
0d387e5
Resolve compilation error
khoanguyen-dev Dec 11, 2023
39813d6
Simplify the testing in advance function
khoanguyen-dev Dec 11, 2023
0509292
Test for getting test result in Person
khoanguyen-dev Dec 14, 2023
6f4a8eb
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Dec 20, 2023
dfe6899
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Dec 20, 2023
0ecd87d
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Dec 27, 2023
562dca4
Add test to run TestStrategy for future Trips and Migration rules
khoanguyen-dev Jan 4, 2024
267767c
Remove unused variables in the tests running TestStrategy for future …
khoanguyen-dev Jan 4, 2024
609e4f9
Remove unused variables in the tests running TestStrategy for future …
khoanguyen-dev Jan 4, 2024
e266ad9
Add migration plan for Person class
khoanguyen-dev Jan 5, 2024
0d4d789
Add check to see if the Person plan ahead of time
khoanguyen-dev Jan 8, 2024
69419cf
Add check for parameter LookAheadTime
khoanguyen-dev Jan 8, 2024
4a29d4d
Change Person's m_test_results from vector to CustomIndexArray
khoanguyen-dev Jan 19, 2024
e75e79d
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Jan 19, 2024
7458989
Fix error in test abm migration and person
khoanguyen-dev Jan 19, 2024
09bbacf
Fix an error in run_strategy()
khoanguyen-dev Jan 22, 2024
941df85
Remove some debugging cout from run_strategy()
khoanguyen-dev Jan 22, 2024
b11679d
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Feb 11, 2024
44f9388
Add structure for Person to remember its lastest planning time
khoanguyen-dev Feb 11, 2024
eb53fde
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Jul 9, 2024
c523cfc
Remove tests for planning in World
khoanguyen-dev Jul 9, 2024
b82e845
Fix the error of PRAGMA_OMP(parallel for) in World::planning
khoanguyen-dev Jul 10, 2024
26d5a67
Attemp 2
khoanguyen-dev Jul 11, 2024
921c24e
Attemp 3
khoanguyen-dev Jul 11, 2024
dc375cf
Attemp 4 with pragma omp critical
khoanguyen-dev Jul 12, 2024
f7bc458
Add PRAGMA_OMP(critical) to World
khoanguyen-dev Jul 17, 2024
ec9c878
Fix error with PRAGMA_OMP(parallel for) to World
khoanguyen-dev Jul 17, 2024
59869d9
Merge branch 'main' into 466-add-delay-in-testing-and-planned-migration
khoanguyen-dev Jul 29, 2024
4e906af
Improve comments and adjust TestResult to have a variable named is_al…
khoanguyen-dev Jul 29, 2024
aa36dfd
Remove m_time_of_last_test for Person
khoanguyen-dev Jul 29, 2024
8eed843
Fix error in pycode abm.cpp
khoanguyen-dev Jul 29, 2024
7c03e5f
Fix error in pycode test_abm.py
khoanguyen-dev Jul 29, 2024
cc625cb
Move checking old test result to run_scheme()
khoanguyen-dev Jul 29, 2024
da9db33
= 0,
khoanguyen-dev Jul 31, 2024
b44be5b
Modifications according to David comments
khoanguyen-dev Aug 1, 2024
a37bab8
Small adjustments in comments
khoanguyen-dev Aug 1, 2024
80dc615
Move validity_period from TestParameter to TestingScheme
khoanguyen-dev Aug 2, 2024
4a29b0c
Fix pycode
khoanguyen-dev Aug 2, 2024
c0f443e
Small adjustments according to David's comments
khoanguyen-dev Aug 5, 2024
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
4 changes: 2 additions & 2 deletions cpp/examples/abm_history_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,14 @@ int main()
model.get_location(work).get_infection_parameters().set<mio::abm::MaximumContacts>(10);

// People can get tested at work (and do this with 0.5 probability) from time point 0 to day 30.
auto testing_min_time = mio::abm::days(1);
auto validity_period = mio::abm::days(1);
auto probability = 0.5;
auto start_date = mio::abm::TimePoint(0);
auto end_date = mio::abm::TimePoint(0) + mio::abm::days(30);
auto test_type = mio::abm::TestType::Antigen;
auto test_parameters = model.parameters.get<mio::abm::TestData>()[test_type];
auto testing_criteria_work = mio::abm::TestingCriteria();
auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date,
auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, validity_period, start_date, end_date,
test_parameters, probability);
model.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work);

Expand Down
4 changes: 2 additions & 2 deletions cpp/examples/abm_minimal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ int main()
.get<mio::abm::ContactRates>()[{age_group_15_to_34, age_group_15_to_34}] = 10.0;

// People can get tested at work (and do this with 0.5 probability) from time point 0 to day 10.
auto testing_min_time = mio::abm::days(1);
auto validity_period = mio::abm::days(1);
auto probability = 0.5;
auto start_date = mio::abm::TimePoint(0);
auto end_date = mio::abm::TimePoint(0) + mio::abm::days(10);
auto test_type = mio::abm::TestType::Antigen;
auto test_parameters = model.parameters.get<mio::abm::TestData>()[test_type];
auto testing_criteria_work = mio::abm::TestingCriteria();
auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date,
auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, validity_period, start_date, end_date,
test_parameters, probability);
model.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work);

Expand Down
3 changes: 1 addition & 2 deletions cpp/models/abm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ add_household_group_to_model(model, twoPersonHousehold_group);
During the simulation, people can get tested, and we have to specify the scheme for that:

```cpp
auto testing_min_time = mio::abm::days(1);
auto probability = 0.5;
auto start_date = mio::abm::TimePoint(0);
auto end_date = mio::abm::TimePoint(0) + mio::abm::days(30);
Expand All @@ -107,7 +106,7 @@ auto test_at_work = std::vector<mio::abm::LocationType>{mio::abm::LocationTy
auto testing_criteria_work =
std::vector<mio::abm::TestingCriteria>{mio::abm::TestingCriteria({}, test_at_work, {})};
auto testing_scheme_work =
mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, test_type, probability);
mio::abm::TestingScheme(testing_criteria_work, start_date, end_date, test_type, probability);
model.get_testing_strategy().add_testing_scheme(testing_scheme_work);
```

Expand Down
84 changes: 43 additions & 41 deletions cpp/models/abm/parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace abm
* @brief Time that a Person is infected but not yet infectious.
*/
struct IncubationPeriod {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -54,7 +54,7 @@ struct IncubationPeriod {
};

struct InfectedNoSymptomsToSymptoms {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -66,7 +66,7 @@ struct InfectedNoSymptomsToSymptoms {
};

struct InfectedNoSymptomsToRecovered {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -78,7 +78,7 @@ struct InfectedNoSymptomsToRecovered {
};

struct InfectedSymptomsToRecovered {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -90,7 +90,7 @@ struct InfectedSymptomsToRecovered {
};

struct InfectedSymptomsToSevere {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -102,7 +102,7 @@ struct InfectedSymptomsToSevere {
};

struct SevereToCritical {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -114,7 +114,7 @@ struct SevereToCritical {
};

struct SevereToRecovered {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -126,7 +126,7 @@ struct SevereToRecovered {
};

struct CriticalToRecovered {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -138,7 +138,7 @@ struct CriticalToRecovered {
};

struct CriticalToDead {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -150,7 +150,7 @@ struct CriticalToDead {
};

struct RecoveredToSusceptible {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand Down Expand Up @@ -211,7 +211,7 @@ struct InfectivityDistributions {
* @brief Probability that an Infection is detected.
*/
struct DetectInfection {
using Type = CustomIndexArray< UncertainValue<>, VirusVariant, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
static Type get_default(AgeGroup size)
{
return Type({VirusVariant::Count, size}, 1.);
Expand All @@ -226,7 +226,7 @@ struct DetectInfection {
* @brief Effectiveness of a Mask of a certain MaskType% against an Infection%.
*/
struct MaskProtection {
using Type = CustomIndexArray< UncertainValue<>, MaskType>;
using Type = CustomIndexArray<UncertainValue<>, MaskType>;
static Type get_default(AgeGroup /*size*/)
{
return Type({MaskType::Count}, 1.);
Expand Down Expand Up @@ -311,38 +311,40 @@ struct HighViralLoadProtectionFactor {
* @brief Parameters that describe the reliability of a test.
*/
struct TestParameters {
UncertainValue<> sensitivity;
UncertainValue<> specificity;
UncertainValue<> sensitivity;
UncertainValue<> specificity;
TimeSpan required_time;
TestType type;

/**
/**
* serialize this.
* @see mio::serialize
*/
template <class IOContext>
void serialize(IOContext& io) const
{
auto obj = io.create_object("TestParameters");
obj.add_element("Sensitivity", sensitivity);
obj.add_element("Specificity", specificity);
}

/**
template <class IOContext>
void serialize(IOContext& io) const
{
auto obj = io.create_object("TestParameters");
obj.add_element("Sensitivity", sensitivity);
obj.add_element("Specificity", specificity);
}

/**
* deserialize an object of this class.
* @see mio::deserialize
*/
template <class IOContext>
static IOResult<TestParameters> deserialize(IOContext& io)
{
auto obj = io.expect_object("TestParameters");
auto sens = obj.expect_element("Sensitivity", mio::Tag<UncertainValue<>>{});
auto spec = obj.expect_element("Specificity", mio::Tag<UncertainValue<>>{});
return apply(
io,
[](auto&& sens_, auto&& spec_) {
return TestParameters{sens_, spec_};
},
sens, spec);
}
template <class IOContext>
static IOResult<TestParameters> deserialize(IOContext& io)
{
auto obj = io.expect_object("TestParameters");
auto sens = obj.expect_element("Sensitivity", mio::Tag<UncertainValue<>>{});
auto spec = obj.expect_element("Specificity", mio::Tag<UncertainValue<>>{});
return apply(
io,
[](auto&& sens_, auto&& spec_) {
return TestParameters{sens_, spec_};
},
sens, spec);
}
};

/**
Expand All @@ -353,9 +355,9 @@ struct TestData {
static auto get_default(AgeGroup /*size*/)
{
Type default_val = Type({TestType::Count});
default_val[{TestType::Generic}] = TestParameters{0.9, 0.99};
default_val[{TestType::Antigen}] = TestParameters{0.8, 0.88};
default_val[{TestType::PCR}] = TestParameters{0.9, 0.99};
default_val[{TestType::Generic}] = TestParameters{0.9, 0.99, hours(48), TestType::Generic};
default_val[{TestType::Antigen}] = TestParameters{0.8, 0.88, minutes(30), TestType::Antigen};
default_val[{TestType::PCR}] = TestParameters{0.9, 0.99, hours(48), TestType::PCR};
return default_val;
}
static std::string name()
Expand Down Expand Up @@ -398,7 +400,7 @@ struct QuarantineDuration {
* @brief Parameter for the exponential distribution to decide if a Person goes shopping.
*/
struct BasicShoppingRate {
using Type = CustomIndexArray< UncertainValue<>, AgeGroup>;
using Type = CustomIndexArray<UncertainValue<>, AgeGroup>;
static auto get_default(AgeGroup size)
{
return Type({size}, 1.0);
Expand Down
16 changes: 13 additions & 3 deletions cpp/models/abm/person.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ Person::Person(mio::RandomNumberGenerator& rng, LocationType location_type, Loca
, m_quarantine_start(TimePoint(-(std::numeric_limits<int>::max() / 2)))
, m_age(age)
, m_time_at_location(0)
, m_time_of_last_test(TimePoint(-(std::numeric_limits<int>::max() / 2)))
, m_mask(Mask(MaskType::Community))
, m_wears_mask(false)
, m_mask_compliance((uint32_t)LocationType::Count, 0.)
, m_person_id(person_id)
, m_cells{0}
, m_last_transport_mode(TransportMode::Unknown)
, m_test_results({TestType::Count}, TestResult())
DavidKerkmann marked this conversation as resolved.
Show resolved Hide resolved
{
m_random_workgroup = UniformDistribution<double>::get_instance()(rng);
m_random_schoolgroup = UniformDistribution<double>::get_instance()(rng);
Expand Down Expand Up @@ -154,8 +154,7 @@ void Person::remove_quarantine()

bool Person::get_tested(PersonalRandomNumberGenerator& rng, TimePoint t, const TestParameters& params)
{
ScalarType random = UniformDistribution<double>::get_instance()(rng);
m_time_of_last_test = t;
ScalarType random = UniformDistribution<double>::get_instance()(rng);
if (is_infected(t)) {
// true positive
if (random < params.sensitivity) {
Expand Down Expand Up @@ -264,5 +263,16 @@ ScalarType Person::get_protection_factor(TimePoint t, VirusVariant virus, const
t.days() - latest_protection.second.days());
}

void Person::add_test_result(TimePoint t, TestType type, bool result)
{
// Remove outdated test results or replace the old result of the same type
m_test_results[{type}] = {t, result};
}

TestResult Person::get_test_result(TestType type) const
{
return m_test_results[{type}];
}

} // namespace abm
} // namespace mio
32 changes: 20 additions & 12 deletions cpp/models/abm/person.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "abm/person_id.h"
#include "abm/personal_rng.h"
#include "abm/time.h"
#include "abm/test_type.h"
#include "abm/vaccine.h"
#include "abm/mask.h"
#include "abm/mobility_data.h"
Expand Down Expand Up @@ -155,15 +156,6 @@ class Person
m_time_at_location += dt;
}

/**
* @brief Get the TimePoint of the last negative test.
* @return TimePoint since the last test.
*/
TimePoint get_time_of_last_test() const
{
return m_time_of_last_test;
}

/**
* @brief Set an assigned Location of the Person.
*
Expand Down Expand Up @@ -391,7 +383,7 @@ class Person
}

/**
* @brief Get the latest #Infection or #Vaccination and its initial TimePoint of the Person.
* @brief Get the latest #ExposureType and its initial TimePoint of the Person.
*/
std::pair<ExposureType, TimePoint> get_latest_protection() const;

Expand Down Expand Up @@ -427,6 +419,22 @@ class Person
loc, age, id);
}

/**
* @brief Add TestResult to the Person
* @param[in] t The TimePoint of the test.
* @param[in] type The TestType of the test.
* @param[in] result The result of the test.
*/
void add_test_result(TimePoint t, TestType type, bool result);

/**
* @brief Get the most recent TestResult performed from the Person based on the TestType.
* If time_of_testing == TimePoint(std::numeric_limits<int>::min()), there is no previous TestResult.
* @param[in] type The TestType of the test.
DavidKerkmann marked this conversation as resolved.
Show resolved Hide resolved
* @return The latest TestResult of the given Type.
*/
TestResult get_test_result(TestType type) const;

private:
LocationId m_location; ///< Current Location of the Person.
LocationType m_location_type; ///< Type of the current Location.
Expand All @@ -441,14 +449,14 @@ class Person
double m_random_schoolgroup; ///< Value to determine if the Person goes to school or stays at home during lockdown.
double m_random_goto_work_hour; ///< Value to determine at what time the Person goes to work.
double m_random_goto_school_hour; ///< Value to determine at what time the Person goes to school.
TimePoint m_time_of_last_test; ///< TimePoint of the last negative test.
Mask m_mask; ///< The Mask of the Person.
bool m_wears_mask = false; ///< Whether the Person currently wears a Mask.
std::vector<ScalarType> m_mask_compliance; ///< Vector of Mask compliance values for all #LocationType%s.
PersonId m_person_id; ///< Id of the Person.
std::vector<uint32_t> 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.
Counter<uint32_t> m_rng_counter{0}; ///< counter for RandomNumberGenerator
Counter<uint32_t> m_rng_counter{0}; ///< counter for RandomNumberGenerator.
CustomIndexArray<TestResult, TestType> m_test_results; ///< CustomIndexArray for TestResults.
DavidKerkmann marked this conversation as resolved.
Show resolved Hide resolved
};

} // namespace abm
Expand Down
10 changes: 9 additions & 1 deletion cpp/models/abm/test_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#define MIO_ABM_TEST_TYPE_H

#include <cstdint>

#include <limits>
namespace mio
{
namespace abm
Expand All @@ -40,6 +40,14 @@ enum class TestType : std::uint32_t
Count
};

/**
* @brief The TestResult of a Person.
*/
struct TestResult {
TimePoint time_of_testing{std::numeric_limits<int>::min()}; ///< The TimePoint when the Person performs the test.
bool result{false}; ///< The test result.
};

} // namespace abm
} // namespace mio

Expand Down
Loading
Loading