Skip to content

Commit 9450046

Browse files
committed
added check after initialization
1 parent 7205b9d commit 9450046

File tree

4 files changed

+59
-47
lines changed

4 files changed

+59
-47
lines changed

cpp/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The MEmilio C++ library contains the implementation of the epidemiological model
44

55
Directory structure:
66
- memilio: framework for developing epidemiological models with, e.g., interregional mobility implementations, nonpharmaceutical interventions (NPIs), and mathematical, programming, and IO utilities.
7-
- models: implementation of concrete models (ODE and ABM)
7+
- models: implementation of concrete models (ODE, IDE, LCT and ABM)
88
- simulations: simulation applications that were used to generate the scenarios and data for publications
99
- examples: small applications that help with using the framework and models
1010
- tests: unit tests for framework and models.

cpp/models/ide_secir/model.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,19 @@ void Model::initialize(ScalarType dt)
130130
"larger 0.");
131131
}
132132
}
133+
134+
// Verify that the initialization produces an appropriate result.
135+
// Another check would be if the sum of the compartments is equal to N, but in all initialization methods one of the compartments is initialized via N - the others.
136+
// This also means that if a compartment is greater than N, we will always have one or more compartments less than zero.
137+
// Check if all compartments are non negative.
138+
for (int i = 0; i < (int)InfectionState::Count; i++) {
139+
if (m_populations[0][i] < 0) {
140+
m_initialization_method = -2;
141+
log_error("Initialization failed. One or more initial values for populations are less than zero. It may "
142+
"help to use a different method for initialization.");
143+
}
144+
}
145+
133146
// Compute m_forceofinfection at time 0 needed for further simulation.
134147
update_forceofinfection(dt);
135148
}

