See
- The definitions simemindividual.h
- The description Epidemiological Modeling Individuals
<project-file type=“source”/> <content> #include <simemindividual.h> #include <simprocess.h> #include <genrand2.h>
#include <iostream>
SimEMIndividual::SimEMIndividual(SimID id, SimImmuneSystem *immunesystem)
: SimAgent(id)
{
ImmuneSystem = immunesystem; for (int i = 0; i < Infections.size(); i++) delete Infections[i];
}
SimEMIndividual::~SimEMIndividual() {
if (ImmuneSystem != NULL) delete ImmuneSystem; for (int i = 0; i < Infections.size(); i++) delete Infections[i];
}
SimImmuneSystem::SimImmuneSystem() { }
SimImmuneSystem::~SimImmuneSystem() { }
SimInfectionHistory::SimInfectionHistory() { }
SimInfectionHistory::~SimInfectionHistory() { }
float SimInfectionHistory::immunity(const SimPathogen *Pathogen, float time) {
if (Pathogen==NULL) return 1; std::map<SimID, float>::iterator p=History.find(Pathogen->id()); return (p == History.end())?0:1;
}
void SimInfectionHistory::infect(const SimPathogen *Pathogen, float time) {
if (Pathogen != NULL) History[Pathogen->id()] = time;
}
SimInfectionState::SimInfectionState(const SimPathogen * pathogen, float CurrentTime)
: SimSchedule(SIM_INFINITY)
{
// must have a pathogen if (pathogen==NULL) throw InvalidPathogen(); Pathogen = pathogen;
// must have at least on stage of in fection int i, n = pathogen->initialStages(); if (n == 0) throw InvalidPathogen();
// normalize the probability of entering which initial stage float probs[n]; probs[0] = pathogen->initialStageProbability(0); for (i = 1; i < n; i++) probs[i] = probs[i-1] + pathogen->initialStageProbability(i); float p = probs[n-1]; for (i = 0; i < n; i++) probs[i] /= p; p = genrand2d(); for (i = 0; i < n && p > probs[i]; i++); Stage = pathogen->initialStage(i);
// if the initial stage is invalid if (Stage == NULL) throw InvalidPathogen();
updateEvent(CurrentTime); }
void SimInfectionState::updateEvent(float CurrentTime) {
NextStage = NULL;
float DeathTime = SIM_INFINITY; float ProgressionTime = SIM_INFINITY; if (genrand2d() < Stage->fatality()) { NextState = SIM_DIE; DeathTime = Stage->deathTime(CurrentTime); } else { NextState = SIM_PROGRESS;
// normalize the probability of entering which linked stage int n = Stage->links(), i; float prob[n]; for (i = 0; i < n; i++) prob[i] = Stage->link(i)->probability(); for (i = 1; i < n; i++) prob[i] += prob[i - 1]; for (i = 0; i < n; i++) prob[i] /= prob[n-1]; float p = genrand2d(); for (i = 0; i < n && p > prob[i]; i++); const SimStageLink *l = Stage->link(i); ProgressionTime = CurrentTime + l->duration(); NextStage = l->stage(); } float MutationTime = expRandom(Pathogen->mutationRate())+CurrentTime; if (MutationTime < ProgressionTime && MutationTime < DeathTime) { NextState = SIM_MUTATE; setEventTime(MutationTime); } else if (NextState == SIM_DIE) setEventTime(DeathTime); else setEventTime(ProgressionTime);
}
SimInfectionState::~SimInfectionState() { }
void SimInfectionState::handler(float Time, SimProcess *process) {
switch (NextState) { case SIM_MUTATE: // if mutate, mutates. mutation does not change the infection status // so we simply discard the mutation state Mutant = Pathogen->mutate(Time); if (Mutant!=NULL) { ((SimEMIndividual*)owner())->infect(Mutant, Time, process); Stage = NULL; } break; case SIM_DIE: owner()->die(process); Stage = NULL; break; case SIM_PROGRESS: // if not mutation, then this is going to be the current state Stage = NextStage; break; }
process→log(Time, owner(), this);
((SimEMIndividual*)owner())->infectionStateChanged(Time, this);
if (NextState == SIM_PROGRESS && Stage != NULL) { // explicitly request for rescheduling updateEvent(Time); owner()->schedule(this); }
}
bool SimEMIndividual::infectious() const {
if (Infections.empty()) return false; int n = Infections.size(); for (int i = 0; i < n; i++) if (Infections[i]->infectivity() > 0) return true; return false;
}
void SimEMIndividual::infectionStateChanged(float, SimInfectionState *state) {
if (state == NULL || state->stage() != NULL) return;
unschedule(state); std::vector<SimInfectionState*>::iterator i; for (i= Infections.begin(); i != Infections.end() && *i != state; i++); if (i != Infections.end()) Infections.erase(i);
}
bool SimEMIndividual::infect(const SimPathogen *p, float CurrentTime,
SimProcess *process) { if (p==NULL) return false;
float Immunity = 0; if (ImmuneSystem != NULL) Immunity = ImmuneSystem->immunity(p, CurrentTime); else { for (int i=0; i<Infections.size(); i++) if (Infections[i]->pathogen() == p) return false; }
// looking for the infection state // infection only occurs when not currently infected if (genrand2d()>Immunity) { SimInfectionState *Infection = new SimInfectionState(p, CurrentTime); Infections.push_back(Infection); schedule(Infection); // add p into the immune system if (ImmuneSystem != NULL) ImmuneSystem->infect(p, CurrentTime); process->log(CurrentTime, this, Infection); infectionStateChanged(CurrentTime, Infection); return true; } return false;
}
bool SimEMIndividual::transmit(double Time, SimEMIndividual *victim, SimProcess *process) {
// if not infectious, do nothing if (!infectious() || victim == NULL) return false; // pass on all the infections int n = infections(); bool infected = false; for (int i = 0; i < n; i++) { const SimInfectionState *inf = infection(i); if (genrand2d() < inf->infectivity()) infected |= victim->infect(inf->pathogen(), Time, process); } return infected;
} </content> <use name=“simemindividual.h”/> <use name=“simpathogen.h”/> <use name=“simagent.h”/>