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