From 3fcb8773843cefd976624e52be3a0e461e873375 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 31 Jul 2023 17:30:37 +0200 Subject: [PATCH 01/16] firstcommit --- cpp/models/abm/infection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 504724a0eb..62fe109c75 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -130,6 +130,7 @@ void Infection::draw_infection_course_forward(AgeGroup age, const GlobalInfectio v = uniform_dist(); if (v < 0.5) { // TODO: subject to change time_period = days(params.get()[{ + //Todo:e.g. is this timelength m_virus_variant, age, VaccinationState::Unvaccinated}]); // TODO: subject to change next_state = InfectionState::InfectedSymptoms; } From 3113609dfd1de34080635910473ec6a622bc32d1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:23:55 +0200 Subject: [PATCH 02/16] add first draft for tree --- cpp/models/abm/test_tree.cpp | 10 +++++ cpp/models/abm/weighted_decision_tree.h | 54 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 cpp/models/abm/test_tree.cpp create mode 100644 cpp/models/abm/weighted_decision_tree.h diff --git a/cpp/models/abm/test_tree.cpp b/cpp/models/abm/test_tree.cpp new file mode 100644 index 0000000000..9a7b64e6b5 --- /dev/null +++ b/cpp/models/abm/test_tree.cpp @@ -0,0 +1,10 @@ +#include "weighted_decision_tree.h" +#include + +int main(int argc, char const* argv[]) +{ + auto nodes = std::vector({1, 4, 10}); + auto edges = std::vector>({{1, 4, 0.5}, {4, 10, 0.5}}); + auto decision_tree = weighted_decision_tree(nodes, edges); + return 0; +} diff --git a/cpp/models/abm/weighted_decision_tree.h b/cpp/models/abm/weighted_decision_tree.h new file mode 100644 index 0000000000..20047d5d98 --- /dev/null +++ b/cpp/models/abm/weighted_decision_tree.h @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2020-2021 German Aerospace Center (DLR-SC) +* +* Authors: Sascha Korf +* +* 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. +*/ + +#include +#include +#include +#include +#include + +struct TreeNode { + int value; +}; + +struct TreeEdge { + double time_length; +}; + +class weighted_decision_tree +{ +public: + weighted_decision_tree(std::vector nodes, std::vector> edges) + { + for (auto edge : edges) { + auto parent_node = std::find(nodes.begin(), nodes.end(), std::get<0>(edge)); + auto child_node = std::find(nodes.begin(), nodes.end(), std::get<1>(edge)); + build_tree(TreeNode{*parent_node}, TreeEdge{std::get<2>(edge)}, TreeNode{*child_node}); + } + } + +private: + void build_tree(TreeNode node, TreeEdge edge, TreeNode child) + { + m_tree.insert({node, std::make_pair(edge, child)}); + } + + std::map> m_tree; +}; From 25e790541dd6e0a3424f4c79ffe28c91a5ef6a86 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:14:04 +0100 Subject: [PATCH 03/16] Update parameters --- cpp/models/abm/parameters.h | 126 +++++++++++++++------------ cpp/models/ode_secirvvs/parameters.h | 2 +- 2 files changed, 73 insertions(+), 55 deletions(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index ad1d37b49a..0031e50070 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -39,14 +39,17 @@ namespace mio namespace abm { +// Distribution that can be used for the time spend in InfectionStates +using InfectionStateTimesDistributionsParameters = UniformDistribution::ParamType; + /** - * @brief Time that a Person is infected but not yet infectious. + * @brief Time that a Person is infected but not yet infectious in day unit */ struct IncubationPeriod { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { @@ -54,113 +57,127 @@ struct IncubationPeriod { } }; -struct InfectedNoSymptomsToSymptoms { - using Type = CustomIndexArray; +/** +* @brief Time that a Person is infected but nonsymptomatic in day unit +*/ +struct TimeInfectedNoSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedNoSymptomsToSymptoms"; + return "TimeInfectedNoSymptoms"; } }; -struct InfectedNoSymptomsToRecovered { - using Type = CustomIndexArray; +/** +* @brief Time that a Person is infected and symptomatic but +* who do not need to be hospitalized (yet) in day unit +*/ +struct TimeInfectedSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedNoSymptomsToRecovered"; + return "TimeInfectedSymptoms"; } }; -struct InfectedSymptomsToRecovered { - using Type = CustomIndexArray; +/** + * @brief Time that a Person is infected and 'simply' hospitalized in day unit + */ +struct TimeInfectedSevere { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedSymptomsToRecovered"; + return "TimeInfectedSevere"; } }; -struct InfectedSymptomsToSevere { - using Type = CustomIndexArray; +/** + * @brief Time that a Person is treated by ICU in day unit + */ +struct TimeInfectedCritical { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedSymptomsToSevere"; + return "TimeInfectedCritical"; } }; -struct SevereToCritical { - using Type = CustomIndexArray; +/** +* @brief the percentage of symptomatic cases +*/ +struct SymptomsPerInfectedNoSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "SevereToCritical"; + return "SymptomaticPerInfectedNoSymptoms"; } }; -struct SevereToRecovered { - using Type = CustomIndexArray; +/** +* @brief the percentage of hospitalized patients per infected patients +*/ +struct SeverePerInfectedSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "SevereToRecovered"; + return "SeverePerInfectedSymptoms"; } }; -struct CriticalToRecovered { - using Type = CustomIndexArray; +/** +* @brief the percentage of ICU patients per hospitalized patients +*/ +struct CriticalPerInfectedSevere { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "CriticalToRecovered"; + return "CriticalPerInfectedSevere"; } }; -struct CriticalToDead { - using Type = CustomIndexArray; +/** +* @brief the percentage of dead patients per ICU patients +*/ +struct DeathsPerInfectedCritical { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "CriticalToDead"; + return "DeathsPerInfectedCritical"; } }; -struct RecoveredToSusceptible { - using Type = CustomIndexArray; - static Type get_default(AgeGroup size) - { - return Type({VirusVariant::Count, size}, 1.); - } - static std::string name() - { - return "RecoveredToSusceptible"; - } -}; /** * @brief Parameters for the ViralLoad course. Default values taken as constant values from the average from * https://github.com/VirologyCharite/SARS-CoV-2-VL-paper/tree/main @@ -363,7 +380,7 @@ struct PCRTest : public GenericTest { */ struct LockdownDate { using Type = TimePoint; - static auto get_default(AgeGroup /*size*/) + static auto get_default() { return TimePoint(std::numeric_limits::max()); } @@ -524,11 +541,11 @@ struct AgeGroupGotoWork { }; using ParametersBase = - ParameterSet; @@ -597,8 +614,9 @@ class Parameters : public ParametersBase { for (auto i = AgeGroup(0); i < AgeGroup(m_num_groups); ++i) { - if (this->get()[{VirusVariant::Wildtype, i}] < 0) { - log_error("Constraint check: Parameter IncubationPeriod of age group {:.0f} smaller than {:.4f}", + if (this->get()[{VirusVariant::Wildtype, i}].params.a() < 0) { + log_error("Constraint check: Lower end of parameter range IncubationPeriod of age group {:.0f} smaller " + "than {:.4f}", (size_t)i, 0); return true; } diff --git a/cpp/models/ode_secirvvs/parameters.h b/cpp/models/ode_secirvvs/parameters.h index 75540be02a..6fbbe045bb 100644 --- a/cpp/models/ode_secirvvs/parameters.h +++ b/cpp/models/ode_secirvvs/parameters.h @@ -150,7 +150,7 @@ struct IncubationTime { /** * @brief the infectious time for symptomatic cases that are infected but -* who do not need to be hsopitalized in the SECIR model in day unit +* who do not need to be hospitalized in the SECIR model in day unit */ struct TimeInfectedSymptoms { using Type = CustomIndexArray; From 7d92aa8d60567c3b12ba0ddf9cbd8a883ff193bf Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:15:40 +0100 Subject: [PATCH 04/16] Use new enum iterator --- cpp/memilio/utils/stl_util.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cpp/memilio/utils/stl_util.h b/cpp/memilio/utils/stl_util.h index 1c58e4d707..2c4603d55e 100644 --- a/cpp/memilio/utils/stl_util.h +++ b/cpp/memilio/utils/stl_util.h @@ -22,6 +22,8 @@ #include "memilio/utils/metaprogramming.h" +#include +#include #include #include #include @@ -289,6 +291,30 @@ bool contains(Iter b, Iter e, Pred p) return find_if(b, e, p) != e; } +/** + * Get an std::array that contains all members of an enum class. + * The enum class must be a valid index, i.e. members must be sequential starting at 0 and there must + * be a member `Count` at the end, that will not be included in the array. + * Example: + * ``` + * enum class E { A, B, Count }; + * assert(enum_members() == std::array<2, E>(E::A, E::B)); + * ``` + * @tparam T An enum class that is a valid index. + * @return Array of all members of the enum class not including T::Count. + */ +template +constexpr std::array enum_members() +{ + auto enum_members = std::array{}; + auto indices = std::array, size_t(T::Count)>{}; + std::iota(indices.begin(), indices.end(), std::underlying_type_t(0)); + std::transform(indices.begin(), indices.end(), enum_members.begin(), [](auto i) { + return T(i); + }); + return enum_members; +} + } // namespace mio #endif //STL_UTIL_H From a4f16e877f0440b26c95f4a1ff810c7c806aef5c Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:29:06 +0100 Subject: [PATCH 05/16] Fix parameters --- cpp/models/abm/parameters.h | 168 +++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 79 deletions(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 0031e50070..34ad76353b 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -122,10 +122,10 @@ struct TimeInfectedCritical { * @brief the percentage of symptomatic cases */ struct SymptomsPerInfectedNoSymptoms { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -137,10 +137,10 @@ struct SymptomsPerInfectedNoSymptoms { * @brief the percentage of hospitalized patients per infected patients */ struct SeverePerInfectedSymptoms { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -152,10 +152,10 @@ struct SeverePerInfectedSymptoms { * @brief the percentage of ICU patients per hospitalized patients */ struct CriticalPerInfectedSevere { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -167,10 +167,10 @@ struct CriticalPerInfectedSevere { * @brief the percentage of dead patients per ICU patients */ struct DeathsPerInfectedCritical { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -613,77 +613,87 @@ class Parameters : public ParametersBase bool check_constraints() const { for (auto i = AgeGroup(0); i < AgeGroup(m_num_groups); ++i) { - - if (this->get()[{VirusVariant::Wildtype, i}].params.a() < 0) { - log_error("Constraint check: Lower end of parameter range IncubationPeriod of age group {:.0f} smaller " - "than {:.4f}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error( - "Constraint check: Parameter InfectedNoSymptomsToSymptoms of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error( - "Constraint check: Parameter InfectedNoSymptomsToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error( - "Constraint check: Parameter InfectedSymptomsToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter InfectedSymptomsToSevere of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter SevereToCritical of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter SevereToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter CriticalToDead of age group {:.0f} smaller than {:d}", (size_t)i, - 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter CriticalToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter RecoveredToSusceptible of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0 || - this->get()[{VirusVariant::Wildtype, i}] > 1.0) { - log_error("Constraint check: Parameter DetectInfection of age group {:.0f} smaller than {:d} or " - "larger than {:d}", - (size_t)i, 0, 1); - return true; + for (auto&& v : enum_members()) { + + if (this->get()[{v, i}].params.a() < 0) { + log_error("Constraint check: Lower end of parameter range IncubationPeriod of virus variant {} and " + "age group {:.0f} smaller " + "than {:.4f}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptoms of virus variant " + "{} and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSymptoms of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSevere of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedCritical of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter SymptomsPerInfectedNoSymptoms of virus variant {} and age " + "group {:.0f} smaller than {:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter SeverePerInfectedSymptoms of virus variant {} and age group " + "{:.0f} smaller than {:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter CriticalPerInfectedSevere of virus variant {} and age group " + "{:.0f} smaller than {:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter DeathsPerInfectedCritical of age group {:.0f} smaller than " + "{:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter DetectInfection of virus variant {} and age group {:.0f} " + "smaller than {:d} or " + "larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } } if (this->get()[i].seconds() < 0.0 || From 64f2edf5ce5bca2aeba6d39808d099b176900958 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:27:52 +0100 Subject: [PATCH 06/16] Fix infection setup --- cpp/models/abm/infection.cpp | 127 ++++++++++++++++++++--------------- cpp/models/abm/parameters.h | 8 +-- 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 1783942764..07c4f12d50 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -129,76 +129,79 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng InfectionState next_state{start_state}; // next state to enter m_infection_course.push_back(std::pair(t, next_state)); auto& uniform_dist = UniformDistribution::get_instance(); - ScalarType v; // random draws + ScalarType p; // uniform random draws from [0, 1] while ((next_state != InfectionState::Recovered && next_state != InfectionState::Dead)) { switch (next_state) { case InfectionState::Exposed: // roll out how long until infected without symptoms - time_period = days(params.get()[{m_virus_variant, age}]); // subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); next_state = InfectionState::InfectedNoSymptoms; break; case InfectionState::InfectedNoSymptoms: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.5) { // TODO: subject to change - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + p = uniform_dist(rng); + if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedSymptoms; } else { - time_period = days( - params.get()[{m_virus_variant, age}]); // TODO: subject to change next_state = InfectionState::Recovered; } break; case InfectionState::InfectedSymptoms: // roll out next infection step - { - ScalarType severity_protection_factor = 0.5; - v = uniform_dist(rng); - if (latest_exposure.first != ExposureType::NoProtection) { - severity_protection_factor = - params.get()[{latest_exposure.first, age, m_virus_variant}]( - t.days() - latest_exposure.second.days()); - } - if (v < (1 - severity_protection_factor) * 0.5) { - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change - next_state = InfectionState::InfectedSevere; - } - else { - time_period = days( - params.get()[{m_virus_variant, age}]); // TODO: subject to change - next_state = InfectionState::Recovered; - } - break; + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + ScalarType severity_protection_factor = 1.; + p = uniform_dist(rng); + if (latest_exposure.first != ExposureType::NoProtection) { + severity_protection_factor = + params.get()[{latest_exposure.first, age, m_virus_variant}]( + t.days() - latest_exposure.second.days()); } + if (p < + (1 - severity_protection_factor) * params.get()[{m_virus_variant, age}]) { + next_state = InfectionState::InfectedSevere; + } + else { + next_state = InfectionState::Recovered; + } + + break; + case InfectionState::InfectedSevere: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.5) { // TODO: subject to change - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + p = uniform_dist(rng); + if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedCritical; } else { - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change next_state = InfectionState::Recovered; } break; + case InfectionState::InfectedCritical: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.5) { // TODO: subject to change - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + p = uniform_dist(rng); + if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::Dead; } else { - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change next_state = InfectionState::Recovered; } break; + default: break; } @@ -213,61 +216,73 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato { auto start_date = init_date; TimeSpan time_period{}; // time period for current infection state - InfectionState previous_state{init_state}; // next state to enter + InfectionState previous_state{init_state}; // previous state to enter auto& uniform_dist = UniformDistribution::get_instance(); - ScalarType v; // random draws + ScalarType p; // uniform random draws from [0, 1] while ((previous_state != InfectionState::Exposed)) { switch (previous_state) { case InfectionState::InfectedNoSymptoms: - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::Exposed; break; case InfectionState::InfectedSymptoms: - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedNoSymptoms; break; case InfectionState::InfectedSevere: - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSymptoms; break; case InfectionState::InfectedCritical: - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSevere; break; case InfectionState::Recovered: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.25) { - time_period = days( - params.get()[{m_virus_variant, age}]); // TODO: subject to change + p = uniform_dist(rng); + // compute correct probabilities while factoring out the chance to die + auto p_death = params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}]; + if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedNoSymptoms; } - else if (v < 0.5) { // TODO: subject to change - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + else if (p < params.get()[{m_virus_variant, age}] * + (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSymptoms; } - else if (v < 0.75) { - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + else if (p < params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}] * + (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSevere; } else { - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedCritical; } break; case InfectionState::Dead: - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedCritical; break; diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 34ad76353b..2b1e68f95f 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -125,7 +125,7 @@ struct SymptomsPerInfectedNoSymptoms { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { @@ -140,7 +140,7 @@ struct SeverePerInfectedSymptoms { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { @@ -155,7 +155,7 @@ struct CriticalPerInfectedSevere { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { @@ -170,7 +170,7 @@ struct DeathsPerInfectedCritical { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { From 8b995e20d5fe0488205a9c3354df1febbba42003 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:57:17 +0100 Subject: [PATCH 07/16] Fix analyze_result --- cpp/models/abm/analyze_result.h | 63 ++++++++++++++++++++----- cpp/models/abm/test_tree.cpp | 10 ---- cpp/models/abm/weighted_decision_tree.h | 54 --------------------- 3 files changed, 51 insertions(+), 76 deletions(-) delete mode 100644 cpp/models/abm/test_tree.cpp delete mode 100644 cpp/models/abm/weighted_decision_tree.h diff --git a/cpp/models/abm/analyze_result.h b/cpp/models/abm/analyze_result.h index 0e93be84a9..301ee8bffd 100644 --- a/cpp/models/abm/analyze_result.h +++ b/cpp/models/abm/analyze_result.h @@ -62,39 +62,78 @@ std::vector ensemble_params_percentile(const std::vector((uint32_t)virus_variant + 1)) { + for (auto virus_variant : enum_members()) { // Global infection parameters param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { return model.parameters.template get()[{virus_variant, age_group}]; }); diff --git a/cpp/models/abm/test_tree.cpp b/cpp/models/abm/test_tree.cpp deleted file mode 100644 index 9a7b64e6b5..0000000000 --- a/cpp/models/abm/test_tree.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "weighted_decision_tree.h" -#include - -int main(int argc, char const* argv[]) -{ - auto nodes = std::vector({1, 4, 10}); - auto edges = std::vector>({{1, 4, 0.5}, {4, 10, 0.5}}); - auto decision_tree = weighted_decision_tree(nodes, edges); - return 0; -} diff --git a/cpp/models/abm/weighted_decision_tree.h b/cpp/models/abm/weighted_decision_tree.h deleted file mode 100644 index 20047d5d98..0000000000 --- a/cpp/models/abm/weighted_decision_tree.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright (C) 2020-2021 German Aerospace Center (DLR-SC) -* -* Authors: Sascha Korf -* -* 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. -*/ - -#include -#include -#include -#include -#include - -struct TreeNode { - int value; -}; - -struct TreeEdge { - double time_length; -}; - -class weighted_decision_tree -{ -public: - weighted_decision_tree(std::vector nodes, std::vector> edges) - { - for (auto edge : edges) { - auto parent_node = std::find(nodes.begin(), nodes.end(), std::get<0>(edge)); - auto child_node = std::find(nodes.begin(), nodes.end(), std::get<1>(edge)); - build_tree(TreeNode{*parent_node}, TreeEdge{std::get<2>(edge)}, TreeNode{*child_node}); - } - } - -private: - void build_tree(TreeNode node, TreeEdge edge, TreeNode child) - { - m_tree.insert({node, std::make_pair(edge, child)}); - } - - std::map> m_tree; -}; From e74c26c578b54641750106b312e7bbc270fd2396 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 18:05:15 +0100 Subject: [PATCH 08/16] Fix error in transmission --- cpp/models/abm/location.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 2e0c509a6a..4cc043ddb5 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -58,12 +58,13 @@ Location Location::copy_location_without_persons(size_t num_agegroups) ScalarType Location::transmission_contacts_per_day(uint32_t cell_index, VirusVariant virus, AgeGroup age_receiver, size_t num_agegroups) const { - ScalarType prob = 0; + ScalarType transmissions = 0; for (uint32_t age_transmitter = 0; age_transmitter != num_agegroups; ++age_transmitter) { - prob += m_cells[cell_index].m_cached_exposure_rate_contacts[{virus, static_cast(age_transmitter)}] * - m_parameters.get()[{age_receiver, static_cast(age_transmitter)}]; + transmissions += + m_cells[cell_index].m_cached_exposure_rate_contacts[{virus, static_cast(age_transmitter)}] * + m_parameters.get()[{age_receiver, static_cast(age_transmitter)}]; } - return prob; + return transmissions; } ScalarType Location::transmission_air_per_day(uint32_t cell_index, VirusVariant virus, @@ -118,12 +119,22 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou auto virus = inf.get_virus_variant(); auto age = p->get_age(); /* average infectivity over the time step - * to second order accuracy using midpoint rule + * to second order accuracy using midpoint rule */ cell.m_cached_exposure_rate_contacts[{virus, age}] += inf.get_infectivity(t + dt / 2); cell.m_cached_exposure_rate_air[{virus}] += inf.get_infectivity(t + dt / 2); } } + + for (auto age_group = AgeGroup(0); age_group < AgeGroup(num_agegroups); age_group++) { + for (auto& v : cell.m_cached_exposure_rate_contacts.slice(AgeGroup(age_group))) { + v = v / + std::count_if(cell.m_persons.begin(), cell.m_persons.end(), [age_group](observer_ptr p) { + return p->get_age() == age_group; + }); + } + } + if (m_capacity_adapted_transmission_risk) { cell.m_cached_exposure_rate_air.array() *= cell.compute_space_per_person_relative(); } From c7d6f129c43bd35403fa3bf21696bbc0b36a2e54 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 20 Dec 2023 13:07:20 +0100 Subject: [PATCH 09/16] Some fixes --- cpp/models/abm/infection.cpp | 100 +++++++++++++++---------------- cpp/models/abm/parameters.h | 26 ++++---- cpp/tests/test_abm_infection.cpp | 17 ++++-- 3 files changed, 73 insertions(+), 70 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 07c4f12d50..a7673882ee 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -132,16 +132,16 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng ScalarType p; // uniform random draws from [0, 1] while ((next_state != InfectionState::Recovered && next_state != InfectionState::Dead)) { switch (next_state) { - case InfectionState::Exposed: + case InfectionState::Exposed: { // roll out how long until infected without symptoms auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - next_state = InfectionState::InfectedNoSymptoms; - break; - case InfectionState::InfectedNoSymptoms: + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + next_state = InfectionState::InfectedNoSymptoms; + } break; + case InfectionState::InfectedNoSymptoms: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { @@ -150,12 +150,11 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng else { next_state = InfectionState::Recovered; } - - break; - case InfectionState::InfectedSymptoms: + } break; + case InfectionState::InfectedSymptoms: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); ScalarType severity_protection_factor = 1.; p = uniform_dist(rng); @@ -171,36 +170,35 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng else { next_state = InfectionState::Recovered; } + } break; - break; - - case InfectionState::InfectedSevere: + case InfectionState::InfectedSevere: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedCritical; + next_state = InfectionState::InfectedCritical; } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; } - break; + } break; - case InfectionState::InfectedCritical: + case InfectionState::InfectedCritical: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::Dead; + next_state = InfectionState::Dead; } else { next_state = InfectionState::Recovered; } - break; + } break; default: break; @@ -223,31 +221,31 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato while ((previous_state != InfectionState::Exposed)) { switch (previous_state) { - case InfectionState::InfectedNoSymptoms: + case InfectionState::InfectedNoSymptoms: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::Exposed; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::Exposed; + } break; - case InfectionState::InfectedSymptoms: + case InfectionState::InfectedSymptoms: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedNoSymptoms; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; + } break; - case InfectionState::InfectedSevere: + case InfectionState::InfectedSevere: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSymptoms; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; + } break; - case InfectionState::InfectedCritical: + case InfectionState::InfectedCritical: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSevere; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; + } break; - case InfectionState::Recovered: + case InfectionState::Recovered: { // roll out next infection step p = uniform_dist(rng); // compute correct probabilities while factoring out the chance to die @@ -257,34 +255,34 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}]; if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedNoSymptoms; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSymptoms; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSevere; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; } else { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedCritical; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; } - break; + } break; - case InfectionState::Dead: + case InfectionState::Dead: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedCritical; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; + } break; default: break; diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 2958b21056..d57e8cbc2a 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -134,7 +134,7 @@ struct SymptomsPerInfectedNoSymptoms { }; /** -* @brief the percentage of hospitalized patients per infected patients +* @brief the percentage of hospitalized cases per infected cases */ struct SeverePerInfectedSymptoms { using Type = CustomIndexArray; @@ -149,7 +149,7 @@ struct SeverePerInfectedSymptoms { }; /** -* @brief the percentage of ICU patients per hospitalized patients +* @brief the percentage of ICU cases per hospitalized cases */ struct CriticalPerInfectedSevere { using Type = CustomIndexArray; @@ -164,7 +164,7 @@ struct CriticalPerInfectedSevere { }; /** -* @brief the percentage of dead patients per ICU patients +* @brief the percentage of dead cases per ICU cases */ struct DeathsPerInfectedCritical { using Type = CustomIndexArray; @@ -619,7 +619,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range IncubationPeriod of virus variant {} and " "age group {:.0f} smaller " "than {:.4f}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -627,7 +627,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptoms of virus variant " "{} and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -635,7 +635,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedSymptoms of virus variant {} " "and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -643,7 +643,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedSevere of virus variant {} " "and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -651,7 +651,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedCritical of virus variant {} " "and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -659,7 +659,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter SymptomsPerInfectedNoSymptoms of virus variant {} and age " "group {:.0f} smaller than {:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -667,7 +667,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter SeverePerInfectedSymptoms of virus variant {} and age group " "{:.0f} smaller than {:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -675,7 +675,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter CriticalPerInfectedSevere of virus variant {} and age group " "{:.0f} smaller than {:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -683,7 +683,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter DeathsPerInfectedCritical of age group {:.0f} smaller than " "{:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -691,7 +691,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Parameter DetectInfection of virus variant {} and age group {:.0f} " "smaller than {:d} or " "larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } } diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index 82ad0c67e8..ce1a2f4042 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -118,17 +118,22 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(NUM_AGE_GROUPS); - // Time to go from all infected states to recover is 1 day (dt). - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + // Time in all infected states 1 day (dt). + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(14)) .WillOnce(testing::Return(0.1)) // Transition to InfectedNoSymptoms - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) // Time rollout .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) From 5100fb8b9d1ee59f376a9e222b552bfe69153907 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:59:08 +0100 Subject: [PATCH 10/16] Add author Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/models/abm/parameters.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index d57e8cbc2a..3d47b4d21a 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2020-2024 MEmilio * -* Authors: Daniel Abele, Elisabeth Kluth, Khoa Nguyen +* Authors: Daniel Abele, Elisabeth Kluth, Khoa Nguyen, David Kerkmann * * Contact: Martin J. Kuehn * From 85ab275afe12e65568e01a2fb67eca8b7b11dbea Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:35:33 +0100 Subject: [PATCH 11/16] Fix recovered people not beeing able to reinfect. Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/models/abm/person.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index dd493adfc1..bb19191c33 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -61,7 +61,8 @@ Person Person::copy_person(Location& location) void Person::interact(RandomNumberGenerator& rng, TimePoint t, TimeSpan dt, const Parameters& params) { - if (get_infection_state(t) == InfectionState::Susceptible) { // Susceptible + if (get_infection_state(t) == InfectionState::Susceptible || + get_infection_state(t) == InfectionState::Recovered) { // Susceptible or Recovered people can be (re)infected m_location->interact(rng, *this, t, dt, params); } m_time_at_location += dt; From 10bd31e75f24ee3a00243049c828fa56f36c85f5 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:44:33 +0100 Subject: [PATCH 12/16] Change back to infection course related time parameters and fix build. --- cpp/models/abm/analyze_result.h | 100 ++++++++--- cpp/models/abm/infection.cpp | 53 ++++-- cpp/models/abm/infection.h | 1 + cpp/models/abm/parameters.h | 164 ++++++++++++++--- cpp/simulations/abm.cpp | 255 ++++++++++++++++----------- cpp/simulations/abm_braunschweig.cpp | 254 +++++++++++++++----------- cpp/tests/test_abm_infection.cpp | 18 +- cpp/tests/test_abm_location.cpp | 4 +- cpp/tests/test_abm_person.cpp | 2 +- cpp/tests/test_abm_world.cpp | 97 +++++----- cpp/tests/test_analyze_result.cpp | 72 ++++---- 11 files changed, 655 insertions(+), 365 deletions(-) diff --git a/cpp/models/abm/analyze_result.h b/cpp/models/abm/analyze_result.h index 301ee8bffd..8b359c3031 100644 --- a/cpp/models/abm/analyze_result.h +++ b/cpp/models/abm/analyze_result.h @@ -65,59 +65,109 @@ std::vector ensemble_params_percentile(const std::vector()) { // Global infection parameters param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); @@ -197,6 +247,16 @@ std::vector ensemble_params_percentile(const std::vector auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.b(); + return result; + }); param_percentil(node, [virus_variant](auto&& model) -> auto& { return model.parameters.template get()[{virus_variant}]; }); diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index a7673882ee..1118788ca6 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -54,6 +54,9 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age m_log_norm_alpha = inf_params.infectivity_alpha.get_distribution_instance()(rng, inf_params.infectivity_alpha.params); m_log_norm_beta = inf_params.infectivity_beta.get_distribution_instance()(rng, inf_params.infectivity_beta.params); + + auto shedfactor_param = params.get()[{virus, age}]; + m_individual_virus_shed_factor = shedfactor_param.get_distribution_instance()(rng, shedfactor_param.params); } ScalarType Infection::get_viral_load(TimePoint t) const @@ -76,7 +79,7 @@ ScalarType Infection::get_infectivity(TimePoint t) const { if (m_viral_load.start_date >= t || get_infection_state(t) == InfectionState::Exposed) return 0; - return 1 / (1 + exp(-(m_log_norm_alpha + m_log_norm_beta * get_viral_load(t)))); + return m_individual_virus_shed_factor / (1 + exp(-(m_log_norm_alpha + m_log_norm_beta * get_viral_load(t)))); } VirusVariant Infection::get_virus_variant() const @@ -126,6 +129,8 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng { auto t = init_date; TimeSpan time_period{}; // time period for current infection state + auto time_in_state = params.get()[{ + m_virus_variant, age}]; // time distribution parameters for current infection state InfectionState next_state{start_state}; // next state to enter m_infection_course.push_back(std::pair(t, next_state)); auto& uniform_dist = UniformDistribution::get_instance(); @@ -134,27 +139,27 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng switch (next_state) { case InfectionState::Exposed: { // roll out how long until infected without symptoms - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); next_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedNoSymptoms: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; case InfectionState::InfectedSymptoms: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); ScalarType severity_protection_factor = 1.; p = uniform_dist(rng); @@ -166,37 +171,45 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng if (p < (1 - severity_protection_factor) * params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedSevere; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; case InfectionState::InfectedSevere: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedCritical; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; case InfectionState::InfectedCritical: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::Dead; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; @@ -214,6 +227,8 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato { auto start_date = init_date; TimeSpan time_period{}; // time period for current infection state + auto time_in_state = params.get()[{ + m_virus_variant, age}]; // time distribution parameters for current infection state InfectionState previous_state{init_state}; // previous state to enter auto& uniform_dist = UniformDistribution::get_instance(); ScalarType p; // uniform random draws from [0, 1] @@ -222,25 +237,25 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato switch (previous_state) { case InfectionState::InfectedNoSymptoms: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::Exposed; } break; case InfectionState::InfectedSymptoms: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedSevere: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSymptoms; } break; case InfectionState::InfectedCritical: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSevere; } break; @@ -254,32 +269,32 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}]; if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSevere; } else { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedCritical; } } break; case InfectionState::Dead: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedCritical; } break; diff --git a/cpp/models/abm/infection.h b/cpp/models/abm/infection.h index f882d22af2..0e2cc2ce40 100644 --- a/cpp/models/abm/infection.h +++ b/cpp/models/abm/infection.h @@ -159,6 +159,7 @@ class Infection ViralLoad m_viral_load; ///< ViralLoad of the Infection. ScalarType m_log_norm_alpha, m_log_norm_beta; ///< Parameters for the infectivity mapping, which is modelled through an invlogit function. + ScalarType m_individual_virus_shed_factor; ///< Individual virus shed factor. bool m_detected; ///< Whether an Infection is detected or not. }; diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 3d47b4d21a..047227a0c4 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -58,9 +58,9 @@ struct IncubationPeriod { }; /** -* @brief Time that a Person is infected but nonsymptomatic in day unit +* @brief Time that a Person is infected but presymptomatic in day unit */ -struct TimeInfectedNoSymptoms { +struct TimeInfectedNoSymptomsToSymptoms { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -68,15 +68,75 @@ struct TimeInfectedNoSymptoms { } static std::string name() { - return "TimeInfectedNoSymptoms"; + return "TimeInfectedNoSymptomsToSymptoms"; + } +}; + +/** +* @brief Time that a Person is infected when staying asymptomatic in day unit +*/ +struct TimeInfectedNoSymptomsToRecovered { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedNoSymptomsToRecovered"; } }; /** * @brief Time that a Person is infected and symptomatic but -* who do not need to be hospitalized (yet) in day unit +* who do not need to be hospitalized yet in day unit +*/ +struct TimeInfectedSymptomsToSevere { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedSymptomsToSevere"; + } +}; + +/** +* @brief Time that a Person is infected and symptomatic who will recover in day unit */ -struct TimeInfectedSymptoms { +struct TimeInfectedSymptomsToRecovered { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedSymptomsToRecovered"; + } +}; + +/** + * @brief Time that a Person is infected and 'simply' hospitalized before becoming critical in day unit + */ +struct TimeInfectedSevereToCritical { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedSevereToCritical"; + } +}; + +/** + * @brief Time that a Person is infected and 'simply' hospitalized before recovering in day unit + */ +struct TimeInfectedSevereToRecovered { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -84,14 +144,14 @@ struct TimeInfectedSymptoms { } static std::string name() { - return "TimeInfectedSymptoms"; + return "TimeInfectedSevereToRecovered"; } }; /** - * @brief Time that a Person is infected and 'simply' hospitalized in day unit + * @brief Time that a Person is treated by ICU before dying in day unit */ -struct TimeInfectedSevere { +struct TimeInfectedCriticalToDead { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -99,14 +159,14 @@ struct TimeInfectedSevere { } static std::string name() { - return "TimeInfectedSevere"; + return "TimeInfectedCriticalToDead"; } }; /** - * @brief Time that a Person is treated by ICU in day unit + * @brief Time that a Person is treated by ICU before recovering in day unit */ -struct TimeInfectedCritical { +struct TimeInfectedCriticalToRecovered { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -114,7 +174,7 @@ struct TimeInfectedCritical { } static std::string name() { - return "TimeInfectedCritical"; + return "TimeInfectedCriticalToRecovered"; } }; @@ -225,6 +285,22 @@ struct InfectivityDistributions { } }; +/** + * @brief Individual virus shed factor to account for variability in infectious viral load spread. +*/ +struct VirusShedFactor { + using Type = CustomIndexArray::ParamType, VirusVariant, AgeGroup>; + static Type get_default(AgeGroup size) + { + Type default_val({VirusVariant::Count, size}, UniformDistribution::ParamType{0., 0.28}); + return default_val; + } + static std::string name() + { + return "VirusShedFactor"; + } +}; + /** * @brief Probability that an Infection is detected. */ @@ -541,9 +617,11 @@ struct AgeGroupGotoWork { }; using ParametersBase = - ParameterSetget()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptoms of virus variant " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptomsToSymptoms " + "of virus variant " + "{} and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptomsToRecovered of " + "virus variant " "{} and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); return true; } - if (this->get()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedSymptoms of virus variant {} " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSymptomsToSevere of virus " + "variant {} " + "and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSymptomsToRecovered of virus " + "variant {} " + "and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSevereToCritical of virus " + "variant {} " "and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); return true; } - if (this->get()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedSevere of virus variant {} " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSevereToRecovered of virus " + "variant {} " "and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); return true; } - if (this->get()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedCritical of virus variant {} " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error( + "Constraint check: Lower end of parameter range TimeInfectedCriticalToDead of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedCriticalToRecovered of virus " + "variant {} " "and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); diff --git a/cpp/simulations/abm.cpp b/cpp/simulations/abm.cpp index ba1cb50e9c..49886ea686 100644 --- a/cpp/simulations/abm.cpp +++ b/cpp/simulations/abm.cpp @@ -470,153 +470,194 @@ void set_parameters(mio::abm::Parameters params) }; //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.092; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.; - + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.139; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.139; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.123; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.024; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.123; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.024; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.115; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.115; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; // Set each parameter for vaccinated people including personal infection and vaccine protection levels. // Summary: https://doi.org/10.1038/s41577-021-00550-x, //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.132; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.141; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.141; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.133; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.133; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; } /** diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index d9480ed15f..394d107d5e 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -398,90 +398,115 @@ void set_parameters(mio::abm::Parameters params) }; //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.092; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.139; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.139; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.123; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.024; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.123; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.024; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.115; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.115; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; // Set each parameter for vaccinated people including personal infection and vaccine protection levels. // Summary: https://doi.org/10.1038/s41577-021-00550-x, //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.132; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_0_TO_4, @@ -539,16 +564,19 @@ void set_parameters(mio::abm::Parameters params) }; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_5_TO_14, @@ -605,17 +633,21 @@ void set_parameters(mio::abm::Parameters params) }; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; // Set up personal infection and vaccine protection levels, based on: https://doi.org/10.1038/s41577-021-00550-x, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_15_TO_34, mio::abm::VirusVariant::Wildtype}] = @@ -671,17 +703,20 @@ void set_parameters(mio::abm::Parameters params) }; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.141; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.141; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_35_TO_59, @@ -738,17 +773,21 @@ void set_parameters(mio::abm::Parameters params) }; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_60_TO_79, @@ -805,16 +844,19 @@ void set_parameters(mio::abm::Parameters params) }; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.133; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.133; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_80_PLUS, diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index ce1a2f4042..89589070d1 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -118,22 +118,18 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(NUM_AGE_GROUPS); - // Time in all infected states 1 day (dt). - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + // Time to go from all infected states to recover is 1 day (dt). + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 1; ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(14)) .WillOnce(testing::Return(0.1)) // Transition to InfectedNoSymptoms - .WillOnce(testing::Return(0.1)) // Time rollout + .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) diff --git a/cpp/tests/test_abm_location.cpp b/cpp/tests/test_abm_location.cpp index d596fa8ada..c71f461d37 100644 --- a/cpp/tests/test_abm_location.cpp +++ b/cpp/tests/test_abm_location.cpp @@ -159,10 +159,10 @@ TEST(TestLocation, reachCapacity) //setup so p1 doesn't do transition world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto home_id = world.add_location(mio::abm::LocationType::Home); diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index fd14098de8..f5328dcfcc 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -121,7 +121,7 @@ TEST(TestPerson, quarantine) auto t_morning = mio::abm::TimePoint(0) + mio::abm::hours(7); auto dt = mio::abm::hours(1); infection_parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.5 * dt.days(); auto person = make_test_person(home, AGE_GROUP_35_TO_59, mio::abm::InfectionState::InfectedSymptoms, t_morning, diff --git a/cpp/tests/test_abm_world.cpp b/cpp/tests/test_abm_world.cpp index 026b1809db..cc69dcd614 100644 --- a/cpp/tests/test_abm_world.cpp +++ b/cpp/tests/test_abm_world.cpp @@ -133,15 +133,16 @@ TEST(TestWorld, evolveStateTransition) world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto location1 = world.add_location(mio::abm::LocationType::School); @@ -175,11 +176,10 @@ TEST(TestWorld, evolveMigration) auto world = mio::abm::World(NUM_AGE_GROUPS); //setup so p1 doesn't do transition world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = - 2 * dt.days(); - world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); + world.parameters.get()[{mio::abm::VirusVariant::Wildtype, + AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto home_id = world.add_location(mio::abm::LocationType::Home); auto school_id = world.add_location(mio::abm::LocationType::School); @@ -230,14 +230,15 @@ TEST(TestWorld, evolveMigration) auto world = mio::abm::World(NUM_AGE_GROUPS); //setup so p1-p5 don't do transition world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); + world.parameters.get()[{mio::abm::VirusVariant::Wildtype, + AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = - 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto home_id = world.add_location(mio::abm::LocationType::Home); @@ -359,10 +360,12 @@ TEST(TestWorld, evolveMigration) auto world = mio::abm::World(NUM_AGE_GROUPS); // Time to go from severe to critical infection is 1 day (dt). - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.5; // Time to go from critical infection to dead state is 1/2 day (0.5 * dt). - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.5; + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.5; auto home_id = world.add_location(mio::abm::LocationType::Home); auto work_id = world.add_location(mio::abm::LocationType::Work); @@ -409,9 +412,10 @@ TEST(TestWorldTestingCriteria, testAddingAndUpdatingAndRunningTestingSchemes) auto world = mio::abm::World(NUM_AGE_GROUPS); // make sure the infected person stay in Infected long enough - world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = + world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = + 100; + world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = 100; - world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = 100; auto home_id = world.add_location(mio::abm::LocationType::Home); auto work_id = world.add_location(mio::abm::LocationType::Work); @@ -463,15 +467,15 @@ TEST(TestWorld, checkParameterConstraints) auto params = world.parameters; params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 1.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 3.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 10.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 3.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.3; params.get()[AGE_GROUP_35_TO_59] = mio::abm::hours(4); params.get()[AGE_GROUP_35_TO_59] = mio::abm::hours(8); @@ -486,33 +490,34 @@ TEST(TestWorld, checkParameterConstraints) params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -1.; ASSERT_EQ(params.check_constraints(), true); params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 1.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -2.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + -2.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -3.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + -3.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 3.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -4.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 3.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -4.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -5.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -5.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -6.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -6.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -7.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -7.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -8.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -8.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -9.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -9.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -10.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 10.; params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 1.1; ASSERT_EQ(params.check_constraints(), true); params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.3; @@ -580,12 +585,12 @@ TEST(TestWorld, copyWorld) auto infection_params = world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] - .value(); + .params.a(); auto copied_world = mio::abm::World(world); auto copied_infection_params = copied_world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] - .value(); + .params.a(); // Assert the parameters, trips, locations and persons of copied world are logically equal to that of original world ASSERT_EQ(copied_infection_params, infection_params); diff --git a/cpp/tests/test_analyze_result.cpp b/cpp/tests/test_analyze_result.cpp index 8648171b6a..54f4e8c824 100644 --- a/cpp/tests/test_analyze_result.cpp +++ b/cpp/tests/test_analyze_result.cpp @@ -475,27 +475,31 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) auto world1 = mio::abm::World(num_age_groups); auto world2 = mio::abm::World(num_age_groups); - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.1; - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.1; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.2; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.3; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.3; auto g1 = std::vector({world1, world2}); world1.parameters - .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.3; - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.4; + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.3; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.4; world2.parameters - .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.7; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.4; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.5; + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.7; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.4; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.5; auto g2 = std::vector({world1, world2}); @@ -506,48 +510,56 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) auto check1 = ensemble_p49_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check2 = ensemble_p49_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check1, 0.1); EXPECT_EQ(check2, 0.2); auto check3 = ensemble_p51_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check4 = ensemble_p51_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check3, 0.3); EXPECT_EQ(check4, 0.4); auto check5 = ensemble_p49_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check6 = ensemble_p49_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check5, 0.2); EXPECT_EQ(check6, 0.3); auto check7 = ensemble_p51_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check8 = ensemble_p51_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check7, 0.4); EXPECT_EQ(check8, 0.5); From 6f489f69042df007b11fe501015ad631615ba621 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:20:49 +0100 Subject: [PATCH 13/16] Fix from merge --- cpp/simulations/abm.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/abm.cpp b/cpp/simulations/abm.cpp index 685134e28b..1b472a70ab 100644 --- a/cpp/simulations/abm.cpp +++ b/cpp/simulations/abm.cpp @@ -578,15 +578,15 @@ void set_parameters(mio::abm::Parameters params) 0.179; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.142; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.001; From 054b7462c98f1162495faa8abbcbdf91d1f8bf4b Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:00:15 +0100 Subject: [PATCH 14/16] Fix infection tests --- cpp/models/abm/infection.cpp | 6 +-- cpp/tests/test_abm_infection.cpp | 73 ++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index c59d85eb3c..5ba22dd079 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -272,18 +272,18 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}]; - if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + if (p > (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; } - else if (p < params.get()[{m_virus_variant, age}] * + else if (p > params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSymptoms; } - else if (p < params.get()[{m_virus_variant, age}] * + else if (p > params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index 17d2894bc2..ab62404fa6 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -30,6 +30,8 @@ TEST(TestInfection, init) auto virus_variant_test = mio::abm::VirusVariant::Wildtype; auto age_group_test = age_group_15_to_34; + params.get()[{virus_variant_test, age_group_test}] = {0.1, 0.2}; + //set up a personal RNG for infections //uses uniformdistribution but result doesn't matter, so init before the mock mio::abm::Location loc(mio::abm::LocationType::Hospital, 0); @@ -38,9 +40,13 @@ TEST(TestInfection, init) ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) - .Times(testing::AtLeast(7)) + .Times(testing::AtLeast(21)) + // 1st infection + .WillOnce(testing::Return(1.)) // IncubationTime .WillOnce(testing::Return(0.4)) // Transition to Infected + .WillOnce(testing::Return(0.4)) // TimeInfectedNoSymptomsToSymptoms .WillOnce(testing::Return(0.6)) // Transition to Recovered + .WillOnce(testing::Return(0.4)) // TimeInfectedSymptomsToRecovered .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .viral_load_peak.params.a())) // Viral load draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] @@ -51,8 +57,13 @@ TEST(TestInfection, init) .infectivity_alpha.params.a())) // Infectivity draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) - .WillOnce(testing::Return(0.1)) // Transition to Infected - .WillOnce(testing::Return(0.1)) // Transition to Recovered + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor + // 2nd infection + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms + .WillOnce(testing::Return(1.0)) // IncubationTime + .WillOnce(testing::Return(1.0)) // Transition to Recovered + .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToRecovered .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .viral_load_peak.params.a())) // Viral load draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] @@ -63,6 +74,8 @@ TEST(TestInfection, init) .infectivity_alpha.params.a())) // Infectivity draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor .WillRepeatedly(testing::Return(1.0)); auto infection = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, @@ -75,7 +88,7 @@ TEST(TestInfection, init) mio::abm::InfectionState::Exposed); EXPECT_EQ(infection.get_infection_state(mio::abm::TimePoint(0) + mio::abm::days(1)), mio::abm::InfectionState::InfectedNoSymptoms); - EXPECT_NEAR(infection.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), 0.2689414213699951, 1e-14); + EXPECT_NEAR(infection.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), 0.02689414213699951, 1e-14); params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_test, virus_variant_test}] = [](ScalarType days) -> ScalarType { @@ -94,7 +107,7 @@ TEST(TestInfection, init) EXPECT_EQ(infection_w_previous_exp.get_infection_state(mio::abm::TimePoint(0) + mio::abm::days(1)), mio::abm::InfectionState::Recovered); EXPECT_NEAR(infection_w_previous_exp.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), - 0.45760205922564895, 1e-14); + 9.1105119440064545e-05, 1e-14); } TEST(TestInfection, getInfectionState) @@ -118,30 +131,46 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); - // Time to go from all infected states to recover is 1 day (dt). - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = - 1; - ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) - .Times(testing::AtLeast(14)) - .WillOnce(testing::Return(0.1)) // Transition to InfectedNoSymptoms + .Times(testing::AtLeast(32)) + // 1st infection + .WillOnce(testing::Return(1.0)) // Transition to InfectedNoSymptoms + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToRecovered + .WillOnce(testing::Return(1.0)) // IncubationPeriod + .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + // 2nd infection + .WillOnce(testing::Return(0.4)) // Transition to InfectedSymptoms + .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToRecovered + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms + .WillOnce(testing::Return(1.0)) // IncubationPeriod + .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.3)) // Transition to InfectedSymptoms - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.6)) // Transition to InfectedSevere - .WillRepeatedly(testing::Return(0.9)); // Transition to InfectedCritical + // 3rd infection + .WillOnce(testing::Return(0.2)) // Transition to InfectedSevere + .WillOnce(testing::Return(1.0)) // TimeInfectedSevereToRecovered + .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToSevere + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms + .WillOnce(testing::Return(1.0)) // IncubationPeriod + .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + // 4th infection + .WillOnce(testing::Return(0.0)) // Transition to InfectedCritical + .WillOnce(testing::Return(1.0)) //TimeInfectedCriticalToRecovered + .WillRepeatedly(testing::Return(1.0)); auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, From e9069a4896fcbe1458c3bd859c57e1aec518ae9e Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 2 Feb 2024 17:41:46 +0100 Subject: [PATCH 15/16] Adjust contact rates correctly and fix dividing by 0 in exposure rate. --- cpp/models/abm/location.cpp | 49 +++++++++++++++------ cpp/models/abm/location.h | 6 +++ cpp/models/abm/world.cpp | 1 + cpp/tests/test_abm_infection.cpp | 73 ++++++++++++++++++++------------ cpp/tests/test_abm_location.cpp | 14 +++--- 5 files changed, 99 insertions(+), 44 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 3067fb14cb..a24cd2a724 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -59,13 +59,14 @@ ScalarType Location::transmission_contacts_per_day(uint32_t cell_index, VirusVar size_t num_agegroups) const { assert(age_receiver.get() < num_agegroups); - ScalarType transmissions = 0; + + ScalarType transmissions_per_day = 0; for (uint32_t age_transmitter = 0; age_transmitter != num_agegroups; ++age_transmitter) { - transmissions += + transmissions_per_day += m_cells[cell_index].m_cached_exposure_rate_contacts[{virus, static_cast(age_transmitter)}] * m_parameters.get()[{age_receiver, static_cast(age_transmitter)}]; } - return transmissions; + return transmissions_per_day; } ScalarType Location::transmission_air_per_day(uint32_t cell_index, VirusVariant virus, @@ -84,21 +85,19 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time assert(person.get_cells().size() && "Person is in multiple cells. Interact logic is incorrect at the moment."); for (auto cell_index : person.get_cells()) { // TODO: the logic here is incorrect in case a person is in multiple cells - std::pair local_indiv_trans_prob[static_cast(VirusVariant::Count)]; + std::pair local_indiv_expected_trans[static_cast(VirusVariant::Count)]; for (uint32_t v = 0; v != static_cast(VirusVariant::Count); ++v) { VirusVariant virus = static_cast(v); - ScalarType local_indiv_trans_prob_v = - (std::min( - m_parameters.get(), - transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups())) + + ScalarType local_indiv_expected_trans_v = + (transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups()) + transmission_air_per_day(cell_index, virus, global_params)) * - (1 - mask_protection) * dt.days() * (1 - person.get_protection_factor(t, virus, global_params)); + (1 - mask_protection) * (1 - person.get_protection_factor(t, virus, global_params)); - local_indiv_trans_prob[v] = std::make_pair(virus, local_indiv_trans_prob_v); + local_indiv_expected_trans[v] = std::make_pair(virus, local_indiv_expected_trans_v); } VirusVariant virus = random_transition(rng, VirusVariant::Count, dt, - local_indiv_trans_prob); // use VirusVariant::Count for no virus submission + local_indiv_expected_trans); // use VirusVariant::Count for no virus submission if (virus != VirusVariant::Count) { person.add_new_infection(Infection(rng, virus, age_receiver, global_params, t + dt / 2, mio::abm::InfectionState::Exposed, person.get_latest_protection(), @@ -107,6 +106,28 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time } } +void Location::adjust_contact_rates(size_t num_agegroups) +{ + ScalarType total_contacts = 0.; + for (auto contact_from = AgeGroup(0); contact_from < AgeGroup(num_agegroups); contact_from++) { + // slizing would be preferred but is problematic since both Tags of ContactRates are AgeGroup + for (auto contact_to = AgeGroup(0); contact_to < AgeGroup(num_agegroups); contact_to++) { + total_contacts += m_parameters.get()[{contact_from, contact_to}]; + } + if (total_contacts > m_parameters.get()) { + for (auto contact_to = AgeGroup(0); contact_to < AgeGroup(num_agegroups); contact_to++) { + m_parameters.get()[{contact_from, contact_to}] = + m_parameters.get()[{contact_from, contact_to}] * m_parameters.get() / + total_contacts; + } + } + total_contacts = 0; + //auto contact_rates_slice = m_parameters.get().slice(AgeGroup(contact_from)); + //auto total_contacts = std::accumulate(contact_rates_slice.begin(), contact_rates_slice.end(), 0.); + //contact_rates_slice = std::min(1., m_parameters.get() / total_contacts) * contact_rates_slice; + } +} + void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegroups) { //cache for next step so it stays constant during the step while subpopulations change @@ -127,12 +148,16 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou } } + // normalize contact exposure rate by number of people in age groups for (auto age_group = AgeGroup(0); age_group < AgeGroup(num_agegroups); age_group++) { for (auto& v : cell.m_cached_exposure_rate_contacts.slice(AgeGroup(age_group))) { - v = v / + auto number_persons_in_age_group = std::count_if(cell.m_persons.begin(), cell.m_persons.end(), [age_group](observer_ptr p) { return p->get_age() == age_group; }); + if (number_persons_in_age_group > 0) { + v = v / number_persons_in_age_group; + } } } diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index 1c8f2d027c..04bf941f73 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -213,6 +213,12 @@ class Location */ void remove_person(Person& person); + /** + * @brief Adjust local contact rates based on maximum contacts. + * @param[in] num_agegroups The number of age groups in the model. + */ + void adjust_contact_rates(size_t num_agegroups); + /** * @brief Prepare the Location for the next Simulation step. * @param[in] t Current TimePoint of the Simulation. diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index e534b8cec0..859b93320e 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -152,6 +152,7 @@ void World::begin_step(TimePoint t, TimeSpan dt) PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; + location->adjust_contact_rates(parameters.get_num_groups()); location->cache_exposure_rates(t, dt, parameters.get_num_groups()); } } diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index ab62404fa6..2f1b78aabb 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -131,6 +131,9 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); + auto virus_variant_test = mio::abm::VirusVariant::Wildtype; + auto age_group_test = age_group_60_to_79; + ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(32)) @@ -138,51 +141,69 @@ TEST(TestInfection, drawInfectionCourseBackward) .WillOnce(testing::Return(1.0)) // Transition to InfectedNoSymptoms .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToRecovered .WillOnce(testing::Return(1.0)) // IncubationPeriod - .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_peak.params.a())) // Viral load draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_incline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_decline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_alpha.params.a())) // Infectivity draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor // 2nd infection .WillOnce(testing::Return(0.4)) // Transition to InfectedSymptoms .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToRecovered .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms .WillOnce(testing::Return(1.0)) // IncubationPeriod - .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_peak.params.a())) // Viral load draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_incline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_decline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_alpha.params.a())) // Infectivity draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor // 3rd infection .WillOnce(testing::Return(0.2)) // Transition to InfectedSevere .WillOnce(testing::Return(1.0)) // TimeInfectedSevereToRecovered .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToSevere .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms .WillOnce(testing::Return(1.0)) // IncubationPeriod - .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_peak.params.a())) // Viral load draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_incline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_decline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_alpha.params.a())) // Infectivity draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor // 4th infection .WillOnce(testing::Return(0.0)) // Transition to InfectedCritical .WillOnce(testing::Return(1.0)) //TimeInfectedCriticalToRecovered .WillRepeatedly(testing::Return(1.0)); - auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection1 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); - auto infection2 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection2 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); - auto infection3 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection3 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); - auto infection4 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection4 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); EXPECT_EQ(infection1.get_infection_state(t), mio::abm::InfectionState::InfectedNoSymptoms); diff --git a/cpp/tests/test_abm_location.cpp b/cpp/tests/test_abm_location.cpp index 85943b9302..d9166250f9 100644 --- a/cpp/tests/test_abm_location.cpp +++ b/cpp/tests/test_abm_location.cpp @@ -111,6 +111,7 @@ TEST(TestLocation, CacheExposureRate) auto dt = mio::abm::seconds(10000); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); + params.get()[{variant, age}] = 0.1; // setup a location with some chance of exposure mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups, 1); @@ -129,11 +130,12 @@ TEST(TestLocation, CacheExposureRate) //cache precomputed results location.cache_exposure_rates(t, dt, num_age_groups); - EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_contacts[{variant, age}]), 0.015015859523894731, 1e-14); - EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.015015859523894731, 1e-14); - EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_contacts[{variant, age}]), 0.0075079297619473654, + EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_contacts[{variant, age}]), 0.0015015859523894731, 1e-14); - EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.0075079297619473654, 1e-14); + EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.0015015859523894731, 1e-14); + EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_contacts[{variant, age}]), 0.00075079297619473654, + 1e-14); + EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.00075079297619473654, 1e-14); EXPECT_NEAR((location.get_cells()[2].m_cached_exposure_rate_contacts[{variant, age}]), 0, 1e-14); EXPECT_NEAR((location.get_cells()[2].m_cached_exposure_rate_air[{variant}]), 0, 1e-14); @@ -144,8 +146,8 @@ TEST(TestLocation, CacheExposureRate) location.set_capacity(2, 22, 2); // Capacity for Cell 3 location.cache_exposure_rates(t, dt, num_age_groups); - EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.045047578571684191, 1e-14); - EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.022523789285842095, 1e-14); + EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.0045047578571684191, 1e-14); + EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.0022523789285842095, 1e-14); EXPECT_NEAR((location.get_cells()[2].m_cached_exposure_rate_air[{variant}]), 0, 1e-14); } From 0703b8d58abb773c667ef751e3f4af2e94d7f1a2 Mon Sep 17 00:00:00 2001 From: jubicker Date: Tue, 20 Aug 2024 13:20:21 +0200 Subject: [PATCH 16/16] bug in draw_infection_course_backward --- cpp/models/abm/infection.cpp | 82 ++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 5ba22dd079..705de0cd87 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -142,21 +142,21 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng switch (next_state) { case InfectionState::Exposed: { // roll out how long until infected without symptoms - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - next_state = InfectionState::InfectedNoSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + next_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedNoSymptoms: { // roll out next infection step p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedSymptoms; + next_state = InfectionState::InfectedSymptoms; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -173,12 +173,12 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng } if (p < (1 - severity_protection_factor) * params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedSevere; + next_state = InfectionState::InfectedSevere; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -189,12 +189,12 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedCritical; + next_state = InfectionState::InfectedCritical; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -205,12 +205,12 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::Dead; + next_state = InfectionState::Dead; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -241,27 +241,27 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato switch (previous_state) { case InfectionState::InfectedNoSymptoms: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::Exposed; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::Exposed; } break; case InfectionState::InfectedSymptoms: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedNoSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedSevere: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; } break; case InfectionState::InfectedCritical: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSevere; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; } break; case InfectionState::Recovered: { @@ -272,35 +272,35 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}]; - if (p > (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedNoSymptoms; + if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; } - else if (p > params.get()[{m_virus_variant, age}] * + else if (p < params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; } - else if (p > params.get()[{m_virus_variant, age}] * + else if (p < params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSevere; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; } else { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedCritical; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; } } break; case InfectionState::Dead: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedCritical; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; } break; default: