3434 * 4. Attach the scheme to location types via a TestingStrategy.
3535 * 5. Run the simulation and compare results with the no-testing baseline.
3636 *
37- * Key concept -- Testing in MEmilio ABM:
38- * A TestingCriteria specifies which age groups and infection states trigger
39- * a test. A TestingScheme wraps the criteria together with test parameters
40- * (sensitivity, specificity via TestData), validity period, active time
41- * window, and testing probability. Schemes are added to location types
37+ * Key concept -- Testing in MEmilio-ABM:
38+ * An element of TestingCriteria specifies which age groups and infection states trigger a test.
39+ * A TestingScheme wraps the criteria together with test parameters (sensitivity, specificity via TestData),
40+ * validity period, active time window, and testing probability. Schemes are added to location types
4241 * through the model's TestingStrategy.
4342 */
4443
@@ -62,42 +61,36 @@ const auto age_group_80_plus = mio::AgeGroup(5);
6261
6362// *** Set up a PCR testing strategy and attach it to public locations. ***
6463// This function creates a single TestingScheme that:
64+ // - Is active for the full 30-day simulation window.
6565// - Uses a PCR test (sensitivity/specificity come from TestData defaults).
66- // - Applies to all age groups except school children (5-14 ).
66+ // - Tests are valid for `validity_days`; a negative result exempts retesting for validity_days days (Default: 3 ).
6767// - Targets persons in any infected state (Exposed through Critical).
68- // - Is active for the full 30-day simulation window.
69- // - Tests with 100 % probability upon entry.
70- // - Has a 3-day validity (a negative result exempts retesting for 3 days).
71- void add_npi_testing_strategies_to_world (mio::abm::Model& model,
72- double testing_probability,
73- int validity_days)
68+ // - Applies to all age groups except school children (5-14).
69+ // - Tests with `testing_probability` probability upon entry (Default: 100%).
70+ // - Applies to all public locations (SocialEvent, School, Work, BasicsShop)
71+ void add_npi_testing_strategies_to_world (mio::abm::Model& model, double testing_probability, int validity_days)
7472{
7573 auto start_date_test = mio::abm::TimePoint (mio::abm::days (0 ).seconds ());
7674 auto end_date_test = mio::abm::TimePoint (mio::abm::days (30 ).seconds ());
7775
7876 // Retrieve built-in PCR test parameters (sensitivity, specificity, etc.).
79- auto pcr_test = mio::abm::TestType::PCR;
80- auto pcr_test_parameters =
81- model.parameters .get <mio::abm::TestData>()[pcr_test];
82- auto validity = mio::abm::days (validity_days);
77+ auto pcr_test = mio::abm::TestType::PCR;
78+ auto pcr_test_parameters = model.parameters .get <mio::abm::TestData>()[pcr_test];
79+ auto validity = mio::abm::days (validity_days);
8380
8481 // Infection states that should trigger a test.
8582 auto states_to_test = std::vector<mio::abm::InfectionState>{
86- mio::abm::InfectionState::InfectedSymptoms,
87- mio::abm::InfectionState::Exposed,
88- mio::abm::InfectionState::InfectedNoSymptoms,
89- mio::abm::InfectionState::InfectedSevere,
83+ mio::abm::InfectionState::Exposed, mio::abm::InfectionState::InfectedNoSymptoms,
84+ mio::abm::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedSevere,
9085 mio::abm::InfectionState::InfectedCritical};
9186
9287 // Age groups subject to testing (all except school children 5-14).
93- auto ages_to_test = std::vector<mio::AgeGroup>{
94- age_group_0_to_4, age_group_15_to_34, age_group_35_to_59,
95- age_group_60_to_79, age_group_80_plus};
88+ auto ages_to_test = std::vector<mio::AgeGroup>{age_group_0_to_4, age_group_15_to_34, age_group_35_to_59,
89+ age_group_60_to_79, age_group_80_plus};
9690
9791 auto testing_criteria = mio::abm::TestingCriteria (ages_to_test, states_to_test);
98- auto testing_scheme = mio::abm::TestingScheme (
99- testing_criteria, validity, start_date_test, end_date_test,
100- pcr_test_parameters, testing_probability);
92+ auto testing_scheme = mio::abm::TestingScheme (testing_criteria, validity, start_date_test, end_date_test,
93+ pcr_test_parameters, testing_probability);
10194
10295 // Attach the scheme to all public location types.
10396 model.get_testing_strategy ().add_scheme (mio::abm::LocationType::SocialEvent, testing_scheme);
@@ -112,9 +105,9 @@ int main(int argc, char* argv[])
112105 // testing_prob : probability of testing at location entry (default: 1.0)
113106 // validity_days : days a negative test stays valid (default: 3)
114107 // n_households : number of each household type (default: 125)
115- double arg_testing_prob = (argc > 1 ) ? std::atof (argv[1 ]) : 1.0 ;
116- int arg_validity_days = (argc > 2 ) ? std::atoi (argv[2 ]) : 3 ;
117- int arg_n_households = (argc > 3 ) ? std::atoi (argv[3 ]) : 125 ;
108+ double arg_testing_prob = (argc > 1 ) ? std::atof (argv[1 ]) : 1.0 ;
109+ int arg_validity_days = (argc > 2 ) ? std::atoi (argv[2 ]) : 3 ;
110+ int arg_n_households = (argc > 3 ) ? std::atoi (argv[3 ]) : 125 ;
118111
119112 // Suppress verbose log output; only warnings and errors are shown.
120113 mio::set_log_level (mio::LogLevel::warn);
@@ -133,8 +126,7 @@ int main(int argc, char* argv[])
133126 model.parameters .get <mio::abm::AgeGroupGotoSchool>() = false ;
134127 model.parameters .get <mio::abm::AgeGroupGotoSchool>()[age_group_5_to_14] = true ;
135128
136- model.parameters .get <mio::abm::AgeGroupGotoWork>().set_multiple (
137- {age_group_15_to_34, age_group_35_to_59}, true );
129+ model.parameters .get <mio::abm::AgeGroupGotoWork>().set_multiple ({age_group_15_to_34, age_group_35_to_59}, true );
138130
139131 // *** Define HouseholdMember types (same as Tutorial 1). ***
140132 //
@@ -145,7 +137,7 @@ int main(int argc, char* argv[])
145137
146138 // child: equally likely to be 0-4 or 5-14 years old (weights 1 and 1).
147139 auto child = mio::abm::HouseholdMember (num_age_groups);
148- child.set_age_weight (age_group_0_to_4, 1 );
140+ child.set_age_weight (age_group_0_to_4, 1 );
149141 child.set_age_weight (age_group_5_to_14, 1 );
150142
151143 // parent: equally likely to be 15-34 or 35-59 years old.
@@ -167,7 +159,7 @@ int main(int argc, char* argv[])
167159
168160 // --- Type A: two-person household (1 parent + 1 child) -------------------
169161 auto twoPersonHousehold = mio::abm::Household ();
170- twoPersonHousehold.add_members (child, 1 );
162+ twoPersonHousehold.add_members (child, 1 );
171163 twoPersonHousehold.add_members (parent, 1 );
172164
173165 auto twoPersonGroup = mio::abm::HouseholdGroup ();
@@ -176,7 +168,7 @@ int main(int argc, char* argv[])
176168
177169 // --- Type B: three-person household (2 parents + 1 child) ----------------
178170 auto threePersonHousehold = mio::abm::Household ();
179- threePersonHousehold.add_members (child, 1 );
171+ threePersonHousehold.add_members (child, 1 );
180172 threePersonHousehold.add_members (parent, 2 );
181173
182174 auto threePersonGroup = mio::abm::HouseholdGroup ();
@@ -202,17 +194,16 @@ int main(int argc, char* argv[])
202194 // one. This distributes contacts across venues and makes the testing
203195 // strategy more realistic.
204196
205-
206197 // One hospital and one ICU shared by all persons.
207198 auto hospital = model.add_location (mio::abm::LocationType::Hospital);
208- auto icu = model.add_location (mio::abm::LocationType::ICU);
199+ auto icu = model.add_location (mio::abm::LocationType::ICU);
209200
210201 // 10 social event venues (e.g. a community centre).
211202 auto social_event_venues = std::vector<mio::abm::LocationId>();
212203 for (int i = 0 ; i < 10 ; ++i) {
213204 social_event_venues.push_back (model.add_location (mio::abm::LocationType::SocialEvent));
214205 }
215-
206+
216207 // One supermarket.
217208 auto shop = model.add_location (mio::abm::LocationType::BasicsShop);
218209
@@ -222,7 +213,6 @@ int main(int argc, char* argv[])
222213 // One workplace for all working adults.
223214 auto work = model.add_location (mio::abm::LocationType::Work);
224215
225-
226216 // *** Assign initial infection states. ***
227217 //
228218 // Index | InfectionState | Probability
@@ -242,16 +232,13 @@ int main(int argc, char* argv[])
242232 for (auto & person : model.get_persons ()) {
243233 // Draw an infection state from the distribution above.
244234 mio::abm::InfectionState infection_state = mio::abm::InfectionState (
245- mio::DiscreteDistribution<size_t >::get_instance ()(
246- mio::thread_local_rng (), infection_distribution));
247-
235+ mio::DiscreteDistribution<size_t >::get_instance ()(mio::thread_local_rng (), infection_distribution));
236+
248237 auto rng = mio::abm::PersonalRandomNumberGenerator (person);
249238 if (infection_state != mio::abm::InfectionState::Susceptible) {
250239 // Infect an agent with the drawn state
251- person.add_new_infection (
252- mio::abm::Infection (rng, mio::abm::VirusVariant::Wildtype,
253- person.get_age (), model.parameters ,
254- start_date, infection_state));
240+ person.add_new_infection (mio::abm::Infection (rng, mio::abm::VirusVariant::Wildtype, person.get_age (),
241+ model.parameters , start_date, infection_state));
255242 }
256243 }
257244
@@ -267,13 +254,11 @@ int main(int argc, char* argv[])
267254 // Each person is assigned to one of the 10 social event venues.
268255 model.assign_location (id, social_event_venues[person.get_id ().get () % social_event_venues.size ()]);
269256
270-
271257 // Age-specific locations.
272258 if (person.get_age () == age_group_5_to_14) {
273259 model.assign_location (id, school);
274260 }
275- if (person.get_age () == age_group_15_to_34 ||
276- person.get_age () == age_group_35_to_59) {
261+ if (person.get_age () == age_group_15_to_34 || person.get_age () == age_group_35_to_59) {
277262 model.assign_location (id, work);
278263 }
279264 }
@@ -297,9 +282,7 @@ int main(int argc, char* argv[])
297282 // *** Write results to file. ***
298283 std::ofstream outfile (" abm_tests.txt" );
299284 std::get<0 >(historyTimeSeries.get_log ())
300- .print_table (outfile,
301- {" S" , " E" , " I_NS" , " I_Sy" , " I_Sev" , " I_Crit" , " R" , " D" },
302- 7 , 4 );
285+ .print_table (outfile, {" S" , " E" , " I_NS" , " I_Sy" , " I_Sev" , " I_Crit" , " R" , " D" }, 7 , 4 );
303286 std::cout << " Results written to abm_tests.txt\n " ;
304287
305288 return 0 ;
0 commit comments