Skip to content

Commit c82e29a

Browse files
kilianvolmerreneSchmjubicker
authored
1341 SMM Model with generic indices
Co-authored-by: reneSchm <[email protected]> Co-authored-by: jubicker <[email protected]>
1 parent 7064838 commit c82e29a

12 files changed

Lines changed: 492 additions & 212 deletions

File tree

cpp/examples/smm.cpp

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Copyright (C) 2020-2026 MEmilio
33
*
4-
* Authors: Julia Bicker, René Schmieding
4+
* Authors: Julia Bicker, René Schmieding, Kilian Volmer
55
*
66
* Contact: Martin J. Kuehn <[email protected]>
77
*
@@ -18,11 +18,12 @@
1818
* limitations under the License.
1919
*/
2020

21+
#include "memilio/config.h"
22+
#include "memilio/epidemiology/age_group.h"
2123
#include "smm/simulation.h"
2224
#include "smm/model.h"
2325
#include "smm/parameters.h"
2426
#include "memilio/data/analyze_result.h"
25-
#include "memilio/epidemiology/adoption_rate.h"
2627

2728
enum class InfectionState
2829
{
@@ -33,61 +34,75 @@ enum class InfectionState
3334
R,
3435
D,
3536
Count
37+
};
3638

39+
struct Species : public mio::Index<Species> {
40+
Species(size_t val)
41+
: Index<Species>(val)
42+
{
43+
}
3744
};
3845

