@@ -29,7 +29,7 @@ namespace abm
2929TestingCriteria::TestingCriteria (const std::vector<AgeGroup>& ages, const std::vector<InfectionState>& infection_states)
3030{
3131 for (auto age : ages) {
32- m_ages.insert (static_cast <size_t >(age));
32+ m_ages.set (static_cast <size_t >(age), true );
3333 }
3434 for (auto infection_state : infection_states) {
3535 m_infection_states.set (static_cast <size_t >(infection_state), true );
@@ -43,13 +43,12 @@ bool TestingCriteria::operator==(const TestingCriteria& other) const
4343
4444void TestingCriteria::add_age_group (const AgeGroup age_group)
4545{
46-
47- m_ages.insert (static_cast <size_t >(age_group));
46+ m_ages.set (static_cast <size_t >(age_group), true );
4847}
4948
5049void TestingCriteria::remove_age_group (const AgeGroup age_group)
5150{
52- m_ages.erase (static_cast <size_t >(age_group));
51+ m_ages.set (static_cast <size_t >(age_group), false );
5352}
5453
5554void TestingCriteria::add_infection_state (const InfectionState infection_state)
@@ -65,7 +64,7 @@ void TestingCriteria::remove_infection_state(const InfectionState infection_stat
6564bool TestingCriteria::evaluate (const Person& p, TimePoint t) const
6665{
6766 // An empty vector of ages or none bitset of #InfectionStates% means that no condition on the corresponding property is set.
68- return (m_ages.empty () || m_ages. count ( static_cast <size_t >(p.get_age ())) ) &&
67+ return (m_ages.none () || m_ages[ static_cast <size_t >(p.get_age ())] ) &&
6968 (m_infection_states.none () || m_infection_states[static_cast <size_t >(p.get_infection_state (t))]);
7069}
7170
@@ -104,9 +103,9 @@ void TestingScheme::update_activity_status(TimePoint t)
104103bool TestingScheme::run_scheme (Person::RandomNumberGenerator& rng, Person& person, TimePoint t) const
105104{
106105 if (person.get_time_since_negative_test () > m_minimal_time_since_last_test) {
107- double random = UniformDistribution< double >:: get_instance ()(rng);
108- if ( random < m_probability) {
109- if (m_testing_criteria. evaluate (person, t) ) {
106+ if (m_testing_criteria. evaluate (person, t)) {
107+ double random = UniformDistribution< double >:: get_instance ()(rng);
108+ if (random < m_probability ) {
110109 return !person.get_tested (rng, t, m_test_type.get_default ());
111110 }
112111 }
@@ -116,23 +115,45 @@ bool TestingScheme::run_scheme(Person::RandomNumberGenerator& rng, Person& perso
116115
117116TestingStrategy::TestingStrategy (
118117 const std::unordered_map<LocationId, std::vector<TestingScheme>>& location_to_schemes_map)
119- : m_location_to_schemes_map(location_to_schemes_map)
118+ : m_location_to_schemes_map(location_to_schemes_map.begin(), location_to_schemes_map.end() )
120119{
121120}
122121
123122void TestingStrategy::add_testing_scheme (const LocationId& loc_id, const TestingScheme& scheme)
124123{
125- auto & schemes_vector = m_location_to_schemes_map[loc_id];
126- if (std::find (schemes_vector.begin (), schemes_vector.end (), scheme) == schemes_vector.end ()) {
127- schemes_vector.emplace_back (scheme);
124+ auto iter_schemes =
125+ std::find_if (m_location_to_schemes_map.begin (), m_location_to_schemes_map.end (), [loc_id](auto & p) {
126+ return p.first == loc_id;
127+ });
128+ if (iter_schemes == m_location_to_schemes_map.end ()) {
129+ // no schemes for this location yet, add a new list with one scheme
130+ m_location_to_schemes_map.emplace_back (loc_id, std::vector<TestingScheme>(1 , scheme));
131+ }
132+ else {
133+ // add scheme to existing vector if the scheme doesn't exist yet
134+ auto & schemes = iter_schemes->second ;
135+ if (std::find (schemes.begin (), schemes.end (), scheme) == schemes.end ()) {
136+ schemes.push_back (scheme);
137+ }
128138 }
129139}
130140
131141void TestingStrategy::remove_testing_scheme (const LocationId& loc_id, const TestingScheme& scheme)
132142{
133- auto & schemes_vector = m_location_to_schemes_map[loc_id];
134- auto last = std::remove (schemes_vector.begin (), schemes_vector.end (), scheme);
135- schemes_vector.erase (last, schemes_vector.end ());
143+ auto iter_schemes =
144+ std::find_if (m_location_to_schemes_map.begin (), m_location_to_schemes_map.end (), [loc_id](auto & p) {
145+ return p.first == loc_id;
146+ });
147+ if (iter_schemes != m_location_to_schemes_map.end ()) {
148+ // remove the scheme from the list
149+ auto & schemes_vector = iter_schemes->second ;
150+ auto last = std::remove (schemes_vector.begin (), schemes_vector.end (), scheme);
151+ schemes_vector.erase (last, schemes_vector.end ());
152+ // delete the list of schemes for this location if no schemes left
153+ if (schemes_vector.empty ()) {
154+ m_location_to_schemes_map.erase (iter_schemes);
155+ }
156+ }
136157}
137158
138159void TestingStrategy::update_activity_status (TimePoint t)
@@ -152,16 +173,22 @@ bool TestingStrategy::run_strategy(Person::RandomNumberGenerator& rng, Person& p
152173 return true ;
153174 }
154175
155- // Combine two vectors of schemes at corresponding location and location stype
156- std::vector<TestingScheme>* schemes_vector[] = {
157- &m_location_to_schemes_map[LocationId{location.get_index (), location.get_type ()}],
158- &m_location_to_schemes_map[LocationId{INVALID_LOCATION_INDEX, location.get_type ()}]};
159-
160- for (auto vec_ptr : schemes_vector) {
161- if (!std::all_of (vec_ptr->begin (), vec_ptr->end (), [&rng, &person, t](TestingScheme& ts) {
162- return !ts.is_active () || ts.run_scheme (rng, person, t);
163- })) {
164- return false ;
176+ // lookup schemes for this specific location as well as the location type
177+ // lookup in std::vector instead of std::map should be much faster unless for large numbers of schemes
178+ for (auto loc_key : {LocationId{location.get_index (), location.get_type ()},
179+ LocationId{INVALID_LOCATION_INDEX, location.get_type ()}}) {
180+ auto iter_schemes =
181+ std::find_if (m_location_to_schemes_map.begin (), m_location_to_schemes_map.end (), [loc_key](auto & p) {
182+ return p.first == loc_key;
183+ });
184+ if (iter_schemes != m_location_to_schemes_map.end ()) {
185+ // apply all testing schemes that are found
186+ auto & schemes = iter_schemes->second ;
187+ if (!std::all_of (schemes.begin (), schemes.end (), [&rng, &person, t](TestingScheme& ts) {
188+ return !ts.is_active () || ts.run_scheme (rng, person, t);
189+ })) {
190+ return false ;
191+ }
165192 }
166193 }
167194 return true ;
0 commit comments