Line data Source code
1 : /* 2 : * Copyright (C) 2020-2024 MEmilio 3 : * 4 : * Authors: Elisabeth Kluth, David Kerkmann, Sascha Korf, Martin J. Kuehn, Khoa Nguyen 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_ABM_TESTING_SCHEME_H 21 : #define MIO_ABM_TESTING_SCHEME_H 22 : 23 : #include "abm/config.h" 24 : #include "abm/location_id.h" 25 : #include "abm/location_type.h" 26 : #include "abm/parameters.h" 27 : #include "abm/person.h" 28 : #include "abm/location.h" 29 : #include "abm/time.h" 30 : #include "memilio/io/default_serialize.h" 31 : 32 : #include <bitset> 33 : #include <vector> 34 : 35 : namespace mio 36 : { 37 : namespace abm 38 : { 39 : 40 : /** 41 : * @brief TestingCriteria for TestingScheme. 42 : */ 43 : class TestingCriteria 44 : { 45 : public: 46 : /** 47 : * @brief Create a TestingCriteria where everyone is tested. 48 : */ 49 18 : TestingCriteria() = default; 50 : 51 : /** 52 : * @brief Create a TestingCriteria. 53 : * @param[in] ages Vector of AgeGroup%s that are either allowed or required to be tested. 54 : * @param[in] infection_states Vector of #InfectionState%s that are either allowed or required to be tested. 55 : * An empty vector of ages or none bitset of #InfectionStates% means that no condition on the corresponding property 56 : * is set! 57 : */ 58 : TestingCriteria(const std::vector<AgeGroup>& ages, const std::vector<InfectionState>& infection_states); 59 : 60 : /** 61 : * @brief Compares two TestingCriteria for functional equality. 62 : */ 63 : bool operator==(const TestingCriteria& other) const; 64 : 65 : /** 66 : * @brief Add an AgeGroup to the set of AgeGroup%s that are either allowed or required to be tested. 67 : * @param[in] age_group AgeGroup to be added. 68 : */ 69 : void add_age_group(const AgeGroup age_group); 70 : 71 : /** 72 : * @brief Remove an AgeGroup from the set of AgeGroup%s that are either allowed or required to be tested. 73 : * @param[in] age_group AgeGroup to be removed. 74 : */ 75 : void remove_age_group(const AgeGroup age_group); 76 : 77 : /** 78 : * @brief Add an #InfectionState to the set of #InfectionState%s that are either allowed or required to be tested. 79 : * @param[in] infection_state #InfectionState to be added. 80 : */ 81 : void add_infection_state(const InfectionState infection_state); 82 : 83 : /** 84 : * @brief Remove an #InfectionState from the set of #InfectionState%s that are either allowed or required to be 85 : * tested. 86 : * @param[in] infection_state #InfectionState to be removed. 87 : */ 88 : void remove_infection_state(const InfectionState infection_state); 89 : 90 : /** 91 : * @brief Check if a Person and a Location meet all the required properties to get tested. 92 : * @param[in] p Person to be checked. 93 : * @param[in] t TimePoint when to evaluate the TestingCriteria. 94 : */ 95 : bool evaluate(const Person& p, TimePoint t) const; 96 : 97 18 : auto default_serialize() 98 : { 99 36 : return Members("TestingCriteria").add("ages", m_ages).add("infection_states", m_infection_states); 100 : } 101 : 102 : private: 103 : std::bitset<MAX_NUM_AGE_GROUPS> m_ages; ///< Set of #AgeGroup%s that are either allowed or required to be tested. 104 : std::bitset<(size_t)InfectionState::Count> 105 : m_infection_states; /**< BitSet of #InfectionState%s that are either allowed or required to 106 : be tested.*/ 107 : }; 108 : 109 : /** 110 : * @brief TestingScheme to regular test Person%s. 111 : */ 112 : class TestingScheme 113 : { 114 : public: 115 : /** 116 : * @brief Create a TestingScheme. 117 : * @param[in] testing_criteria Vector of TestingCriteria that are checked for testing. 118 : * @param validity_period The valid TimeSpan of the test. 119 : * @param start_date Starting date of the scheme. 120 : * @param end_date Ending date of the scheme. 121 : * @param test_parameters The parameters of test to be performed. 122 : * @param probability Probability of the test to be performed if a testing rule applies. 123 : */ 124 : TestingScheme(const TestingCriteria& testing_criteria, TimeSpan validity_period, TimePoint start_date, 125 : TimePoint end_date, TestParameters test_parameters, ScalarType probability); 126 : 127 : /** 128 : * @brief Compares two TestingScheme%s for functional equality. 129 : */ 130 : bool operator==(const TestingScheme& other) const; 131 : 132 : /** 133 : * @brief Gets the activity status of the scheme. 134 : * @return Whether the TestingScheme is currently active. 135 : */ 136 : bool is_active() const; 137 : 138 : /** 139 : * @brief Checks if the scheme is active at a given time and updates activity status. 140 : * @param[in] t TimePoint to be updated at. 141 : */ 142 : void update_activity_status(TimePoint t); 143 : 144 : /** 145 : * @brief Runs the TestingScheme and potentially tests a Person. 146 : * @param[inout] rng PersonalRandomNumberGenerator of the Person being tested. 147 : * @param[in] person Person to check. 148 : * @param[in] t TimePoint when to run the scheme. 149 : * @return If the person is allowed to enter the Location by the scheme. 150 : */ 151 : bool run_scheme(PersonalRandomNumberGenerator& rng, Person& person, TimePoint t) const; 152 : 153 : /// This method is used by the default serialization feature. 154 18 : auto default_serialize() 155 : { 156 36 : return Members("TestingScheme") 157 54 : .add("criteria", m_testing_criteria) 158 54 : .add("validity_period", m_validity_period) 159 54 : .add("start_date", m_start_date) 160 54 : .add("end_date", m_end_date) 161 54 : .add("test_params", m_test_parameters) 162 54 : .add("probability", m_probability) 163 54 : .add("is_active", m_is_active); 164 : } 165 : 166 : private: 167 : friend DefaultFactory<TestingScheme>; 168 9 : TestingScheme() = default; 169 : 170 : TestingCriteria m_testing_criteria; ///< TestingCriteria of the scheme. 171 : TimeSpan m_validity_period; ///< The valid TimeSpan of the test. 172 : TimePoint m_start_date; ///< Starting date of the scheme. 173 : TimePoint m_end_date; ///< Ending date of the scheme. 174 : TestParameters m_test_parameters; ///< Parameters of the test. 175 : ScalarType m_probability; ///< Probability of performing the test. 176 : bool m_is_active = false; ///< Whether the scheme is currently active. 177 : }; 178 : 179 : /** 180 : * @brief Set of TestingSchemes that are checked for testing. 181 : */ 182 : class TestingStrategy 183 : { 184 : public: 185 : /** 186 : * @brief List of testing schemes for a given LocationType and LocationId. 187 : * A LocalStrategy with id of value LocationId::invalid_id() is used for all Locations with LocationType type. 188 : */ 189 : struct LocalStrategy { 190 : LocationType type; 191 : LocationId id; 192 : std::vector<TestingScheme> schemes; 193 : 194 : /// This method is used by the default serialization feature. 195 18 : auto default_serialize() 196 : { 197 36 : return Members("LocalStrategy").add("type", type).add("id", id).add("schemes", schemes); 198 : } 199 : }; 200 : 201 : /** 202 : * @brief Create a TestingStrategy. 203 : * @param[in] testing_schemes Vector of TestingSchemes that are checked for testing. 204 : */ 205 217 : TestingStrategy() = default; 206 : explicit TestingStrategy(const std::vector<LocalStrategy>& location_to_schemes_map); 207 : 208 : /** 209 : * @brief Add a TestingScheme to the set of schemes that are checked for testing at a certain Location. 210 : * A TestingScheme with loc_id of value LocationId::invalid_id() is used for all Locations of the given type. 211 : * @param[in] loc_type LocationType key for TestingScheme to be remove. 212 : * @param[in] loc_id LocationId key for TestingScheme to be added. 213 : * @param[in] scheme TestingScheme to be added. 214 : */ 215 : void add_testing_scheme(const LocationType& loc_type, const LocationId& loc_id, const TestingScheme& scheme); 216 : 217 : /** 218 : * @brief Add a TestingScheme to the set of schemes that are checked for testing at a certain LocationType. 219 : * A TestingScheme with loc_id of value LocationId::invalid_id() is used for all Locations of the given type. 220 : * @param[in] loc_type LocationId key for TestingScheme to be added. 221 : * @param[in] scheme TestingScheme to be added. 222 : */ 223 54 : void add_testing_scheme(const LocationType& loc_type, const TestingScheme& scheme) 224 : { 225 54 : add_testing_scheme(loc_type, LocationId::invalid_id(), scheme); 226 54 : } 227 : 228 : /** 229 : * @brief Remove a TestingScheme from the set of schemes that are checked for testing at a certain Location. 230 : * @param[in] loc_type LocationType key for TestingScheme to be remove. 231 : * @param[in] loc_id LocationId key for TestingScheme to be remove. 232 : * @param[in] scheme TestingScheme to be removed. 233 : */ 234 : void remove_testing_scheme(const LocationType& loc_type, const LocationId& loc_id, const TestingScheme& scheme); 235 : 236 : /** 237 : * @brief Remove a TestingScheme from the set of schemes that are checked for testing at a certain Location. 238 : * A TestingScheme with loc_id of value LocationId::invalid_id() is used for all Locations of the given type. 239 : * @param[in] loc_type LocationType key for TestingScheme to be remove. 240 : * @param[in] scheme TestingScheme to be removed. 241 : */ 242 9 : void remove_testing_scheme(const LocationType& loc_type, const TestingScheme& scheme) 243 : { 244 9 : remove_testing_scheme(loc_type, LocationId::invalid_id(), scheme); 245 9 : } 246 : 247 : /** 248 : * @brief Checks if the given TimePoint is within the interval of start and end date of each TestingScheme and then 249 : * changes the activity status for each TestingScheme accordingly. 250 : * @param t TimePoint to check the activity status of each TestingScheme. 251 : */ 252 : void update_activity_status(const TimePoint t); 253 : 254 : /** 255 : * @brief Runs the TestingStrategy and potentially tests a Person. 256 : * @param[inout] rng PersonalRandomNumberGenerator of the Person being tested. 257 : * @param[in] person Person to check. 258 : * @param[in] location Location to check. 259 : * @param[in] t TimePoint when to run the strategy. 260 : * @return If the Person is allowed to enter the Location. 261 : */ 262 : bool run_strategy(PersonalRandomNumberGenerator& rng, Person& person, const Location& location, TimePoint t); 263 : 264 : /// This method is used by the default serialization feature. 265 27 : auto default_serialize() 266 : { 267 54 : return Members("TestingStrategy").add("schemes", m_location_to_schemes_map); 268 : } 269 : 270 : private: 271 : std::vector<LocalStrategy> m_location_to_schemes_map; ///< Set of schemes that are checked for testing. 272 : }; 273 : 274 : } // namespace abm 275 : } // namespace mio 276 : 277 : #endif