Simpact Cyan
Population based event driven simulation using mNRM
|
This class provides functions for a population-based simulation using the modified Next Reaction Method (mNRM). More...
#include <population.h>
Public Member Functions | |
Population (bool parallel, GslRandomNumberGenerator *pRng) | |
Constructor of the class, indicating if a parallel version should be used and which random number generator should be used. More... | |
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. More... | |
PersonBase ** | getAllPeople () |
Returns a list to the current living members in the population, introduced into the simulation using Population::addNewPerson. More... | |
PersonBase ** | getMen () |
Same as Population::getAllPeople, but only the men are returned. More... | |
PersonBase ** | getWomen () |
Same as Population::getAllPeople, but only the women are returned. More... | |
PersonBase ** | getDeceasedPeople () |
Returns the people who were part of the simulation but who are now deceased (intended for result analysis, not to be used during the simulation). More... | |
int | getNumberOfPeople () const |
Returns the number of people in the array returned by Population::getAllPeople. More... | |
int | getNumberOfMen () const |
Returns the number of people in the array returned by Population::getMen. More... | |
int | getNumberOfWomen () const |
Returns the number of people in the array returned by Population::getWomen. More... | |
int | getNumberOfDeceasedPeople () const |
Returns the number of people in the array returned by Population::getDeceasedPeople. More... | |
void | addNewPerson (PersonBase *pPerson) |
When a new person is introduced into the population, this function must be used to tell the simulation about this. More... | |
void | setPersonDied (PersonBase *pPerson) |
When a person has died, this function must be called to inform the simulation about this. More... | |
void | onNewEvent (PopulationEvent *pEvt) |
When a new event has been created, it must be injected into the simulation using this function. More... | |
void | markAffectedPerson (PersonBase *pPerson) const |
This should only be called from within the PopulationEvent::markOtherAffectedPeople function, to indicate which other persons are also affected by the event (other that the persons mentioned in the event constructor. More... | |
Public Member Functions inherited from State | |
State (GslRandomNumberGenerator *pRng) | |
Constructor of the class, to which the random number generator to be used internally must be specified. More... | |
bool | evolve (double &tMax, int64_t &maxEvents, double startTime=0, bool initEvents=true) |
This advances the simulation state using the core mNRM. More... | |
double | getTime () const |
This function returns the current time of the simulation. More... | |
GslRandomNumberGenerator * | getRandomNumberGenerator () const |
Returns the random number generator that was specified in the constructor. More... | |
Public Member Functions inherited from errut::ErrorBase | |
ErrorBase () | |
Creates an instance without an explicit object name. More... | |
ErrorBase (const std::string &objName) | |
Creates an instance with the object name set to objName . More... | |
std::string | getObjectName () const |
Returns the stored object name. More... | |
std::string | getErrorString () const |
Returns the currently stored error message. More... | |
Additional Inherited Members | |
Protected Member Functions inherited from State | |
virtual void | onAboutToFire (EventBase *pEvt) |
Called right before pEvt is fired. More... | |
virtual void | onFiredEvent (EventBase *pEvt) |
Called after pEvt is fired. More... | |
virtual void | onAlgorithmLoop (bool finished) |
Called at the end of each algorithm loop, with finished set to true if the loop will be exited. More... | |
Protected Member Functions inherited from errut::ErrorBase | |
void | setErrorString (const std::string &str) const |
Derived classes can use this member function to store an error message. More... | |
This class provides functions for a population-based simulation using the modified Next Reaction Method (mNRM).
Being population-based, the state of the simulation mostly consists of the (living) people.
Depending on a compiler setting, it either uses the very straightforward algorithm provided by the SimpleState class, or it uses a different algorithm by deriving from State directly and overriding the functions State::getNextScheduledEvent and State::advanceEventTimes. It is always good to compare the results of the two versions to assure the correct working of this more optimized version.
This is a base class for an actual simulation and needs to be completed. The initialization of the persons in the population (represented by classes derived from PersonBase) and of the initial events in the simulation needs to be done in a derived class. When this initialization is done, the Population::run function can be called to actually start the simulation.
Events for this type of simulation should derive from the PopulationEvent class instead of using the EventBase base class directly.
To know how to use this population based algorithm, it can be useful to understand the way it works. The figure below illustrates how everything is organized. In essence, a population is just a collection of people (represented by some class derived from PersonBase), and each person stores a list of events that are relevant to him.
When you construct a new PopulationEvent based instance, you need to specify the persons involved in this event, and the event gets stored in these persons' lists. As the figure shows, it is very well possible that a single event appears in the lists of different people: for example a relationship formation event would involve two persons and would therefore be present in two lists. To be able to have global events, events that in principle don't affect people that are known in advance, a 'dummy' person is introduced. This 'dummy' person, neither labelled as a 'Man' nor as a 'Woman', only has such global events in its event list. By definition, these events will not be present in any other person's list. Note that this implies that PopulationEvent::getNumberOfPersons will also return 1 for global events.
When an event fires, the algorithm assumes that the persons which have the event in their lists are affected and that their events will require a recalculation of the fire times. In case other people are affected as well (who you don't know beforehand), this can be specified using the functions PopulationEvent::isEveryoneAffected or PopulationEvent::markOtherAffectedPeople. If such additional people are specified as well, those people's event fire times will be recalculated as well. Using PopulationEvent::areGlobalEventsAffected you can indicate that the fire times of global events should be recalculated.
Before recalculating an event fire time, it is checked if the event is still relevant. If one of the persons specified in the PopulationEvent constructor has died, the event is deemed useless and will be discarded. In case it's possible that an event becomes useless because of some other criteria, the PopulationEvent::isUseless function should be reimplemented to inform the algorithm about this. But note that this is only called before recalculating an event fire time, which in turn is only done for people affected by the event.
Each person keeps track of which event in his list will fire first. To know which event in the entire simulation will fire first, the algorithm then just needs to check the first event times for all the people.
Population::Population | ( | bool | parallel, |
GslRandomNumberGenerator * | pRng | ||
) |
Constructor of the class, indicating if a parallel version should be used and which random number generator should be used.
void Population::addNewPerson | ( | PersonBase * | pPerson | ) |
When a new person is introduced into the population, this function must be used to tell the simulation about this.
In essence this function will make sure that the person appears in the arrays returned by Population::getAllPeople, Population::getMen and Population::getWomen.
|
inline |
Returns a list to the current living members in the population, introduced into the simulation using Population::addNewPerson.
|
inline |
Returns the people who were part of the simulation but who are now deceased (intended for result analysis, not to be used during the simulation).
PersonBase ** Population::getMen | ( | ) |
Same as Population::getAllPeople, but only the men are returned.
|
inline |
Returns the number of people in the array returned by Population::getDeceasedPeople.
|
inline |
Returns the number of people in the array returned by Population::getMen.
|
inline |
Returns the number of people in the array returned by Population::getAllPeople.
|
inline |
Returns the number of people in the array returned by Population::getWomen.
PersonBase ** Population::getWomen | ( | ) |
Same as Population::getAllPeople, but only the women are returned.
void Population::markAffectedPerson | ( | PersonBase * | pPerson | ) | const |
This should only be called from within the PopulationEvent::markOtherAffectedPeople function, to indicate which other persons are also affected by the event (other that the persons mentioned in the event constructor.
void Population::onNewEvent | ( | PopulationEvent * | pEvt | ) |
When a new event has been created, it must be injected into the simulation using this function.
|
inline |
This should be called to actually start the simulation, do not call State::evolve for this.
tMax | Stop the simulation if the simulation time exceeds the specified time. Upon completion of the function, this variable will contain the actual simulation time stopped. |
maxEvents | If positive, the simulation will stop if this many events have been executed. Set to a negative value to disable this limit. At the end of the simulation, this variable will contain the number of events executed. |
startTime | The start time of the simulation, can be used to continue where a previous call to this function left off. |
void Population::setPersonDied | ( | PersonBase * | pPerson | ) |
When a person has died, this function must be called to inform the simulation about this.
This function will set the time of death for the person and will remove the person from the arrays with living people (Population::getAllPeople, Population::getMen and Population::getWomen.