Skip to content

Commit edb2f59

Browse files
authored
1159 add diffusive abm and smm (#1162)
Co-authored-by: reneSchm <49305466+reneSchm@users.noreply.github.com> add diffusive ABM (model, simulation, parameters and quadwell potential) add SMM (model, simulation, parameters) add tests for both models add examples for both models
1 parent 34a0277 commit edb2f59

27 files changed

+1911
-10
lines changed

cpp/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ option(MEMILIO_ENABLE_PROFILING "Enable runtime performance profiling of memilio
2424

2525
mark_as_advanced(MEMILIO_USE_BUNDLED_SPDLOG MEMILIO_SANITIZE_ADDRESS MEMILIO_SANITIZE_UNDEFINED)
2626

27-
# try to treat AppleClang as Clang, but warn about missing support
28-
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
27+
# try to treat AppleClang as Clang, but warn about missing support
28+
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
2929
message(WARNING "The compiler ID \"AppleClang\" is not supported, trying to compile with \"Clang\" options.")
3030
set(CMAKE_CXX_COMPILER_ID "Clang")
3131
endif()
@@ -82,6 +82,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
8282
message(STATUS "Coverage enabled")
8383
include(CodeCoverage)
8484
append_coverage_compiler_flags()
85+
8586
# In addition to standard flags, disable elision and inlining to prevent e.g. closing brackets being marked as
8687
# uncovered.
8788
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-elide-constructors -fno-default-inline")
@@ -149,6 +150,7 @@ add_subdirectory(memilio)
149150

150151
if(MEMILIO_BUILD_MODELS)
151152
add_subdirectory(models/abm)
153+
add_subdirectory(models/d_abm)
152154
add_subdirectory(models/ode_secir)
153155
add_subdirectory(models/ode_secirts)
154156
add_subdirectory(models/ode_secirvvs)
@@ -163,6 +165,7 @@ if(MEMILIO_BUILD_MODELS)
163165
add_subdirectory(models/sde_sirs)
164166
add_subdirectory(models/sde_seirvv)
165167
add_subdirectory(models/graph_abm)
168+
add_subdirectory(models/smm)
166169
endif()
167170

168171
if(MEMILIO_BUILD_EXAMPLES)

cpp/examples/CMakeLists.txt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ add_executable(graph_abm_example graph_abm.cpp)
132132
target_link_libraries(graph_abm_example PRIVATE memilio graph_abm abm)
133133
target_compile_options(graph_abm_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
134134

135+
add_executable(dabm_example d_abm.cpp)
136+
target_link_libraries(dabm_example PRIVATE memilio d_abm)
137+
target_compile_options(dabm_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
138+
139+
add_executable(smm_example smm.cpp)
140+
target_link_libraries(smm_example PRIVATE memilio smm)
141+
target_compile_options(smm_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
142+
135143
if(MEMILIO_HAS_JSONCPP)
136144
add_executable(ode_secir_read_graph_example ode_secir_read_graph.cpp)
137145
target_link_libraries(ode_secir_read_graph_example PRIVATE memilio ode_secir)
@@ -140,13 +148,13 @@ if(MEMILIO_HAS_JSONCPP)
140148
endif()
141149

142150
if(MEMILIO_HAS_HDF5 AND MEMILIO_HAS_JSONCPP)
143-
add_executable(ode_secir_parameter_study_example ode_secir_parameter_study.cpp)
144-
target_link_libraries(ode_secir_parameter_study_example PRIVATE memilio ode_secir)
145-
target_compile_options(ode_secir_parameter_study_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
151+
add_executable(ode_secir_parameter_study_example ode_secir_parameter_study.cpp)
152+
target_link_libraries(ode_secir_parameter_study_example PRIVATE memilio ode_secir)
153+
target_compile_options(ode_secir_parameter_study_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
146154

147-
add_executable(ode_secir_parameter_study_graph ode_secir_parameter_study_graph.cpp)
148-
target_link_libraries(ode_secir_parameter_study_graph PRIVATE memilio ode_secir)
149-
target_compile_options(ode_secir_parameter_study_graph PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
155+
add_executable(ode_secir_parameter_study_graph ode_secir_parameter_study_graph.cpp)
156+
target_link_libraries(ode_secir_parameter_study_graph PRIVATE memilio ode_secir)
157+
target_compile_options(ode_secir_parameter_study_graph PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
150158
endif()
151159

152160
if(MEMILIO_HAS_JSONCPP)

cpp/examples/d_abm.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (C) 2020-2024 German Aerospace Center (DLR-SC)
3+
*
4+
* Authors: Julia Bicker, René Schmieding
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+
21+
#include "d_abm/quad_well.h"
22+
#include "d_abm/simulation.h"
23+
#include "d_abm/parameters.h"
24+
#include "memilio/utils/random_number_generator.h"
25+
#include "memilio/data/analyze_result.h"
26+
#include "memilio/epidemiology/adoption_rate.h"
27+
#include <vector>
28+
29+
enum class InfectionState
30+
{
31+
S,
32+
E,
33+
C,
34+
I,
35+
R,
36+
D,
37+
Count
38+
39+
};
40+
41+
int main()
42+
{
43+
//Example how to run a simulation of the diffusive ABM using the quadwell potential
44+
using Model = mio::dabm::Model<QuadWellModel<InfectionState>>;
45+
std::vector<Model::Agent> agents(1000);
46+
//Random variables for initialization of agents' position and infection state
47+
auto& pos_rng = mio::UniformDistribution<double>::get_instance();
48+
auto& sta_rng = mio::DiscreteDistribution<size_t>::get_instance();
49+
//Infection state distribution
50+
std::vector<double> pop_dist{0.98, 0.01, 0.005, 0.005, 0., 0.};
51+
for (auto& a : agents) {
52+
//Agents are equally distributed in [-2,2]x[-2,2] at the beginning
53+
a.position =
54+
Eigen::Vector2d{pos_rng(mio::thread_local_rng(), -2., 2.), pos_rng(mio::thread_local_rng(), -2., 2.)};
55+
a.status = static_cast<InfectionState>(sta_rng(mio::thread_local_rng(), pop_dist));
56+
}
57+
58+
//Set adoption rates
59+
std::vector<mio::AdoptionRate<InfectionState>> adoption_rates;
60+
for (size_t region = 0; region < 4; ++region) {
61+
adoption_rates.push_back({InfectionState::S,
62+
InfectionState::E,
63+
mio::regions::Region(region),
64+
0.1,
65+
{{InfectionState::C, 1}, {InfectionState::I, 0.5}}});
66+
adoption_rates.push_back({InfectionState::E, InfectionState::C, mio::regions::Region(region), 1.0 / 5., {}});
67+
adoption_rates.push_back({InfectionState::C, InfectionState::R, mio::regions::Region(region), 0.2 / 3., {}});
68+
adoption_rates.push_back({InfectionState::C, InfectionState::I, mio::regions::Region(region), 0.8 / 3., {}});
69+
adoption_rates.push_back({InfectionState::I, InfectionState::R, mio::regions::Region(region), 0.99 / 5., {}});
70+
adoption_rates.push_back({InfectionState::I, InfectionState::D, mio::regions::Region(region), 0.01 / 5., {}});
71+
}
72+
73+
//Set interaction radius and noise term of the diffusion process
74+
double interaction_radius = 0.5;
75+
double noise = 0.4;
76+
77+
double dt = 0.1;
78+
double tmax = 30.;
79+
80+
Model model(agents, adoption_rates, interaction_radius, noise, {InfectionState::D});
81+
auto sim = mio::dabm::Simulation(model, 0.0, dt);
82+
sim.advance(tmax);
83+
84+
auto interpolated_results = mio::interpolate_simulation_result(sim.get_result());
85+
interpolated_results.print_table({"S", "E", "C", "I", "R", "D "});
86+
}

cpp/examples/smm.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (C) 2020-2024 German Aerospace Center (DLR-SC)
3+
*
4+
* Authors: Julia Bicker, René Schmieding
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+
21+
#include "smm/simulation.h"
22+
#include "smm/parameters.h"
23+
#include "memilio/data/analyze_result.h"
24+
#include "memilio/epidemiology/adoption_rate.h"
25+
26+
enum class InfectionState
27+
{
28+
S,
29+
E,
30+
C,
31+
I,
32+
R,
33+
D,
34+
Count
35+
36+
};
37+
38+
int main()
39+
{
40+
41+
//Example how to run the stochastic metapopulation models with four regions
42+
const size_t num_regions = 4;
43+
using Model = mio::smm::Model<num_regions, InfectionState>;
44+
45+
double numE = 12, numC = 4, numI = 12, numR = 0, numD = 0;
46+
47+
Model model;
48+
//Population are distributed uniformly to the four regions
49+
for (size_t r = 0; r < num_regions; ++r) {
50+
model.populations[{mio::regions::Region(r), InfectionState::S}] =
51+
(1000 - numE - numC - numI - numR - numD) / num_regions;
52+
model.populations[{mio::regions::Region(r), InfectionState::E}] = numE / num_regions;
53+
model.populations[{mio::regions::Region(r), InfectionState::C}] = numC / num_regions;
54+
model.populations[{mio::regions::Region(r), InfectionState::I}] = numI / num_regions;
55+
model.populations[{mio::regions::Region(r), InfectionState::R}] = numR / num_regions;
56+
model.populations[{mio::regions::Region(r), InfectionState::D}] = numD / num_regions;
57+
}
58+
59+
//Set infection state adoption and spatial transition rates
60+
std::vector<mio::AdoptionRate<InfectionState>> adoption_rates;
61+
std::vector<mio::smm::TransitionRate<InfectionState>> transition_rates;
62+
for (size_t r = 0; r < num_regions; ++r) {
63+
adoption_rates.push_back({InfectionState::S,
64+
InfectionState::E,
65+
mio::regions::Region(r),
66+
0.1,
67+
{{InfectionState::C, 1}, {InfectionState::I, 0.5}}});
68+
adoption_rates.push_back({InfectionState::E, InfectionState::C, mio::regions::Region(r), 1.0 / 5., {}});
69+
adoption_rates.push_back({InfectionState::C, InfectionState::R, mio::regions::Region(r), 0.2 / 3., {}});
70+
adoption_rates.push_back({InfectionState::C, InfectionState::I, mio::regions::Region(r), 0.8 / 3., {}});
71+
adoption_rates.push_back({InfectionState::I, InfectionState::R, mio::regions::Region(r), 0.99 / 5., {}});
72+
adoption_rates.push_back({InfectionState::I, InfectionState::D, mio::regions::Region(r), 0.01 / 5., {}});
73+
}
74+
75+
//Agents in infection state D do not transition
76+
for (size_t s = 0; s < static_cast<size_t>(InfectionState::D); ++s) {
77+
for (size_t i = 0; i < num_regions; ++i) {
78+
for (size_t j = 0; j < num_regions; ++j)
79+
if (i != j) {
80+
transition_rates.push_back(
81+
{InfectionState(s), mio::regions::Region(i), mio::regions::Region(j), 0.01});
82+
transition_rates.push_back(
83+
{InfectionState(s), mio::regions::Region(j), mio::regions::Region(i), 0.01});
84+
}
85+
}
86+
}
87+
88+
model.parameters.get<mio::smm::AdoptionRates<InfectionState>>() = adoption_rates;
89+
model.parameters.get<mio::smm::TransitionRates<InfectionState>>() = transition_rates;
90+
91+
double dt = 0.1;
92+
double tmax = 30.;
93+
94+
auto sim = mio::smm::Simulation(model, 0.0, dt);
95+
sim.advance(tmax);
96+
97+
auto interpolated_results = mio::interpolate_simulation_result(sim.get_result());
98+
interpolated_results.print_table({"S", "E", "C", "I", "R", "D "});
99+
}

cpp/memilio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ add_library(memilio
1818
epidemiology/dynamic_npis.cpp
1919
epidemiology/lct_infection_state.h
2020
epidemiology/lct_populations.h
21+
epidemiology/adoption_rate.h
2122
geography/regions.h
2223
geography/regions.cpp
2324
epidemiology/simulation_day.h
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (C) 2020-2025 MEmilio
3+
*
4+
* Authors: René Schmieding, Julia Bicker
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_EPI_ADOPTIONRATE_H
21+
#define MIO_EPI_ADOPTIONRATE_H
22+
23+
#include "memilio/utils/index.h"
24+
#include "memilio/config.h"
25+
#include "memilio/geography/regions.h"
26+
27+
namespace mio
28+
{
29+
30+
/**
31+
* @brief Struct defining an influence for a second-order adoption.
32+
* The population having "status" is multiplied with "factor."
33+
* @tparam Status An infection state enum.
34+
*/
35+
template <class Status>
36+
struct Influence {
37+
Status status;
38+
ScalarType factor;
39+
};
40+
41+
/**
42+
* @brief Struct defining a possible status adoption in a Model based on Poisson Processes.
43+
* The AdoptionRate is considered to be of second-order if there are any "influences".
44+
* In the d_abm and smm simulations, "from" is implicitly an influence, scaled by "factor". This is multiplied by
45+
* the sum over all "influences", which scale their "status" with the respective "factor".
46+
* @tparam Status An infection state enum.
47+
*/
48+
template <class Status>
49+
struct AdoptionRate {
50+
Status from; // i
51+
Status to; // j
52+
mio::regions::Region region; // k
53+
ScalarType factor; // gammahat_{ij}^k
54+
std::vector<Influence<Status>> influences; // influences[tau] = ( Psi_{i,j,tau} , gamma_{i,j,tau} )
55+
};
56+
57+
} // namespace mio
58+
59+
#endif

cpp/memilio/geography/regions.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "memilio/utils/date.h"
2424
#include "memilio/utils/stl_util.h"
2525
#include "memilio/utils/type_safe.h"
26+
#include "memilio/utils/index.h"
2627

2728
#include "boost/filesystem.hpp"
2829

@@ -37,6 +38,14 @@ namespace mio
3738
namespace regions
3839
{
3940

41+
/// @biref Index for enumerating subregions (cities, counties, etc.) of the modelled area.
42+
struct Region : public mio::Index<Region> {
43+
Region(const size_t num_regions)
44+
: mio::Index<Region>(num_regions)
45+
{
46+
}
47+
};
48+
4049
/**
4150
* Id of a state.
4251
* For Germany the Ids are:

cpp/memilio/utils/random_number_generator.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,13 @@ using DiscreteDistribution = DistributionAdapter<DiscreteDistributionInPlace<Int
662662
template <class Real>
663663
using ExponentialDistribution = DistributionAdapter<std::exponential_distribution<Real>>;
664664

665+
/**
666+
* adapted std::normal_distribution.
667+
* @see DistributionAdapter
668+
*/
669+
template <class Real>
670+
using NormalDistribution = DistributionAdapter<std::normal_distribution<Real>>;
671+
665672
/**
666673
* adapted std::uniform_int_distribution.
667674
* @see DistributionAdapter

cpp/models/README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
11
# MEmilio Models #
22

3-
Contains different concrete models that are built using the MEmilio C++ library. See the corresponding directory for details about each model.
3+
Contains different concrete models that are built using the MEmilio C++ library. Some models contain a spatial resolution and some do not contain spatial resolution, hence cannot capture spatially heterogenous dynamics.
4+
The models with spatial resolution are:
5+
- abm
6+
- d_abm
7+
8+
The models without spatial resolution are:
9+
- ode_*
10+
- ide_*
11+
- lct_*
12+
- glct_*
13+
- sde_*
14+
15+
See the corresponding directory for details about each model.

cpp/models/d_abm/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_library(d_abm
2+
model.h
3+
model.cpp
4+
simulation.h
5+
simulation.cpp
6+
parameters.h
7+
)
8+
target_link_libraries(d_abm PUBLIC memilio)
9+
target_include_directories(d_abm PUBLIC
10+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
11+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
12+
)
13+
target_compile_options(d_abm PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})

0 commit comments

Comments
 (0)