See

<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”/>