3946
int main()
4047
{
48+
using Age = mio::AgeGroup;
49+
using Status = mio::Index<InfectionState, Age, Species>;
50+
using mio::regions::Region;
51+
using enum InfectionState;
4152

42-
//Example how to run the stochastic metapopulation models with four regions
43-
const size_t num_regions = 4;
44-
using Model = mio::smm::Model<ScalarType, num_regions, InfectionState>;
53+
/* Example how to run the stochastic metapopulation models with four regions. Within each region we differentiate by
54+
age groups, species and infection states. The infection states are S, E, C, I, R, D. For the number of age groups
55+
and species we choose: */
56+
const size_t num_regions = 4;
57+
const size_t num_age_groups = 1;
58+
const size_t num_species = 1;
59+
using Model = mio::smm::Model<ScalarType, InfectionState, Status, Region>;
4560

4661
ScalarType numE = 12, numC = 4, numI = 12, numR = 0, numD = 0;
4762

48-
Model model;
63+
Model model(Status{Count, Age(num_age_groups), Species(num_species)}, Region(num_regions));
4964
//Population are distributed uniformly to the four regions
5065
for (size_t r = 0; r < num_regions; ++r) {
51-
model.populations[{mio::regions::Region(r), InfectionState::S}] =
52-
(1000 - numE - numC - numI - numR - numD) / num_regions;
53-
model.populations[{mio::regions::Region(r), InfectionState::E}] = numE / num_regions;
54-
model.populations[{mio::regions::Region(r), InfectionState::C}] = numC / num_regions;
55-
model.populations[{mio::regions::Region(r), InfectionState::I}] = numI / num_regions;
56-
model.populations[{mio::regions::Region(r), InfectionState::R}] = numR / num_regions;
57-
model.populations[{mio::regions::Region(r), InfectionState::D}] = numD / num_regions;
66+
model.populations[{Region(r), S, Age(0), Species(0)}] = (1000 - numE - numC - numI - numR - numD) / num_regions;
67+
model.populations[{Region(r), E, Age(0), Species(0)}] = numE / num_regions;
68+
model.populations[{Region(r), C, Age(0), Species(0)}] = numC / num_regions;
69+
model.populations[{Region(r), I, Age(0), Species(0)}] = numI / num_regions;
70+
model.populations[{Region(r), R, Age(0), Species(0)}] = numR / num_regions;
71+
model.populations[{Region(r), D, Age(0), Species(0)}] = numD / num_regions;
5872
}
5973

60-
//Set infection state adoption and spatial transition rates
61-
std::vector<mio::AdoptionRate<ScalarType, InfectionState>> adoption_rates;
62-
std::vector<mio::smm::TransitionRate<ScalarType, InfectionState>> transition_rates;
74+
using AR = mio::smm::AdoptionRates<ScalarType, Status, Region>;
75+
using TR = mio::smm::TransitionRates<ScalarType, Status, Region>;
76+
77+
//Set infection state adoption rates. Adoptions only happen within a region.
78+
AR::Type adoption_rates;
6379
for (size_t r = 0; r < num_regions; ++r) {
64-
adoption_rates.push_back({InfectionState::S,
65-
InfectionState::E,
66-
mio::regions::Region(r),
80+
adoption_rates.push_back({{S, Age(0), Species(0)},
81+
{E, Age(0), Species(0)},
82+
Region(r),
6783
0.1,
68-
{{InfectionState::C, 1}, {InfectionState::I, 0.5}}});
69-
adoption_rates.push_back({InfectionState::E, InfectionState::C, mio::regions::Region(r), 1.0 / 5., {}});
70-
adoption_rates.push_back({InfectionState::C, InfectionState::R, mio::regions::Region(r), 0.2 / 3., {}});
71-
adoption_rates.push_back({InfectionState::C, InfectionState::I, mio::regions::Region(r), 0.8 / 3., {}});
72-
adoption_rates.push_back({InfectionState::I, InfectionState::R, mio::regions::Region(r), 0.99 / 5., {}});
73-
adoption_rates.push_back({InfectionState::I, InfectionState::D, mio::regions::Region(r), 0.01 / 5., {}});
84+
{{{C, Age(0), Species(0)}, 1}, {{I, Age(0), Species(0)}, 0.5}}});
85+
adoption_rates.push_back({{C, Age(0), Species(0)}, {R, Age(0), Species(0)}, Region(r), 0.2 / 3., {}});
86+
adoption_rates.push_back({{E, Age(0), Species(0)}, {C, Age(0), Species(0)}, Region(r), 1.0 / 5., {}});
87+
adoption_rates.push_back({{C, Age(0), Species(0)}, {I, Age(0), Species(0)}, Region(r), 0.8 / 3., {}});
88+
adoption_rates.push_back({{I, Age(0), Species(0)}, {R, Age(0), Species(0)}, Region(r), 0.99 / 5., {}});
89+
adoption_rates.push_back({{I, Age(0), Species(0)}, {D, Age(0), Species(0)}, Region(r), 0.01 / 5., {}});
7490
}
7591

76-
//Agents in infection state D do not transition
77-
for (size_t s = 0; s < static_cast<size_t>(InfectionState::D); ++s) {
92+
//Set transition rates between regions. Agents in infection state D do not transition.
93+
TR::Type transition_rates;
94+
for (size_t s = 0; s < static_cast<size_t>(D); ++s) {
7895
for (size_t i = 0; i < num_regions; ++i) {
7996
for (size_t j = 0; j < num_regions; ++j)
8097
if (i != j) {
81-
transition_rates.push_back(
82-
{InfectionState(s), mio::regions::Region(i), mio::regions::Region(j), 0.01});
83-
transition_rates.push_back(
84-
{InfectionState(s), mio::regions::Region(j), mio::regions::Region(i), 0.01});
98+
transition_rates.push_back({{InfectionState(s), Age(0), Species(0)}, Region(i), Region(j), 0.01});
99+
transition_rates.push_back({{InfectionState(s), Age(0), Species(0)}, Region(j), Region(i), 0.01});
85100
}
86101
}
87102
}
88103

89-
model.parameters.get<mio::smm::AdoptionRates<ScalarType, InfectionState>>() = adoption_rates;
90-
model.parameters.get<mio::smm::TransitionRates<ScalarType, InfectionState>>() = transition_rates;
104+
model.parameters.get<AR>() = adoption_rates;
105+
model.parameters.get<TR>() = transition_rates;
91106

92107
ScalarType dt = 0.1;
93108
ScalarType tmax = 30.0;

cpp/memilio/epidemiology/adoption_rate.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Copyright (C) 2020-2026 MEmilio
33
*
4-
* Authors: René Schmieding, Julia Bicker
4+
* Authors: René Schmieding, Julia Bicker, Kilian Volmer
55
*
66
* Contact: Martin J. Kuehn <[email protected]>
77
*
@@ -20,17 +20,16 @@
2020
#ifndef MIO_EPI_ADOPTIONRATE_H
2121
#define MIO_EPI_ADOPTIONRATE_H
2222

23-
#include "memilio/utils/index.h"
24-
#include "memilio/config.h"
2523
#include "memilio/geography/regions.h"
24+
#include <vector>
2625

2726
namespace mio
2827
{
2928

3029
/**
3130
* @brief Struct defining an influence for a second-order adoption.
3231
* The population having "status" is multiplied with "factor."
33-
* @tparam Status An infection state enum.
32+
* @tparam Status An infection state enum or MultiIndex.
3433
*/
3534
template <typename FP, class Status>
3635
struct Influence {
@@ -43,13 +42,14 @@ struct Influence {
4342
* The AdoptionRate is considered to be of second-order if there are any "influences".
4443
* In the d_abm and smm simulations, "from" is implicitly an influence, scaled by "factor". This is multiplied by
4544
* the sum over all "influences", which scale their "status" with the respective "factor".
46-
* @tparam Status An infection state enum.
45+
* @tparam Status An infection state enum or MultiIndex.
46+
* @tparam Region A MultiIndex.
4747
*/
48-
template <typename FP, class Status>
48+
template <typename FP, class Status, class Region = mio::regions::Region>
4949
struct AdoptionRate {
5050
Status from; // i
5151
Status to; // j
52-
mio::regions::Region region; // k
52+
Region region; // k
5353
FP factor; // gammahat_{ij}^k
5454
std::vector<Influence<FP, Status>> influences; // influences[tau] = ( Psi_{i,j,tau} , gamma_{i,j,tau} )
5555
};

cpp/memilio/epidemiology/populations.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,18 @@ class Populations : public CustomIndexArray<UncertainValue<FP>, Categories...>
307307
}
308308
};
309309

310+
/**
311+
* @brief Population template specialization, forwarding categories from a MultiIndex to the Population.
312+
*
313+
* @tparam FP A floating point type, e.g., double.
314+
* @tparam Categories Index categories.
315+
*/
316+
template <typename FP, class... Categories>
317+
class Populations<FP, Index<Categories...>> : public Populations<FP, Categories...>
318+
{
319+
using Populations<FP, Categories...>::Populations;
320+
};
321+
310322
} // namespace mio
311323

312324
#endif // MIO_EPI_POPULATIONS_H

0 commit comments

Comments
 (0)