parameter_space.h Source File

CPP API: parameter_space.h Source File
ode_secirts/parameter_space.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Henrik Zunker, Wadim Koslow, Daniel Abele, Martin J. Kühn
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef MIO_ODE_SECIRTS_PARAMETER_SPACE_H
21 #define MIO_ODE_SECIRTS_PARAMETER_SPACE_H
22 
24 #include "memilio/utils/memory.h"
25 #include "memilio/utils/logging.h"
28 #include "ode_secirts/model.h"
29 
30 #include <assert.h>
31 #include <string>
32 #include <vector>
33 #include <random>
34 #include <memory>
35 
36 namespace mio
37 {
38 namespace osecirts
39 {
46 template <typename FP>
48 {
49  model.parameters.template get<ICUCapacity<FP>>().draw_sample();
50  model.parameters.template get<TestAndTraceCapacity<FP>>().draw_sample();
51 
52  const static std::vector<InfectionState> naive_immunity_states = {
62  };
63 
64  const static std::vector<InfectionState> partial_immunity_states = {
70  };
71 
72  const static std::vector<InfectionState> improved_immunity_states = {
78  };
79 
80  // helper function to calculate the total population of a layer for a given age group
81  auto calculate_layer_total = [&model](const std::vector<InfectionState>& states, AgeGroup ageGroup) {
82  return std::accumulate(states.begin(), states.end(), FP(0.0),
83  [&model, &ageGroup](FP sum, const InfectionState& state) {
84  return evaluate_intermediate<FP>(sum + model.populations[{ageGroup, state}]);
85  });
86  };
87 
88  // helper function to adjust the susceptible population of a layer for a given age group
89  auto adjust_susceptible_population = [&model](AgeGroup i, FP diff, InfectionState susceptibleState) {
90  model.populations[{i, susceptibleState}] += diff;
91  if (model.populations[{i, susceptibleState}] < 0) {
92  mio::log_warning("Negative population in State " + std::to_string(static_cast<size_t>(susceptibleState)) +
93  " for age group " + std::to_string(static_cast<size_t>(i)) + ". Setting to 0.");
94  model.populations[{i, susceptibleState}] = 0;
95  }
96  };
97 
98  for (auto i = AgeGroup(0); i < model.parameters.get_num_groups(); i++) {
99 
100  const FP group_naive_total = calculate_layer_total(naive_immunity_states, i);
101  const FP group_partial_total = calculate_layer_total(partial_immunity_states, i);
102  const FP group_improved_total = calculate_layer_total(improved_immunity_states, i);
103 
104  //sample initial compartments (with exceptions)
105  for (auto inf_state = Index<InfectionState>(0); inf_state < InfectionState::Count; ++inf_state) {
106  if (inf_state != InfectionState::DeadNaive && //not sampled, fixed from data
107  inf_state != InfectionState::DeadPartialImmunity && //not sampled, fixed from data
108  inf_state != InfectionState::DeadImprovedImmunity) { //not sampled, fixed from data
109  model.populations[{i, inf_state}].draw_sample();
110  }
111  }
112  const FP diff_naive = group_naive_total - calculate_layer_total(naive_immunity_states, i);
113  const FP diff_partial = group_partial_total - calculate_layer_total(partial_immunity_states, i);
114  const FP diff_improved = group_improved_total - calculate_layer_total(improved_immunity_states, i);
115 
116  adjust_susceptible_population(i, diff_naive, InfectionState::SusceptibleNaive);
117  adjust_susceptible_population(i, diff_partial, InfectionState::SusceptiblePartialImmunity);
118  adjust_susceptible_population(i, diff_improved, InfectionState::SusceptibleImprovedImmunity);
119  }
120 }
121 
129 template <typename FP>
131 {
132  model.parameters.template get<Seasonality<FP>>().draw_sample();
133 
134  //not age dependent
135  model.parameters.template get<TimeExposed<FP>>()[AgeGroup(0)].draw_sample();
136  model.parameters.template get<TimeInfectedNoSymptoms<FP>>()[AgeGroup(0)].draw_sample();
137  model.parameters.template get<RelativeTransmissionNoSymptoms<FP>>()[AgeGroup(0)].draw_sample();
138  model.parameters.template get<RiskOfInfectionFromSymptomatic<FP>>()[AgeGroup(0)].draw_sample();
139  model.parameters.template get<MaxRiskOfInfectionFromSymptomatic<FP>>()[AgeGroup(0)].draw_sample();
140  model.parameters.template get<TimeTemporaryImmunityPI<FP>>()[AgeGroup(0)].draw_sample();
141  model.parameters.template get<TimeTemporaryImmunityII<FP>>()[AgeGroup(0)].draw_sample();
142 
143  model.parameters.template get<ReducExposedPartialImmunity<FP>>()[AgeGroup(0)].draw_sample();
144  model.parameters.template get<ReducExposedImprovedImmunity<FP>>()[AgeGroup(0)].draw_sample();
145  model.parameters.template get<ReducInfectedSymptomsPartialImmunity<FP>>()[AgeGroup(0)].draw_sample();
146  model.parameters.template get<ReducInfectedSymptomsImprovedImmunity<FP>>()[AgeGroup(0)].draw_sample();
147  model.parameters.template get<ReducInfectedSevereCriticalDeadPartialImmunity<FP>>()[AgeGroup(0)].draw_sample();
148  model.parameters.template get<ReducInfectedSevereCriticalDeadImprovedImmunity<FP>>()[AgeGroup(0)].draw_sample();
149  model.parameters.template get<ReducTimeInfectedMild<FP>>()[AgeGroup(0)].draw_sample();
150 
151  for (auto i = AgeGroup(0); i < model.parameters.get_num_groups(); i++) {
152  //not age dependent
153  model.parameters.template get<TimeExposed<FP>>()[i] =
154  model.parameters.template get<TimeExposed<FP>>()[AgeGroup(0)];
155  model.parameters.template get<TimeInfectedNoSymptoms<FP>>()[i] =
156  model.parameters.template get<TimeInfectedNoSymptoms<FP>>()[AgeGroup(0)];
157  model.parameters.template get<RelativeTransmissionNoSymptoms<FP>>()[i] =
159  model.parameters.template get<RiskOfInfectionFromSymptomatic<FP>>()[i] =
161  model.parameters.template get<MaxRiskOfInfectionFromSymptomatic<FP>>()[i] =
163 
164  model.parameters.template get<ReducExposedPartialImmunity<FP>>()[i] =
166  model.parameters.template get<ReducExposedImprovedImmunity<FP>>()[i] =
168  model.parameters.template get<ReducInfectedSymptomsPartialImmunity<FP>>()[i] =
170  model.parameters.template get<ReducInfectedSymptomsImprovedImmunity<FP>>()[i] =
172  model.parameters.template get<ReducInfectedSevereCriticalDeadPartialImmunity<FP>>()[i] =
174  model.parameters.template get<ReducInfectedSevereCriticalDeadImprovedImmunity<FP>>()[i] =
176  model.parameters.template get<ReducTimeInfectedMild<FP>>()[i] =
177  model.parameters.template get<ReducTimeInfectedMild<FP>>()[AgeGroup(0)];
178 
179  //age dependent
180  model.parameters.template get<TimeInfectedSymptoms<FP>>()[i].draw_sample();
181  model.parameters.template get<TimeInfectedSevere<FP>>()[i].draw_sample();
182  model.parameters.template get<TimeInfectedCritical<FP>>()[i].draw_sample();
183 
184  model.parameters.template get<TransmissionProbabilityOnContact<FP>>()[i].draw_sample();
185  model.parameters.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i].draw_sample();
186  model.parameters.template get<DeathsPerCritical<FP>>()[i].draw_sample();
187  model.parameters.template get<SeverePerInfectedSymptoms<FP>>()[i].draw_sample();
188  model.parameters.template get<CriticalPerSevere<FP>>()[i].draw_sample();
189  }
190 }
191 
199 template <typename FP>
200 void draw_sample(Model<FP>& model)
201 {
202  draw_sample_infection<FP>(model);
203  draw_sample_demographics<FP>(model);
204  model.parameters.template get<ContactPatterns<FP>>().draw_sample();
205  model.apply_constraints();
206 }
207 
216 template <typename FP>
218 {
219  Graph<Model<FP>, MobilityParameters<FP>> sampled_graph;
220 
221  //sample global parameters
222  auto& shared_params_model = graph.nodes()[0].property;
223  draw_sample_infection<FP>(shared_params_model);
224  auto& shared_contacts = shared_params_model.parameters.template get<ContactPatterns<FP>>();
225  shared_contacts.draw_sample_dampings();
226  auto& shared_dynamic_npis = shared_params_model.parameters.template get<DynamicNPIsInfectedSymptoms<FP>>();
227  shared_dynamic_npis.draw_sample();
228 
229  for (auto& params_node : graph.nodes()) {
230  auto& node_model = params_node.property;
231 
232  //sample local parameters
233  draw_sample_demographics<FP>(params_node.property);
234 
235  //copy global parameters
236  //save demographic parameters so they aren't overwritten
237  auto local_icu_capacity = node_model.parameters.template get<ICUCapacity<FP>>();
238  auto local_tnt_capacity = node_model.parameters.template get<TestAndTraceCapacity<FP>>();
239  auto local_holidays = node_model.parameters.template get<ContactPatterns<FP>>().get_school_holidays();
240  auto local_daily_v1 = node_model.parameters.template get<DailyPartialVaccinations<FP>>();
241  auto local_daily_v2 = node_model.parameters.template get<DailyFullVaccinations<FP>>();
242  auto local_daily_v3 = node_model.parameters.template get<DailyBoosterVaccinations<FP>>();
243  node_model.parameters = shared_params_model.parameters;
244  node_model.parameters.template get<ICUCapacity<FP>>() = local_icu_capacity;
245  node_model.parameters.template get<TestAndTraceCapacity<FP>>() = local_tnt_capacity;
246  node_model.parameters.template get<ContactPatterns<FP>>().get_school_holidays() = local_holidays;
247  node_model.parameters.template get<DailyPartialVaccinations<FP>>() = local_daily_v1;
248  node_model.parameters.template get<DailyFullVaccinations<FP>>() = local_daily_v2;
249  node_model.parameters.template get<DailyBoosterVaccinations<FP>>() = local_daily_v3;
250 
251  node_model.parameters.template get<ContactPatterns<FP>>().make_matrix();
252  node_model.apply_constraints();
253 
254  sampled_graph.add_node(params_node.id, node_model);
255  }
256 
257  for (auto& edge : graph.edges()) {
258  auto edge_params = edge.property;
259  //no dynamic NPIs
260  //TODO: add switch to optionally enable dynamic NPIs to edges
261  sampled_graph.add_edge(edge.start_node_idx, edge.end_node_idx, edge_params);
262  }
263 
264  return sampled_graph;
265 }
266 
267 } // namespace osecirts
268 } // namespace mio
269 
270 #endif // MIO_ODE_SECIRTS_PARAMETER_SPACE_H
generic graph structure
Definition: graph.h:153
requires std::constructible_from< EdgePropertyT, Args... > void add_edge(size_t start_node_idx, size_t end_node_idx, Args &&... args)
add an edge to the graph.
Definition: graph.h:238
requires std::constructible_from< NodePropertyT, Args... > void add_node(int id, Args &&... args)
add a node to the graph.
Definition: graph.h:223
An Index with more than one template parameter combines several Index objects.
Definition: index.h:181
parameters that influence mobility.
Definition: metapopulation_mobility_instant.h:123
Definition: ode_secirts/model.h:102
void draw_sample(Model< FP > &model)
Draws a sample from model parameter distributions and stores sample values as parameters values (cf.
Definition: ode_secirts/parameter_space.h:200
void draw_sample_demographics(Model< FP > &model)
Draws a sample from the specified distributions for all parameters related to the demographics,...
Definition: ode_secirts/parameter_space.h:47
InfectionState
The InfectionState enum describes the possible categories for the infectious state of persons.
Definition: ode_secirts/infection_state.h:37
Graph< Model< FP >, MobilityParameters< FP > > draw_sample(Graph< Model< FP >, MobilityParameters< FP >> &graph)
Draws samples for each model node in a graph.
Definition: ode_secirts/parameter_space.h:217
void draw_sample_infection(Model< FP > &model)
Draws a sample from the specified distributions for all parameters related to the infection.
Definition: ode_secirts/parameter_space.h:130
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
auto i
Definition: io.h:809
void log_warning(spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:112
constexpr std::tuple_element< I, std::tuple< Index< CategoryTags >... > >::type & get(Index< CategoryTags... > &i) noexcept
Retrieves the Index (by reference) at the Ith position of a MultiIndex.
Definition: index.h:294
The AgeGroup struct is used as a dynamically sized tag for all age dependent categories.
Definition: age_group.h:32
bool apply_constraints()
Checks whether the model satisfies all constraints.
Definition: compartmental_model.h:131
Populations populations
Definition: compartmental_model.h:156
ParameterSet parameters
Definition: compartmental_model.h:157
Risk of infection from symptomatic cases increases if test and trace capacity is exceeded.
Definition: ode_secirts/parameters.h:428
Factor to reduce infection risk for persons with improved immunity.
Definition: ode_secirts/parameters.h:615
Factor to reduce infection risk for persons with partial immunity.
Definition: ode_secirts/parameters.h:598
Factor to reduce risk of hospitalization for persons with improved immunity.
Definition: ode_secirts/parameters.h:684
Factor to reduce risk of hospitalization for persons with partial immunity.
Definition: ode_secirts/parameters.h:667
Factor to reduce risk of developing symptoms for persons with improved immunity.
Definition: ode_secirts/parameters.h:649
Factor to reduce risk of developing symptoms for persons with partial immunity.
Definition: ode_secirts/parameters.h:632
Factor to reduce infectious time of persons with partial or improved immunity.
Definition: ode_secirts/parameters.h:701
The relative infectability from individuals located in the InfectedNoSymptoms infection state.
Definition: ode_secirts/parameters.h:377
The risk of infection from symptomatic cases in the SECIRTS model.
Definition: ode_secirts/parameters.h:411
Represents the mean latent time in days for different age groups.
Definition: ode_secirts/parameters.h:202
The (mean) time in day unit for asymptomatic cases that are infected but have not yet developed sympt...
Definition: ode_secirts/parameters.h:220