feedback_simulation.h Source File

CPP API: feedback_simulation.h Source File
feedback_simulation.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Henrik Zunker
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_COMPARTMENTS_FEEDBACK_SIMULATION_H
21 #define MIO_COMPARTMENTS_FEEDBACK_SIMULATION_H
22 
28 
29 namespace mio
30 {
38 template <typename FP>
42  {
43  return Type(size.get());
44  }
45  static std::string name()
46  {
47  return "ICUOccupancyHistory";
48  }
49 };
50 
54 template <typename FP>
56  using Type = FP;
58  {
59  return FP(6);
60  }
61  static std::string name()
62  {
63  return "GammaShapeParameter";
64  }
65 };
66 
70 template <typename FP>
72  using Type = FP;
74  {
75  return FP(0.4);
76  }
77  static std::string name()
78  {
79  return "GammaScaleParameter";
80  }
81 };
82 
86 struct GammaCutOff {
87  using Type = size_t;
89  {
90  return Type(45);
91  }
92  static std::string name()
93  {
94  return "GammaCutOff";
95  }
96 };
97 
101 template <typename FP>
103  using Type = std::vector<FP>;
105  {
106  return Type(1, FP(1.0));
107  }
108  static std::string name()
109  {
110  return "ContactReductionMax";
111  }
112 };
113 
117 template <typename FP>
119  using Type = std::vector<FP>;
121  {
122  return Type(1, FP(0.0));
123  }
124  static std::string name()
125  {
126  return "ContactReductionMin";
127  }
128 };
129 
133 template <typename FP>
135  using Type = FP;
137  {
138  return Type(0.1);
139  }
140  static std::string name()
141  {
142  return "SoftPlusCurvatureParameter";
143  }
144 };
145 
149 template <typename FP>
151  using Type = FP;
153  {
154  return Type(9.0);
155  }
156  static std::string name()
157  {
158  return "NominalICUCapacity";
159  }
160 };
161 
166 template <typename FP>
168  using Type = FP;
170  {
171  return FP(1.0);
172  }
173  static std::string name()
174  {
175  return "BlendingFactorLocal";
176  }
177 };
178 
182 template <typename FP>
184  using Type = FP;
186  {
187  return FP(0.0);
188  }
189  static std::string name()
190  {
191  return "BlendingFactorRegional";
192  }
193 };
194 
195 template <typename FP>
200 
212 template <typename FP, typename Sim, typename ContactPatterns>
214 {
215 public:
216  using Model = typename Sim::Model;
217 
224  explicit FeedbackSimulation(Sim&& sim, const std::vector<size_t>& icu_indices)
225  : m_simulation(std::move(sim))
226  , m_icu_indices(icu_indices)
227  , m_feedback_parameters(m_simulation.get_model().parameters.get_num_groups())
228  , m_perceived_risk(static_cast<Eigen::Index>(m_simulation.get_model().parameters.get_num_groups().get()))
230  static_cast<Eigen::Index>(m_simulation.get_model().parameters.get_num_groups().get()))
231  , m_global_icu_occupancy(static_cast<Eigen::Index>(m_simulation.get_model().parameters.get_num_groups().get()))
232  {
233  }
234 
249  auto advance(const FP tmax, const FP dt_feedback = 1.0)
250  {
251  using std::min;
252  FP t = m_simulation.get_result().get_last_time();
253  while (t < tmax) {
254  FP dt_eff = min<FP>(dt_feedback, tmax - t);
255  apply_feedback(t + dt_eff);
256  m_simulation.advance(t + dt_eff);
257  add_icu_occupancy(t + dt_eff);
258  t += dt_eff;
259  }
260  return m_simulation.get_result().get_last_value();
261  }
262 
266  auto& get_result()
267  {
268  return m_simulation.get_result();
269  }
270 
274  auto& get_model()
275  {
276  return m_simulation.get_model();
277  }
278 
279  const auto& get_model() const
280  {
281  return m_simulation.get_model();
282  }
283 
287  auto& get_perceived_risk() const
288  {
289  return m_perceived_risk;
290  }
292  {
293  return m_perceived_risk;
294  }
295 
300  {
301  return m_feedback_parameters;
302  }
303 
313  {
314  const auto& local_icu_occ = m_feedback_parameters.template get<ICUOccupancyHistory<FP>>();
315  size_t num_time_points = local_icu_occ.get_num_time_points();
316  size_t n = std::min(static_cast<size_t>(num_time_points), m_feedback_parameters.template get<GammaCutOff>());
317  FP perceived_risk = 0.0;
318  const auto& a = m_feedback_parameters.template get<GammaShapeParameter<FP>>();
319  const auto& b = m_feedback_parameters.template get<GammaScaleParameter<FP>>();
320 
321  const auto& blending_local = m_feedback_parameters.template get<BlendingFactorLocal<FP>>();
322  const auto& blending_regional = m_feedback_parameters.template get<BlendingFactorRegional<FP>>();
323  const auto& blending_global = 1 - blending_local - blending_regional;
324 
325  // assert that that each blending factor is positive
326  assert(blending_local >= 0 && blending_regional >= 0 && blending_global >= 0 &&
327  "Blending factors must be non-negative.");
328 
329  for (size_t i = num_time_points - n; i < num_time_points; ++i) {
330  size_t day = i - (num_time_points - n);
331  FP gamma = std::pow(b, a) * std::pow(day, a - 1) * std::exp(-b * day) / std::tgamma(a);
332  FP perc_risk = 0.0;
333 
334  if (blending_local > 0) {
335  perc_risk += blending_local * local_icu_occ.get_value(i).sum() /
336  m_feedback_parameters.template get<NominalICUCapacity<FP>>();
337  }
338  if (blending_regional > 0 && m_regional_icu_occupancy.get_num_time_points() > 0) {
339  perc_risk += blending_regional * m_regional_icu_occupancy.get_value(i).sum() /
340  m_feedback_parameters.template get<NominalICUCapacity<FP>>();
341  }
342  if (blending_global > 0 && m_global_icu_occupancy.get_num_time_points() > 0) {
343  perc_risk += blending_global * m_global_icu_occupancy.get_value(i).sum() /
344  m_feedback_parameters.template get<NominalICUCapacity<FP>>();
345  }
346 
347  perc_risk = std::min(perc_risk, 1.0);
348  perceived_risk += perc_risk * gamma;
349  }
350  return perceived_risk;
351  }
352 
362  void add_icu_occupancy(FP t)
363  {
364  auto& model = m_simulation.get_model();
365  size_t num_groups = static_cast<size_t>(model.parameters.get_num_groups());
366  const auto& last_values = m_simulation.get_result().get_last_value();
367  Eigen::VectorX<FP> icu_occ(num_groups);
368  for (size_t i = 0; i < m_icu_indices.size(); ++i) {
369  icu_occ[i] = last_values[m_icu_indices[i]];
370  }
371  // normalize by total population and scale to 100,000 inhabitants
372  icu_occ = icu_occ / model.populations.get_total() * 100000;
373  m_feedback_parameters.template get<ICUOccupancyHistory<FP>>().add_time_point(t, icu_occ);
374  }
375 
383  {
384  m_regional_icu_occupancy = icu_regional;
385  }
386 
393  {
394  m_global_icu_occupancy = icu_global;
395  }
396 
405  void apply_feedback(FP t)
406  {
407  using std::exp;
408  using std::log;
409  using std::min;
410 
411  // get model parameters
412  auto& params = m_simulation.get_model().parameters;
413  const auto num_groups = (size_t)params.get_num_groups();
414 
415  // get feedback parameters
416  const auto& contactReductionMax = m_feedback_parameters.template get<ContactReductionMax<FP>>();
417  const auto& contactReductionMin = m_feedback_parameters.template get<ContactReductionMin<FP>>();
418  const auto epsilon = m_feedback_parameters.template get<SoftPlusCurvatureParameter<FP>>();
419 
420  const size_t num_locations = contactReductionMax.size();
421 
422  // calculate local perceived risk
423  FP perceived_risk = calc_risk_perceived();
424 
425  // add the perceived risk to the time series
426  m_perceived_risk.add_time_point(t, Eigen::VectorX<FP>::Constant(num_groups, perceived_risk));
427 
428  auto group_weights_all = Eigen::VectorX<FP>::Constant(num_groups, 1.0);
429 
430  // define a lambda function to create a damping sampling object given a reduction factor and location
431  auto set_contact_reduction = [=](FP val, size_t location) {
432  auto v = mio::UncertainValue<FP>(val);
433  return mio::DampingSampling(v, mio::DampingLevel(0), mio::DampingType(0), mio::SimulationTime<FP>(t),
434  std::vector<size_t>{location}, group_weights_all);
435  };
436 
437  auto& dampings = params.template get<ContactPatterns>().get_dampings();
438 
439  // for each location, compute the effective contact reduction factor and add the corresponding damping sample
440  for (size_t loc = 0; loc < num_locations; ++loc) {
441 
442  // compute the effective reduction factor using a softplus function.
443  FP reduc_fac = (contactReductionMax[loc] - contactReductionMin[loc]) * epsilon *
444  log(exp(perceived_risk / epsilon) + 1.0) +
445  contactReductionMin[loc];
446 
447  // clamp the reduction factor to the maximum allowed value.
448  reduc_fac = min<FP>(reduc_fac, contactReductionMax[loc]);
449 
450  // generate the damping for the current location.
451  auto damping = set_contact_reduction(reduc_fac, loc);
452 
453  // add the damping to the contact pattern.
454  dampings.push_back(damping);
455  }
456  // update the contact matrices after all dampings have been added.
457  params.template get<ContactPatterns>().make_matrix();
458  }
459 
460 private:
462  std::vector<size_t> m_icu_indices;
467 };
468 
469 } // namespace mio
470 
471 #endif // MIO_COMPARTMENTS_FEEDBACK_SIMULATION_H
randomly sample dampings for e.g.
Definition: damping_sampling.h:38
A generic feedback simulation extending existing simulations with a feedback mechanism.
Definition: feedback_simulation.h:214
auto & get_result()
Returns the simulation result.
Definition: feedback_simulation.h:266
FP calc_risk_perceived()
Calculates the perceived risk based on ICU occupancy data.
Definition: feedback_simulation.h:312
auto advance(const FP tmax, const FP dt_feedback=1.0)
Advances the simulation until tmax while applying feedback at fixed intervals.
Definition: feedback_simulation.h:249
mio::TimeSeries< FP > m_regional_icu_occupancy
The regional ICU occupancy time series.
Definition: feedback_simulation.h:465
void set_regional_icu_occupancy(const mio::TimeSeries< FP > &icu_regional)
Sets the regional ICU occupancy time series.
Definition: feedback_simulation.h:382
Sim m_simulation
The simulation instance.
Definition: feedback_simulation.h:461
FeedbackSimulationParameters< FP > m_feedback_parameters
The feedback parameters.
Definition: feedback_simulation.h:463
mio::TimeSeries< FP > m_perceived_risk
The perceived risk time series.
Definition: feedback_simulation.h:464
const auto & get_model() const
Definition: feedback_simulation.h:279
std::vector< size_t > m_icu_indices
The ICU compartment indices from the model.
Definition: feedback_simulation.h:462
void set_global_icu_occupancy(const mio::TimeSeries< FP > &icu_global)
Sets the global ICU occupancy time series.
Definition: feedback_simulation.h:392
auto & get_perceived_risk()
Definition: feedback_simulation.h:291
typename Sim::Model Model
Definition: feedback_simulation.h:216
void add_icu_occupancy(FP t)
Adds the current (local) ICU occupancy into the parameter containing all historical ICU occupancy val...
Definition: feedback_simulation.h:362
mio::TimeSeries< FP > m_global_icu_occupancy
The global ICU occupancy time series.
Definition: feedback_simulation.h:466
FeedbackSimulation(Sim &&sim, const std::vector< size_t > &icu_indices)
Constructs the FeedbackSimulation by taking ownership of an existing simulation instance.
Definition: feedback_simulation.h:224
auto & get_parameters()
Returns the local feedback parameters.
Definition: feedback_simulation.h:299
auto & get_model()
Returns the model used in the simulation.
Definition: feedback_simulation.h:274
auto & get_perceived_risk() const
Returns the perceived risk time series.
Definition: feedback_simulation.h:287
void apply_feedback(FP t)
Transforms the perceived risk into a contact reduction factor and applies it to the contact patterns.
Definition: feedback_simulation.h:405
An Index with more than one template parameter combines several Index objects.
Definition: index.h:181
a set of parameters defined at compile time
Definition: parameter_set.h:205
double simulation time.
Definition: damping.h:58
stores vectors of values at time points (or some other abstract variable) the value at each time poin...
Definition: time_series.h:58
Definition: ad.h:57
static min_max_return_type< ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > >::type min(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &a, const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &b)
Definition: ad.hpp:2599
ad::internal::binary_intermediate_aa< AD_TAPE_REAL, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::operations::ad_pow_aa< AD_TAPE_REAL > > pow(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &x1, const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &x2)
Definition: ad.hpp:1610
ad::internal::unary_intermediate< AD_TAPE_REAL, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::operations::ad_log< AD_TAPE_REAL > > log(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &x1)
Definition: ad.hpp:1034
ad::internal::unary_intermediate< AD_TAPE_REAL, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::operations::ad_exp< AD_TAPE_REAL > > exp(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &x1)
Definition: ad.hpp:990
int size(Comm comm)
Return the size of the given communicator.
Definition: miompi.cpp:75
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(LogLevel level, spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:128
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
Definition: io.h:94
The AgeGroup struct is used as a dynamically sized tag for all age dependent categories.
Definition: age_group.h:32
Blending factor for local ICU occupancy.
Definition: feedback_simulation.h:167
static std::string name()
Definition: feedback_simulation.h:173
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:169
FP Type
Definition: feedback_simulation.h:168
Blending factor for regional ICU occupancy.
Definition: feedback_simulation.h:183
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:185
static std::string name()
Definition: feedback_simulation.h:189
FP Type
Definition: feedback_simulation.h:184
Maximum allowed contact reduction factors per location.
Definition: feedback_simulation.h:102
std::vector< FP > Type
Definition: feedback_simulation.h:103
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:104
static std::string name()
Definition: feedback_simulation.h:108
Minimum allowed contact reduction factors per location.
Definition: feedback_simulation.h:118
static std::string name()
Definition: feedback_simulation.h:124
std::vector< FP > Type
Definition: feedback_simulation.h:119
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:120
Number of days in the past considered for the gamma distribution.
Definition: feedback_simulation.h:86
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:88
size_t Type
Definition: feedback_simulation.h:87
static std::string name()
Definition: feedback_simulation.h:92
Scale parameter of the gamma distribution.
Definition: feedback_simulation.h:71
FP Type
Definition: feedback_simulation.h:72
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:73
static std::string name()
Definition: feedback_simulation.h:77
Shape parameter of the gamma distribution.
Definition: feedback_simulation.h:55
static std::string name()
Definition: feedback_simulation.h:61
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:57
FP Type
Definition: feedback_simulation.h:56
Daily local ICU occupancy per age group.
Definition: feedback_simulation.h:39
static std::string name()
Definition: feedback_simulation.h:45
static Type get_default(AgeGroup size)
Definition: feedback_simulation.h:41
mio::TimeSeries< FP > Type
Definition: feedback_simulation.h:40
Nominal ICU capacity.
Definition: feedback_simulation.h:150
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:152
static std::string name()
Definition: feedback_simulation.h:156
FP Type
Definition: feedback_simulation.h:151
Soft-plus curvature parameter for contact adjustment.
Definition: feedback_simulation.h:134
FP Type
Definition: feedback_simulation.h:135
static Type get_default(AgeGroup)
Definition: feedback_simulation.h:136
static std::string name()
Definition: feedback_simulation.h:140