@@ -29,7 +29,7 @@ namespace abm
29
29
TestingCriteria::TestingCriteria (const std::vector<AgeGroup>& ages, const std::vector<InfectionState>& infection_states)
30
30
{
31
31
for (auto age : ages) {
32
- m_ages.insert (static_cast <size_t >(age));
32
+ m_ages.set (static_cast <size_t >(age), true );
33
33
}
34
34
for (auto infection_state : infection_states) {
35
35
m_infection_states.set (static_cast <size_t >(infection_state), true );
@@ -43,13 +43,12 @@ bool TestingCriteria::operator==(const TestingCriteria& other) const
43
43
44
44
void TestingCriteria::add_age_group (const AgeGroup age_group)
45
45
{
46
-
47
- m_ages.insert (static_cast <size_t >(age_group));
46
+ m_ages.set (static_cast <size_t >(age_group), true );
48
47
}
49
48
50
49
void TestingCriteria::remove_age_group (const AgeGroup age_group)
51
50
{
52
- m_ages.erase (static_cast <size_t >(age_group));
51
+ m_ages.set (static_cast <size_t >(age_group), false );
53
52
}
54
53
55
54
void TestingCriteria::add_infection_state (const InfectionState infection_state)
@@ -65,7 +64,7 @@ void TestingCriteria::remove_infection_state(const InfectionState infection_stat
65
64
bool TestingCriteria::evaluate (const Person& p, TimePoint t) const
66
65
{
67
66
// 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 ())] ) &&
69
68
(m_infection_states.none () || m_infection_states[static_cast <size_t >(p.get_infection_state (t))]);
70
69
}
71
70
@@ -104,9 +103,9 @@ void TestingScheme::update_activity_status(TimePoint t)
104
103
bool TestingScheme::run_scheme (Person::RandomNumberGenerator& rng, Person& person, TimePoint t) const
105
104
{
106
105
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 ) {
110
109
return !person.get_tested (rng, t, m_test_type.get_default ());
111
110
}
112
111
}
@@ -116,23 +115,45 @@ bool TestingScheme::run_scheme(Person::RandomNumberGenerator& rng, Person& perso
116
115
117
116
TestingStrategy::TestingStrategy (
118
117
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() )
120
119
{
121
120
}
122
121
123
122
void TestingStrategy::add_testing_scheme (const LocationId& loc_id, const TestingScheme& scheme)
124
123
{
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
+ }
128
138
}
129
139
}
130
140
131
141
void TestingStrategy::remove_testing_scheme (const LocationId& loc_id, const TestingScheme& scheme)
132
142
{
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
+ }
136
157
}
137
158
138
159
void TestingStrategy::update_activity_status (TimePoint t)
@@ -152,16 +173,22 @@ bool TestingStrategy::run_strategy(Person::RandomNumberGenerator& rng, Person& p
152
173
return true ;
153
174
}
154
175
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
+ }
165
192
}
166
193
}
167
194
return true ;
0 commit comments