Simpact Cyan
Population based event driven simulation using mNRM
person.h
1 #ifndef PERSON_H
2 
3 #define PERSON_H
4 
5 #include "personbase.h"
6 #include "util.h"
7 #include "aidstodutil.h"
8 #include <stdlib.h>
9 #include <iostream>
10 #include <vector>
11 #include <set>
12 
13 class Person;
14 class Man;
15 class Woman;
17 class ConfigSettings;
18 class ConfigWriter;
20 class VspModel;
21 
22 Man *MAN(Person *pPerson);
23 Woman *WOMAN(Person *pPerson);
24 
25 class Person : public PersonBase
26 {
27 public:
28  enum InfectionType { None, Partner, Mother, Seed };
29  enum InfectionStage { NoInfection, Acute, Chronic, AIDS, AIDSFinal };
30 
31  Person(double dateOfBirth, Gender g);
32  ~Person();
33 
34  bool isMan() const { return getGender() == Male; }
35  bool isWoman() const { return getGender() == Female; }
36 
37  void setFather(Man *pFather) { assert(m_pFather == 0); assert(pFather != 0); m_pFather = pFather; }
38  void setMother(Woman *pMother) { assert(m_pMother == 0); assert(pMother != 0); m_pMother = pMother; }
39 
40  Man *getFather() const { return m_pFather; }
41  Woman *getMother() const { return m_pMother; }
42 
43  // This also resets the iterator for getNextRelationshipPartner
44  int getNumberOfRelationships() const { return m_relationshipsSet.size(); }
45  void startRelationshipIteration();
46  Person *getNextRelationshipPartner(double &formationTime);
47 
48  bool hasRelationshipWith(Person *pPerson) const;
49 
50  // WARNING: do not use these during relationship iteration
51  void addRelationship(Person *pPerson, double t);
52  void removeRelationship(Person *pPerson, double t, bool deathBased);
53 
54  // result is negative if no relations formed yet
55  double getLastRelationshipChangeTime() const { return m_lastRelationChangeTime; }
56 
57  void setSexuallyActive(double t) { m_sexuallyActive = true; assert(t >= 0); m_debutTime = t; }
58  bool isSexuallyActive() { return m_sexuallyActive;}
59  double getDebutTime() const { return m_debutTime; }
60 
61  void setInfected(double t, Person *pOrigin, InfectionType iType);
62  bool isInfected() const { if (m_infectionStage == NoInfection) return false; return true; }
63  double getInfectionTime() const { assert(m_infectionStage != NoInfection); return m_infectionTime; }
64  InfectionStage getInfectionStage() const { return m_infectionStage; }
65  void setInChronicStage() { assert(m_infectionStage == Acute); m_infectionStage = Chronic; }
66  void setInAIDSStage() { assert(m_infectionStage == Chronic); m_infectionStage = AIDS; }
67  void setInFinalAIDSStage() { assert(m_infectionStage == AIDS); m_infectionStage = AIDSFinal; }
68  double getAIDSMortalityTime() const { return m_aidsTodUtil.getTimeOfDeath(); }
69 
70  double getSetPointViralLoad() const { assert(m_infectionStage != NoInfection); return m_Vsp; }
71  double getViralLoad() const;
72  void lowerViralLoad(double fractionOnLogscale, double treatmentTime);
73  bool hasLoweredViralLoad() const { assert(isInfected()); assert(m_Vsp > 0); return m_VspLowered; }
74  double getLastTreatmentStartTime() const { assert(isInfected()); assert(m_Vsp > 0); assert(m_VspLowered); assert(m_lastTreatmentStartTime >= 0); return m_lastTreatmentStartTime; }
75  void resetViralLoad(double dropoutTime);
76  int getNumberTreatmentStarted() const { assert(isInfected()); return m_treatmentCount; }
77 
78  double getFormationEagernessParameter() const { return m_formationEagerness; }
79  double getPreferredAgeDifference() const { assert(m_preferredAgeDiff < 200.0 && m_preferredAgeDiff > -200.0); return m_preferredAgeDiff; }
80 
81  // TODO: currently, the death of a parent or the death of a child does
82  // not have any influence on this list. I don't think modifying the list
83  // on a mortality event is useful, will only complicate things
84  // TODO: what might be useful is a member function to retrieve the number
85  // of living children?
86  void addChild(Person *pPerson);
87  bool hasChild(Person *pPerson) const;
88  int getNumberOfChildren() const { return m_children.size(); }
89  Person *getChild(int idx);
90 
91  // NOTE: this ignores the call if already in the list
92  void addPersonOfInterest(Person *pPerson);
93  void removePersonOfInterest(Person *pPerson);
94  void clearPersonsOfInterest() { m_personsOfInterest.clear(); }
95  int getNumberOfPersonsOfInterest() const { return m_personsOfInterest.size(); }
96  Person *getPersonOfInterest(int idx) const { assert(idx >= 0 && idx < m_personsOfInterest.size()); Person *pPerson = m_personsOfInterest[idx]; assert(pPerson); return pPerson; }
97 
98  double getCD4Count(double t) const;
99 
100  static void processConfig(ConfigSettings &config, GslRandomNumberGenerator *pRndGen);
101  static void obtainConfig(ConfigWriter &config);
102 
103  static void writeToRelationLog(const Person *pMan, const Person *pWoman, double formationTime, double dissolutionTime);
104  void writeToPersonLog();
105  void writeToTreatmentLog(double dropoutTime, bool justDied);
106 private:
107  double initializeEagerness();
108  double getViralLoadFromSetPointViralLoad(double x) const;
109  void initializeCD4Counts();
110  static double pickSeedSetPointViralLoad();
111  static double pickInheritedSetPointViralLoad(const Person *pOrigin);
112 
113  class Relationship
114  {
115  public:
116  // A negative time is used when not relevant, e.g. when
117  // searching for a relationship with a person
118  Relationship(Person *pPerson, double formationTime) { assert(pPerson != 0); assert(formationTime > 0); m_pPerson = pPerson; m_formationTime = formationTime; }
119  Relationship(Person *pPerson) { assert(pPerson != 0); m_pPerson = pPerson; m_formationTime = -1; }
120 
121  Person *getPartner() const { return m_pPerson; }
122  double getFormationTime() const { return m_formationTime; }
123 
124  bool operator<(const Relationship &rel) const
125  {
126  if (m_pPerson->getPersonID() < rel.m_pPerson->getPersonID())
127  return true;
128  return false;
129  }
130  private:
131  Person *m_pPerson;
132  double m_formationTime;
133  };
134 
135 #ifndef NDEBUG
136  bool m_relIterationBusy;
137 #endif
138 
139  std::set<Relationship> m_relationshipsSet;
140  std::set<Relationship>::const_iterator m_relationshipsIterator;
141  double m_lastRelationChangeTime;
142  bool m_sexuallyActive;
143  double m_debutTime;
144 
145  double m_infectionTime;
146  Person *m_pInfectionOrigin;
147  InfectionType m_infectionType;
148  InfectionStage m_infectionStage;
149 
150  double m_Vsp, m_VspOriginal;
151  bool m_VspLowered;
152  double m_lastTreatmentStartTime;
153  int m_treatmentCount;
154 
155  Man *m_pFather;
156  Woman *m_pMother;
157 
158  double m_formationEagerness;
159  double m_preferredAgeDiff;
160 
161  std::vector<Person *> m_children;
162  std::vector<Person *> m_personsOfInterest;
163 
164  AIDSTimeOfDeathUtility m_aidsTodUtil;
165 
166  double m_cd4AtStart, m_cd4AtDeath;
167 
168  static double m_hivSeedWeibullShape;
169  static double m_hivSeedWeibullScale;
170  static double m_VspHeritabilitySigmaFraction;
171  static double m_acuteFromSetPointParamX;
172  static double m_aidsFromSetPointParamX;
173  static double m_finalAidsFromSetPointParamX;
174  static double m_maxValue;
175  static double m_maxViralLoad;
176  static ProbabilityDistribution *m_pEagernessDistribution;
177  static ProbabilityDistribution *m_pMaleAgeGapDistribution;
178  static ProbabilityDistribution *m_pFemaleAgeGapDistribution;
179  static VspModel *m_pVspModel;
180 
181  static ProbabilityDistribution *m_pCD4StartDistribution;
182  static ProbabilityDistribution *m_pCD4EndDistribution;
183 };
184 
185 inline double Person::getViralLoad() const
186 {
187  assert(m_infectionStage != NoInfection);
188  if (m_infectionStage == Acute)
189  return getViralLoadFromSetPointViralLoad(m_acuteFromSetPointParamX);
190  else if (m_infectionStage == Chronic)
191  return getSetPointViralLoad();
192  else if (m_infectionStage == AIDS)
193  return getViralLoadFromSetPointViralLoad(m_aidsFromSetPointParamX);
194  else if (m_infectionStage == AIDSFinal)
195  return getViralLoadFromSetPointViralLoad(m_finalAidsFromSetPointParamX);
196 
197  abortWithMessage("Unknown stage in Person::getViralLoad");
198  return -1;
199 }
200 
201 inline void Person::addChild(Person *pPerson)
202 {
203  assert(pPerson != 0);
204  assert(!hasChild(pPerson));
205 
206  m_children.push_back(pPerson);
207 }
208 
209 // TODO: this is currently not fast for large number of children
210 // can always use a 'set' if this becomes a bottleneck
211 inline bool Person::hasChild(Person *pPerson) const
212 {
213  assert(pPerson != 0);
214 
215  for (int i = 0 ; i < m_children.size() ; i++)
216  {
217  assert(m_children[i] != 0);
218 
219  if (m_children[i] == pPerson)
220  return true;
221  }
222 
223  return false;
224 }
225 
226 class Man : public Person
227 {
228 public:
229  Man(double dateOfBirth);
230  ~Man();
231 };
232 
233 class Woman : public Person
234 {
235 public:
236  Woman(double dateOfBirth);
237  ~Woman();
238 
239  void setPregnant(bool f) { m_pregnant = f; }
240  bool isPregnant() const { return m_pregnant; }
241 private:
242  bool m_pregnant;
243 };
244 
245 inline bool Person::hasRelationshipWith(Person *pPerson) const
246 {
247  return m_relationshipsSet.find(Person::Relationship(pPerson)) != m_relationshipsSet.end();
248 }
249 
250 inline Man *MAN(Person *pPerson)
251 {
252  assert(pPerson != 0);
253  assert(pPerson->getGender() == PersonBase::Male);
254 
255  return static_cast<Man*>(pPerson);
256 }
257 
258 inline Woman *WOMAN(Person *pPerson)
259 {
260  assert(pPerson != 0);
261  assert(pPerson->getGender() == PersonBase::Female);
262 
263  return static_cast<Woman*>(pPerson);
264 }
265 
266 inline Person* Person::getChild(int idx)
267 {
268  assert(idx >= 0 && idx < m_children.size());
269  Person *pChild = m_children[idx];
270 
271  assert(pChild != 0);
272 #ifndef NDEBUG
273  if (isWoman())
274  {
275  assert(pChild->getMother() == this);
276  }
277  else // we should be the father of the child
278  {
279  assert(pChild->getFather() == this);
280  }
281 #endif
282  return pChild;
283 }
284 
285 #endif // PERSON_H
286 
The person is a man.
Definition: personbase.h:30
Gender getGender() const
Returns the gender of the person as set at construction time.
Definition: personbase.h:50
Helper class to read configuration settings, more advanced than ConfigReader.
Definition: configsettings.h:21
The person is a woman.
Definition: personbase.h:32
This class allows you to generate random numbers, and uses the GNU Scientific Library for this...
Definition: gslrandomnumbergenerator.h:16
This is the base class for a person in a population-based simulation that used the Population class...
Definition: personbase.h:23
Abstract base class for probability distribution implementations so that they can be used interchange...
Definition: probabilitydistribution.h:15