Simpact Cyan
Population based event driven simulation using mNRM
population.h
Go to the documentation of this file.
1 #ifndef POPULATION_H
2 
3 #define POPULATION_H
4 
9 //#define SIMPLEMNRM -> now defined using the CMakeList.txt file
10 
11 #include "simplestate.h"
12 #include "mutex.h"
13 #include <assert.h>
14 
16 class PersonBase;
17 class PopulationEvent;
18 
82 #ifndef SIMPLEMNRM
83 class Population : public State
84 #else
85 class Population : public SimpleState
86 #endif // SIMPLEMNRM
87 {
88 public:
92  Population(bool parallel, GslRandomNumberGenerator *pRng);
93  ~Population();
94 
95  bool isParallel() const { return m_parallel; }
96 
108  bool run(double &tMax, int64_t &maxEvents, double startTime = 0) { return State::evolve(tMax, maxEvents, startTime, false); }
109 
112  PersonBase **getAllPeople() { if (m_people.size() == m_numGlobalDummies) return 0; return &(m_people[m_numGlobalDummies]); }
113 
115  PersonBase **getMen();
116 
118  PersonBase **getWomen();
119 
122  PersonBase **getDeceasedPeople() { if (m_deceasedPersons.size() == 0) return 0; return &(m_deceasedPersons[0]); }
123 
125  int getNumberOfPeople() const { int num = (int)m_people.size() - m_numGlobalDummies; assert(num >= 0); return num; }
126 
128  int getNumberOfMen() const { return m_numMen; }
129 
131  int getNumberOfWomen() const { return m_numWomen; }
132 
134  int getNumberOfDeceasedPeople() const { return m_deceasedPersons.size(); }
135 
140  void addNewPerson(PersonBase *pPerson);
141 
146  void setPersonDied(PersonBase *pPerson);
147 
150  void onNewEvent(PopulationEvent *pEvt);
151 
155  void markAffectedPerson(PersonBase *pPerson) const;
156 
157  // TODO: shield these from the user somehow? These functions should not be used
158  // directly by the user, they are used internally by the algorithm
159  void scheduleForRemoval(PopulationEvent *pEvt);
160  void lockEvent(PopulationEvent *pEvt) const;
161  void unlockEvent(PopulationEvent *pEvt) const;
162  void lockPerson(PersonBase *pPerson) const;
163  void unlockPerson(PersonBase *pPerson) const;
164 private:
165  bool initEventTimes() const;
166 #ifndef SIMPLEMNRM
167  EventBase *getNextScheduledEvent(double &dt);
168  void advanceEventTimes(EventBase *pScheduledEvent, double dt);
169 #else
170  const std::vector<EventBase *> &getCurrentEvents() const { return m_allEvents; }
171  void onFiredEvent(EventBase *pEvt, int position);
172 
173  std::vector<EventBase *> m_allEvents;
174 #endif // SIMPLEMNRM
175 
176 #ifdef STATE_SHOW_EVENTS
177  void showEvents(); // FOR DEBUGGING
178 #endif // STATE_SHOW_EVENTS
179  void onAlgorithmLoop();
180 
181  PopulationEvent *getEarliestEvent(const std::vector<PersonBase *> &people);
182  int64_t getNextEventID();
183  int64_t getNextPersonID();
184 
185  // These are living persons, the first part men, the second are women
186  std::vector<PersonBase *> m_people;
187  int m_numMen, m_numWomen;
188  int m_numGlobalDummies;
189 
190  // Deceased persons
191  std::vector<PersonBase *> m_deceasedPersons;
192 
193 #ifndef DISABLEOPENMP
194  Mutex m_eventsToRemoveMutex;
195 #endif // !DISABLEOPENMP
196  std::vector<EventBase *> m_eventsToRemove;
197 
198  // For the parallel version
199  bool m_parallel;
200 
201  int64_t m_nextEventID, m_nextPersonID;
202 #ifndef DISABLEOPENMP
203  Mutex m_nextEventIDMutex, m_nextPersonIDMutex;
204 #endif // !DISABLEOPENMP
205 
206  std::vector<PopulationEvent *> m_tmpEarliestEvents;
207  std::vector<double> m_tmpEarliestTimes;
208 
209  mutable std::vector<PersonBase *> m_otherAffectedPeople;
210 
211 #ifndef DISABLEOPENMP
212  mutable std::vector<Mutex> m_eventMutexes;
213  mutable std::vector<Mutex> m_personMutexes;
214 #endif // !DISABLEOPENMP
215 };
216 
217 inline int64_t Population::getNextEventID()
218 {
219 #ifndef DISABLEOPENMP
220  if (m_parallel)
221  m_nextEventIDMutex.lock();
222 #endif // !DISABLEOPENMP
223 
224  int64_t id = m_nextEventID++;
225 
226 #ifndef DISABLEOPENMP
227  if (m_parallel)
228  m_nextEventIDMutex.unlock();
229 #endif // !DISABLEOPENMP
230 
231  return id;
232 }
233 
234 inline int64_t Population::getNextPersonID()
235 {
236 #ifndef DISABLEOPENMP
237  if (m_parallel)
238  m_nextPersonIDMutex.lock();
239 #endif // !DISABLEOPENMP
240 
241  int64_t id = m_nextPersonID++;
242 
243 #ifndef DISABLEOPENMP
244  if (m_parallel)
245  m_nextPersonIDMutex.unlock();
246 #endif // !DISABLEOPENMP
247 
248  return id;
249 }
250 
251 #ifdef NDEBUG
252 
253 inline void Population::markAffectedPerson(PersonBase *pPerson) const
254 {
255  m_otherAffectedPeople.push_back(pPerson);
256 }
257 
259 {
260  if (m_numMen == 0)
261  return 0;
262 
263  return &(m_people[m_numGlobalDummies]);
264 }
265 
267 {
268  if (m_numWomen == 0)
269  return 0;
270 
271  return &(m_people[m_numMen+m_numGlobalDummies]);
272 }
273 
274 #endif // NDEBUG
275 
276 #endif // POPULATION_H
bool run(double &tMax, int64_t &maxEvents, double startTime=0)
This should be called to actually start the simulation, do not call State::evolve for this...
Definition: population.h:108
int getNumberOfMen() const
Returns the number of people in the array returned by Population::getMen.
Definition: population.h:128
This class both describes the simulation state and contains the core algorithm (as shown on the main ...
Definition: state.h:40
virtual void onFiredEvent(EventBase *pEvt)
Called after pEvt is fired.
Definition: state.h:135
void addNewPerson(PersonBase *pPerson)
When a new person is introduced into the population, this function must be used to tell the simulatio...
Definition: population.cpp:606
PersonBase ** getDeceasedPeople()
Returns the people who were part of the simulation but who are now deceased (intended for result anal...
Definition: population.h:122
This class provides functions for a population-based simulation using the modified Next Reaction Meth...
Definition: population.h:83
void setPersonDied(PersonBase *pPerson)
When a person has died, this function must be called to inform the simulation about this...
Definition: population.cpp:95
void markAffectedPerson(PersonBase *pPerson) const
This should only be called from within the PopulationEvent::markOtherAffectedPeople function...
Definition: population.cpp:498
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 events in population-based simulations which use the Population class...
Definition: populationevent.h:61
int getNumberOfPeople() const
Returns the number of people in the array returned by Population::getAllPeople.
Definition: population.h:125
This is the base class for a person in a population-based simulation that used the Population class...
Definition: personbase.h:23
Population(bool parallel, GslRandomNumberGenerator *pRng)
Constructor of the class, indicating if a parallel version should be used and which random number gen...
Definition: population.cpp:17
PersonBase ** getMen()
Same as Population::getAllPeople, but only the men are returned.
Definition: population.cpp:505
PersonBase ** getWomen()
Same as Population::getAllPeople, but only the women are returned.
Definition: population.cpp:518
This is the base class for events in the mNRM algorithm.
Definition: eventbase.h:62
bool evolve(double &tMax, int64_t &maxEvents, double startTime=0, bool initEvents=true)
This advances the simulation state using the core mNRM.
Definition: state.cpp:23
PersonBase ** getAllPeople()
Returns a list to the current living members in the population, introduced into the simulation using ...
Definition: population.h:112
void onNewEvent(PopulationEvent *pEvt)
When a new event has been created, it must be injected into the simulation using this function...
Definition: population.cpp:535
int getNumberOfWomen() const
Returns the number of people in the array returned by Population::getWomen.
Definition: population.h:131
int getNumberOfDeceasedPeople() const
Returns the number of people in the array returned by Population::getDeceasedPeople.
Definition: population.h:134
A very naive implementation of the necessary functions from the State class.
Definition: simplestate.h:86