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  static void processConfig(ConfigSettings &config, GslRandomNumberGenerator *pRndGen);
88  static void obtainConfig(ConfigWriter &config);
89 
90  static void writeToRelationLog(const Person *pMan, const Person *pWoman, double formationTime, double dissolutionTime);
91  void writeToPersonLog();
92 private:
93  double initializeEagerness();
94  double getViralLoadFromSetPointViralLoad(double x) const;
95  static double pickSeedSetPointViralLoad();
96  static double pickInheritedSetPointViralLoad(const Person *pOrigin);
97 
98  class Relationship
99  {
100  public:
101  // A negative time is used when not relevant, e.g. when
102  // searching for a relationship with a person
103  Relationship(Person *pPerson, double formationTime) { assert(pPerson != 0); assert(formationTime > 0); m_pPerson = pPerson; m_formationTime = formationTime; }
104  Relationship(Person *pPerson) { assert(pPerson != 0); m_pPerson = pPerson; m_formationTime = -1; }
105 
106  Person *getPartner() const { return m_pPerson; }
107  double getFormationTime() const { return m_formationTime; }
108 
109  bool operator<(const Relationship &rel) const
110  {
111  if (m_pPerson->getPersonID() < rel.m_pPerson->getPersonID())
112  return true;
113  return false;
114  }
115  private:
116  Person *m_pPerson;
117  double m_formationTime;
118  };
119 
120 #ifndef NDEBUG
121  bool m_relIterationBusy;
122 #endif
123 
124  std::set<Relationship> m_relationshipsSet;
125  std::set<Relationship>::const_iterator m_relationshipsIterator;
126  double m_lastRelationChangeTime;
127  bool m_sexuallyActive;
128  double m_debutTime;
129 
130  double m_infectionTime;
131  Person *m_pInfectionOrigin;
132  InfectionType m_infectionType;
133  InfectionStage m_infectionStage;
134 
135  double m_Vsp, m_VspOriginal;
136  bool m_VspLowered;
137  double m_treatmentTime;
138 
139  Man *m_pFather;
140  Woman *m_pMother;
141 
142  double m_formationEagerness;
143  double m_preferredAgeDiff;
144 
145  std::vector<Person *> m_children;
146 
147  static double m_hivSeedWeibullShape;
148  static double m_hivSeedWeibullScale;
149  static double m_VspHeritabilitySigmaFraction;
150  static double m_acuteFromSetPointParamX;
151  static double m_aidsFromSetPointParamX;
152  static double m_finalAidsFromSetPointParamX;
153  static double m_maxValue;
154  static double m_maxViralLoad;
155  static ProbabilityDistribution *m_pEagernessDistribution;
156  static ProbabilityDistribution *m_pMaleAgeGapDistribution;
157  static ProbabilityDistribution *m_pFemaleAgeGapDistribution;
158  static VspModel *m_pVspModel;
159 };
160 
161 inline double Person::getViralLoad() const
162 {
163  assert(m_infectionStage != NoInfection);
164  if (m_infectionStage == Acute)
165  return getViralLoadFromSetPointViralLoad(m_acuteFromSetPointParamX);
166  else if (m_infectionStage == Chronic)
167  return getSetPointViralLoad();
168  else if (m_infectionStage == AIDS)
169  return getViralLoadFromSetPointViralLoad(m_aidsFromSetPointParamX);
170  else if (m_infectionStage == AIDSFinal)
171  return getViralLoadFromSetPointViralLoad(m_finalAidsFromSetPointParamX);
172 
173  abortWithMessage("Unknown stage in Person::getViralLoad");
174  return -1;
175 }
176 
177 inline void Person::addChild(Person *pPerson)
178 {
179  assert(pPerson != 0);
180  assert(!hasChild(pPerson));
181 
182  m_children.push_back(pPerson);
183 }
184 
185 // TODO: this is currently not fast for large number of children
186 // can always use a 'set' if this becomes a bottleneck
187 inline bool Person::hasChild(Person *pPerson) const
188 {
189  assert(pPerson != 0);
190 
191  for (int i = 0 ; i < m_children.size() ; i++)
192  {
193  assert(m_children[i] != 0);
194 
195  if (m_children[i] == pPerson)
196  return true;
197  }
198 
199  return false;
200 }
201 
202 class Man : public Person
203 {
204 public:
205  Man(double dateOfBirth);
206  ~Man();
207 };
208 
209 class Woman : public Person
210 {
211 public:
212  Woman(double dateOfBirth);
213  ~Woman();
214 
215  void setPregnant(bool f) { m_pregnant = f; }
216  bool isPregnant() const { return m_pregnant; }
217 private:
218  bool m_pregnant;
219 };
220 
221 inline bool Person::hasRelationshipWith(Person *pPerson) const
222 {
223  return m_relationshipsSet.find(Person::Relationship(pPerson)) != m_relationshipsSet.end();
224 }
225 
226 inline Man *MAN(Person *pPerson)
227 {
228  assert(pPerson != 0);
229  assert(pPerson->getGender() == PersonBase::Male);
230 
231  return static_cast<Man*>(pPerson);
232 }
233 
234 inline Woman *WOMAN(Person *pPerson)
235 {
236  assert(pPerson != 0);
237  assert(pPerson->getGender() == PersonBase::Female);
238 
239  return static_cast<Woman*>(pPerson);
240 }
241 
242 inline Person* Person::getChild(int idx)
243 {
244  assert(idx >= 0 && idx < m_children.size());
245  Person *pChild = m_children[idx];
246 
247  assert(pChild != 0);
248 #ifndef NDEBUG
249  if (isWoman())
250  {
251  assert(pChild->getMother() == this);
252  }
253  else // we should be the father of the child
254  {
255  assert(pChild->getFather() == this);
256  }
257 #endif
258  return pChild;
259 }
260 
261 #endif // PERSON_H
262 
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:20
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