cpp/models/ide_secir/model.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,11 @@ class Model
5959
bool check_constraints(ScalarType dt) const
6060
{
6161
if (!((int)m_transitions.get_num_elements() == (int)InfectionTransition::Count)) {
62-
log_error(
63-
"Initialization failed. Number of elements in transition vector does not match the required number.");
62+
log_error("A variable given for model construction is not valid. Number of elements in transition vector "
63+
"does not match the required number.");
6464
return true;
6565
}
6666

67-
for (int i = 0; i < (int)InfectionState::Count; i++) {
68-
if (m_populations[0][i] < 0) {
69-
log_error("Initialization failed. Initial values for populations are less than zero.");
70-
return true;
71-
}
72-
}
73-
7467
ScalarType support_max = std::max(
7568
{parameters.get<TransitionDistributions>()[(int)InfectionTransition::ExposedToInfectedNoSymptoms]
7669
.get_support_max(dt, m_tol),
@@ -213,9 +206,10 @@ class Model
213206
* @returns 0 if the initialization method has not yet been selected,
214207
* 1 if the method using the total number of confirmed cases at time 0 is used,
215208
* 2 if the initialization is calculated using a prior set value for S,
216-
* 3 if the initialization is calculated using a prior set value for R
217-
* 4 if the force of infection method is used,and
218-
* -1 if the initialization was not possible using any of the methods.
209+
* 3 if the initialization is calculated using a prior set value for R,
210+
* 4 if the force of infection method is used,
211+
* -1 if the initialization was not possible using any of the methods and
212+
* -2 if the initialization was possible using one of the provided methods but the result is not appropriate.
219213
*/
220214
int get_initialization_method()
221215
{

cpp/tests/test_ide_secir.cpp

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -289,50 +289,50 @@ TEST(IdeSecir, checkInitializations)
289289
contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 0));
290290
parameters.get<mio::isecir::ContactPatterns>() = mio::UncertainContactMatrix(contact_matrix);
291291

292-
mio::TimeSeries<ScalarType> init_copy3(init);
293-
mio::isecir::Model model3(std::move(init_copy3), N, deaths, 0, std::move(parameters));
292+
mio::TimeSeries<ScalarType> init_copy2(init);
293+
mio::isecir::Model model2(std::move(init_copy2), N, deaths, 0, std::move(parameters));
294294

295-
model3.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 5000;
296-
model3.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 0;
295+
model2.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 5000;
296+
model2.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 0;
297297

298298
// Carry out simulation.
299-
mio::isecir::Simulation sim3(model3, 0, dt);
300-
sim3.advance(tmax);
299+
mio::isecir::Simulation sim2(model2, 0, dt);
300+
sim2.advance(tmax);
301301

302302
// Verify that the expected initialization method was used.
303-
EXPECT_EQ(2, sim3.get_model().get_initialization_method());
303+
EXPECT_EQ(2, sim2.get_model().get_initialization_method());
304304

305305
// --- Case with R.
306-
mio::TimeSeries<ScalarType> init_copy4(init);
307-
mio::isecir::Model model4(std::move(init_copy4), N, deaths, 0, std::move(parameters));
306+
mio::TimeSeries<ScalarType> init_copy3(init);
307+
mio::isecir::Model model3(std::move(init_copy3), N, deaths, 0, std::move(parameters));
308308

309-
model4.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 0;
310-
model4.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 1000;
309+
model3.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 0;
310+
model3.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 1000;
311311

312312
// Carry out simulation.
313-
mio::isecir::Simulation sim4(model4, 0, dt);
314-
sim4.advance(tmax);
313+
mio::isecir::Simulation sim3(model3, 0, dt);
314+
sim3.advance(tmax);
315315

316316
// Verify that the expected initialization method was used.
317-
EXPECT_EQ(3, sim4.get_model().get_initialization_method());
317+
EXPECT_EQ(3, sim3.get_model().get_initialization_method());
318318

319319
// --- Case with forceofinfection.
320-
mio::TimeSeries<ScalarType> init_copy2(init);
321-
mio::isecir::Model model2(std::move(init_copy2), N, deaths, 0);
320+
mio::TimeSeries<ScalarType> init_copy4(init);
321+
mio::isecir::Model model4(std::move(init_copy4), N, deaths, 0);
322322

323323
// Carry out simulation.
324-
mio::isecir::Simulation sim2(model2, 0, dt);
325-
sim2.advance(tmax);
324+
mio::isecir::Simulation sim4(model4, 0, dt);
325+
sim4.advance(tmax);
326326

327327
// Verify that the expected initialization method was used.
328-
EXPECT_EQ(4, sim2.get_model().get_initialization_method());
328+
EXPECT_EQ(4, sim4.get_model().get_initialization_method());
329329

330330
// --- Case without fitting initialization method.
331-
// Deactivate temporarily log output for next test. Error is expected here.
331+
// Deactivate temporarily log output for next tests. Errors are expected here.
332332
mio::set_log_level(mio::LogLevel::off);
333333

334-
// Here we do not need a copy of init as this is the last use of the vector. We can apply move directly.
335-
mio::isecir::Model model5(std::move(init), N, deaths, 0, std::move(parameters));
334+
mio::TimeSeries<ScalarType> init_copy5(init);
335+
mio::isecir::Model model5(std::move(init_copy5), N, deaths, 0, std::move(parameters));
336336

337337
model5.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 0;
338338
model5.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 0;
@@ -344,6 +344,22 @@ TEST(IdeSecir, checkInitializations)
344344
// Verify that initialization was not possible with one of the models methods.
345345
EXPECT_EQ(-1, sim5.get_model().get_initialization_method());
346346

347+
// --- Test with negative number of deaths.
348+
deaths = -10;
349+
350+
// Here we do not need a copy of init as this is the last use of the vector. We can apply move directly.
351+
mio::isecir::Model model6(std::move(init), N, deaths, 0, std::move(parameters));
352+
353+
model6.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 0;
354+
model6.m_populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 0;
355+
356+
// Carry out simulation.
357+
mio::isecir::Simulation sim6(model6, 0, dt);
358+
sim6.advance(tmax);
359+
360+
// Verify that initialization was possible but the result is not appropriate.
361+
EXPECT_EQ(-2, sim6.get_model().get_initialization_method());
362+
347363
// Reactive log output.
348364
mio::set_log_level(mio::LogLevel::warn);
349365
}
@@ -383,8 +399,7 @@ TEST(IdeSecir, testModelConstraints)
383399
auto constraint_check = model_wrong_size.check_constraints(dt);
384400
EXPECT_TRUE(constraint_check);
385401

386-
// --- Test with negative number of deaths.
387-
deaths = -10;
402+
// --- Test with too few time points.
388403
// Create TimeSeries with num_transitions elements.
389404
mio::TimeSeries<ScalarType> init(num_transitions);
390405
// Add time points for initialization of transitions.
@@ -395,16 +410,6 @@ TEST(IdeSecir, testModelConstraints)
395410
init.add_time_point(init.get_last_time() + dt, vec_init);
396411
}
397412

398-
// Initialize a model.
399-
mio::TimeSeries<ScalarType> init_copy(init);
400-
mio::isecir::Model model_negative_deaths(std::move(init_copy), N, deaths);
401-
402-
// Return true for negative entry in m_populations.
403-
constraint_check = model_negative_deaths.check_constraints(dt);
404-
EXPECT_TRUE(constraint_check);
405-
406-
// --- Test with too few time points.
407-
deaths = 10;
408413
// Initialize a model.
409414
mio::isecir::Model model_few_timepoints(std::move(init), N, deaths);
410415

0 commit comments

Comments
 (0)