Line data Source code
1 : /*
2 : * Copyright (C) 2020-2024 MEmilio
3 : *
4 : * Authors: Daniel Abele, Elisabeth Kluth, David Kerkmann, 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_PERSON_H
21 : #define MIO_ABM_PERSON_H
22 :
23 : #include "abm/infection.h"
24 : #include "abm/infection_state.h"
25 : #include "abm/location_id.h"
26 : #include "abm/location.h"
27 : #include "abm/location_type.h"
28 : #include "abm/parameters.h"
29 : #include "abm/person_id.h"
30 : #include "abm/personal_rng.h"
31 : #include "memilio/io/default_serialize.h"
32 : #include "abm/time.h"
33 : #include "abm/test_type.h"
34 : #include "abm/protection_event.h"
35 : #include "abm/intervention_type.h"
36 : #include "abm/mask.h"
37 : #include "abm/mobility_data.h"
38 : #include "memilio/epidemiology/age_group.h"
39 : #include "memilio/utils/random_number_generator.h"
40 :
41 : namespace mio
42 : {
43 : namespace abm
44 : {
45 :
46 : static constexpr uint32_t INVALID_PERSON_ID = std::numeric_limits<uint32_t>::max();
47 :
48 : /**
49 : * @brief Agents in the simulated Model that can carry and spread the Infection.
50 : */
51 : class Person
52 : {
53 : public:
54 : /**
55 : * @brief Create a Person.
56 : * @param[in, out] rng RandomNumberGenerator.
57 : * @param[in, out] location Initial Location of the Person.
58 : * @param[in] age The AgeGroup of the Person.
59 : * @param[in] person_id Index of the Person.
60 : */
61 : explicit Person(mio::RandomNumberGenerator& rng, LocationType location_type, LocationId location_id, AgeGroup age,
62 : PersonId person_id = PersonId::invalid_id());
63 :
64 : explicit Person(const Person& other, PersonId id);
65 :
66 : /**
67 : * @brief Compare two Person%s.
68 : */
69 : bool operator==(const Person& other) const
70 : {
71 : return (m_person_id == other.m_person_id);
72 : }
73 :
74 : /**
75 : * @brief Get the latest #Infection of the Person.
76 : * @return The latest #Infection of the Person.
77 : */
78 : Infection& get_infection();
79 : const Infection& get_infection() const;
80 :
81 : /**
82 : * @brief Get all vaccinations of the Person.
83 : * @return A vector with all vaccinations.
84 : * @{
85 : */
86 : std::vector<ProtectionEvent>& get_vaccinations()
87 : {
88 : return m_vaccinations;
89 : }
90 :
91 : const std::vector<ProtectionEvent>& get_vaccinations() const
92 : {
93 : return m_vaccinations;
94 : }
95 : /** @} */
96 :
97 : /**
98 : * @brief Returns if the Person is infected at the TimePoint.
99 : * @param[in] t TimePoint of querry. Usually the current time of the Simulation.
100 : * @return True if the Person is infected at the TimePoint.
101 : */
102 : bool is_infected(TimePoint t) const;
103 :
104 : /**
105 : * @brief Get the InfectionState of the Person at a specific TimePoint.
106 : * @param[in] t TimePoint of querry. Usually the current time of the Simulation.
107 : * @return The InfectionState of the latest Infection at time t.
108 : */
109 : InfectionState get_infection_state(TimePoint t) const;
110 :
111 : /**
112 : * @brief Adds a new Infection to the list of Infection%s.
113 : * @param[in] inf The new Infection.
114 : */
115 : void add_new_infection(Infection&& inf);
116 :
117 : /**
118 : * @brief Get the AgeGroup of this Person.
119 : * @return AgeGroup of the Person.
120 : */
121 10035 : AgeGroup get_age() const
122 : {
123 10035 : return m_age;
124 : }
125 :
126 : /**
127 : * @brief Get the current Location of the Person.
128 : * @return Current Location of the Person.
129 : */
130 : LocationId get_location() const;
131 :
132 10701 : LocationType get_location_type() const
133 : {
134 10701 : return m_location_type;
135 : }
136 :
137 : /**
138 : * @brief Change the location of the person.
139 : * @param[in] id The new location.
140 : */
141 : void set_location(LocationType type, LocationId id);
142 :
143 : /**
144 : * @brief Get the time the Person has been at its current Location.
145 : * @return TimeSpan the Person has been at the Location.
146 : */
147 81 : TimeSpan get_time_at_location() const
148 : {
149 81 : return m_time_at_location;
150 : }
151 :
152 : /**
153 : * @brief Add to the time the Person has been at its current Location.
154 : * @param[in] dt TimeSpan the Person has spent at the Location.
155 : */
156 2844 : void add_time_at_location(const TimeSpan dt)
157 : {
158 2844 : m_time_at_location += dt;
159 2844 : }
160 :
161 : /**
162 : * @brief Set an assigned Location of the Person.
163 : *
164 : * Important: Setting incorrect values will cause issues during simulation. It is preferable to use
165 : * Model::assign_location with a valid LocationId, obtained e.g. through Model::add_location.
166 : *
167 : * The assigned Location is saved by the index of its LocationId. Assume that a Person has at most one assigned
168 : * Location of a certain #LocationType.
169 : * @param[in] type The LocationType of the Location.
170 : * @param[in] id The LocationId of the Location.
171 : */
172 : void set_assigned_location(LocationType type, LocationId id);
173 :
174 : /**
175 : * @brief Returns the index of an assigned Location of the Person.
176 : * Assume that a Person has at most one assigned Location of a certain #LocationType.
177 : * @param[in] type #LocationType of the assigned Location.
178 : * @return The index in the LocationId of the assigned Location.
179 : */
180 : LocationId get_assigned_location(LocationType type) const;
181 :
182 : /**
183 : * @brief Get the assigned Location%s of the Person.
184 : * @return A vector with the indices of the assigned Location%s of the Person.
185 : */
186 : const std::vector<LocationId>& get_assigned_locations() const
187 : {
188 : return m_assigned_locations;
189 : }
190 :
191 : /**
192 : * @brief Draw if the Person goes to work or is in home office during lockdown at a specific TimePoint.
193 : * Every Person has a random number. Depending on this number and the time, the Person works from home in case of a
194 : * lockdown.
195 : * @param[in] t The TimePoint of interest. Usually the current time of the Simulation.
196 : * @param[in] params Parameters that describe the mobility between Location%s.
197 : * @return True the Person works from home.
198 : */
199 : bool goes_to_work(TimePoint t, const Parameters& params) const;
200 :
201 : /**
202 : * @brief Draw at what time the Person goes to work.
203 : * Every Person has a random number to determine what time to go to work.
204 : * Depending on this number Person decides what time has to go to work.
205 : * @param[in] params Parameters that describe the mobility between Location%s.
206 : * @return The time of going to work.
207 : */
208 : TimeSpan get_go_to_work_time(const Parameters& params) const;
209 :
210 : /**
211 : * @brief Draw if the Person goes to school or stays at home during lockdown.
212 : * Every Person has a random number that determines if they go to school in case of a lockdown.
213 : * @param[in] t The TimePoint of interest. Usually the current time of the Simulation.
214 : * @param[in] params Parameters that describe the mobility between Location%s.
215 : * @return True if the Person goes to school.
216 : */
217 : bool goes_to_school(TimePoint t, const Parameters& params) const;
218 :
219 : /**
220 : * @brief Draw at what time the Person goes to work.
221 : * Every Person has a random number to determine what time to go to school.
222 : * Depending on this number Person decides what time has to go to school.
223 : * @param[in] params Parameters that describe the mobility between Location%s.
224 : * @return The time of going to school.
225 : */
226 : TimeSpan get_go_to_school_time(const Parameters& params) const;
227 :
228 : /**
229 : * @brief Answers the question if a Person is currently in quarantine.
230 : * If a Person is in quarantine this Person cannot change to Location%s other than Home or the Hospital.
231 : * @param[in] t The TimePoint of interest. Usually the current time of the Simulation.
232 : * @param[in] params Parameter that includes the length of a quarantine.
233 : * @return True if the Person is in quarantine.
234 : */
235 1647 : bool is_in_quarantine(TimePoint t, const Parameters& params) const
236 : {
237 1647 : return t < m_home_isolation_start + params.get<mio::abm::QuarantineDuration>();
238 : }
239 :
240 : /**
241 : * @brief Removes the quarantine status of the Person.
242 : */
243 : void remove_quarantine();
244 :
245 : /**
246 : * @brief Simulates a viral test and returns the test result of the Person.
247 : * If the test is positive, the Person has to quarantine.
248 : * If the test is negative, quarantine ends.
249 : * @param[inout] rng RandomNumberGenerator of the Person.
250 : * @param[in] t TimePoint of the test.
251 : * @param[in] params Sensitivity and specificity of the test method.
252 : * @return True if the test result of the Person is positive.
253 : */
254 : bool get_tested(PersonalRandomNumberGenerator& rng, TimePoint t, const TestParameters& params);
255 :
256 : /**
257 : * @brief Get the PersonId of the Person.
258 : * The PersonId should correspond to the index in m_persons in the Model.
259 : * @return The PersonId.
260 : */
261 : PersonId get_id() const;
262 :
263 : /**
264 : * @brief Get index of Cell%s of the Person.
265 : * @return A vector of all Cell indices the Person visits at the current Location.
266 : */
267 : std::vector<uint32_t>& get_cells();
268 :
269 : const std::vector<uint32_t>& get_cells() const;
270 :
271 : /**
272 : * @brief Get the current Mask of the Person.
273 : * @return Reference to the Mask object of the Person.
274 : */
275 90 : Mask& get_mask()
276 : {
277 90 : return m_mask;
278 : }
279 :
280 : const Mask& get_mask() const
281 : {
282 : return m_mask;
283 : }
284 :
285 : /**
286 : * @brief Get the protection of the Mask.
287 : * A value of 1 represents full protection and a value of 0 means no protection. This depends on the MaskType of the
288 : * Mask the Person is wearing.
289 : * @param[in] params The parameters of the Infection that are the same everywhere within the Model.
290 : * @return The reduction factor of getting an Infection when wearing the Mask.
291 : */
292 : ScalarType get_mask_protective_factor(const Parameters& params) const;
293 :
294 : /**
295 : * @brief For every #InterventionType a Person has a compliance value between 0 and 1.
296 : * 0 means that the Person never complies to the Intervention.
297 : * 1 means that the Person always complies to the Intervention.
298 : * @param[in] intervention_type The #InterventionType.
299 : * @param[in] value The compliance value.
300 : */
301 216 : void set_compliance(InterventionType intervention_type, ScalarType value)
302 : {
303 216 : m_compliance[static_cast<uint32_t>(intervention_type)] = value;
304 216 : }
305 :
306 : /**
307 : * @brief Get the compliance of the Person for an Intervention.
308 : * @param[in] intervention_type The #InterventionType.
309 : * @return The probability that the Person complies to an Intervention.
310 : */
311 666 : ScalarType get_compliance(InterventionType intervention_type) const
312 : {
313 666 : return m_compliance[static_cast<uint32_t>(intervention_type)];
314 : }
315 :
316 : /**
317 : * @brief Checks whether the Person complies an Intervention.
318 : * @param[inout] rng PersonalRandomNumberGenerator of the Person.
319 : * @param[in] intervention The #InterventionType.
320 : * @return Checks whether the Person complies an Intervention.
321 : */
322 : bool is_compliant(PersonalRandomNumberGenerator& rng, InterventionType intervention) const;
323 :
324 : /**
325 : * @brief Change the mask to new type.
326 : * @param[in] type The required #MaskType.
327 : * @param[in] t The TimePoint of mask change.
328 : */
329 : void set_mask(MaskType type, TimePoint t);
330 :
331 : /**
332 : * @brief Get the multiplicative factor on how likely an #Infection is due to the immune system.
333 : * @param[in] t TimePoint of check.
334 : * @param[in] virus VirusVariant to check
335 : * @param[in] params Parameters in the model.
336 : * @returns Protection factor for general #Infection of the immune system to the given VirusVariant at the given TimePoint.
337 : */
338 : ScalarType get_protection_factor(TimePoint t, VirusVariant virus, const Parameters& params) const;
339 :
340 : /**
341 : * @brief Add a new vaccination
342 : * @param[in] v ProtectionType (i. e. vaccine) the person takes.
343 : * @param[in] t TimePoint of the vaccination.
344 : */
345 18 : void add_new_vaccination(ProtectionType v, TimePoint t)
346 : {
347 18 : m_vaccinations.push_back(ProtectionEvent(v, t));
348 18 : }
349 :
350 : /**
351 : * @brief Get the transport mode the Person used to get to its current Location.
352 : * @return TransportMode the Person used to get to its current Location.
353 : */
354 1377 : mio::abm::TransportMode get_last_transport_mode() const
355 : {
356 1377 : return m_last_transport_mode;
357 : }
358 :
359 : /**
360 : * @brief Set the transport mode the Person used to get to its current Location.
361 : * @param[in] mode TransportMode the Person used to get to its current Location.
362 : */
363 351 : void set_last_transport_mode(const mio::abm::TransportMode mode)
364 : {
365 351 : m_last_transport_mode = mode;
366 351 : }
367 :
368 : /**
369 : * @brief Get this persons RandomNumberGenerator counter.
370 : * @see mio::abm::PersonalRandomNumberGenerator.
371 : */
372 6642 : Counter<uint32_t>& get_rng_counter()
373 : {
374 6642 : return m_rng_counter;
375 : }
376 :
377 : /**
378 : * @brief Get the latest #ProtectionType and its initial TimePoint of the Person.
379 : */
380 : ProtectionEvent get_latest_protection() const;
381 :
382 : /// This method is used by the default serialization feature.
383 18 : auto default_serialize()
384 : {
385 36 : return Members("Person")
386 54 : .add("location", m_location)
387 54 : .add("location_type", m_location_type)
388 54 : .add("assigned_locations", m_assigned_locations)
389 54 : .add("vaccinations", m_vaccinations)
390 54 : .add("infections", m_infections)
391 54 : .add("home_isolation_start", m_home_isolation_start)
392 54 : .add("age_group", m_age)
393 54 : .add("time_at_location", m_time_at_location)
394 54 : .add("rnd_workgroup", m_random_workgroup)
395 54 : .add("rnd_schoolgroup", m_random_schoolgroup)
396 54 : .add("rnd_go_to_work_hour", m_random_goto_work_hour)
397 54 : .add("rnd_go_to_school_hour", m_random_goto_school_hour)
398 54 : .add("mask", m_mask)
399 54 : .add("compliance", m_compliance)
400 54 : .add("id", m_person_id)
401 54 : .add("cells", m_cells)
402 54 : .add("last_transport_mode", m_last_transport_mode)
403 54 : .add("rng_counter", m_rng_counter)
404 54 : .add("test_results", m_test_results);
405 : }
406 :
407 : /**
408 : * @brief Add TestResult to the Person
409 : * @param[in] t The TimePoint of the test.
410 : * @param[in] type The TestType of the test.
411 : * @param[in] result The result of the test.
412 : */
413 : void add_test_result(TimePoint t, TestType type, bool result);
414 :
415 : /**
416 : * @brief Get the most recent TestResult performed from the Person based on the TestType.
417 : * If time_of_testing == TimePoint(std::numeric_limits<int>::min()), there is no previous TestResult.
418 : * @param[in] type The TestType of the test.
419 : * @return The latest TestResult of the given Type.
420 : */
421 : TestResult get_test_result(TestType type) const;
422 :
423 : private:
424 : LocationId m_location; ///< Current Location of the Person.
425 : LocationType m_location_type; ///< Type of the current Location.
426 : std::vector<LocationId> m_assigned_locations; /**! Vector with the indices of the assigned Locations so that the
427 : Person always visits the same Home or School etc. */
428 : std::vector<ProtectionEvent> m_vaccinations; ///< Vector with all vaccinations the Person has received.
429 : std::vector<Infection> m_infections; ///< Vector with all Infection%s the Person had.
430 : TimePoint m_home_isolation_start; ///< TimePoint when the Person started isolation at home.
431 : AgeGroup m_age; ///< AgeGroup the Person belongs to.
432 : TimeSpan m_time_at_location; ///< Time the Person has spent at its current Location so far.
433 : double m_random_workgroup; ///< Value to determine if the Person goes to work or works from home during lockdown.
434 : double m_random_schoolgroup; ///< Value to determine if the Person goes to school or stays at home during lockdown.
435 : double m_random_goto_work_hour; ///< Value to determine at what time the Person goes to work.
436 : double m_random_goto_school_hour; ///< Value to determine at what time the Person goes to school.
437 : Mask m_mask; ///< The Mask of the Person.
438 : std::vector<ScalarType>
439 : m_compliance; ///< Vector of compliance values for all #InterventionType%s. Values from 0 to 1.
440 : PersonId m_person_id; ///< Id of the Person.
441 : std::vector<uint32_t> m_cells; ///< Vector with all Cell%s the Person visits at its current Location.
442 : mio::abm::TransportMode m_last_transport_mode; ///< TransportMode the Person used to get to its current Location.
443 : Counter<uint32_t> m_rng_counter{0}; ///< counter for RandomNumberGenerator.
444 : CustomIndexArray<TestResult, TestType> m_test_results; ///< CustomIndexArray for TestResults.
445 : };
446 :
447 : } // namespace abm
448 :
449 : /// @brief Creates an instance of abm::Person for default serialization.
450 : template <>
451 : struct DefaultFactory<abm::Person> {
452 9 : static abm::Person create()
453 : {
454 : return abm::Person(thread_local_rng(), abm::LocationType::Count, abm::LocationId(), AgeGroup(0),
455 9 : abm::PersonId());
456 : }
457 : };
458 :
459 : } // namespace mio
460 :
461 : #endif
|