Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #Set 8: Simulating the Spread of Disease and Virus Population Dynamics
- import time
- import random
- '''
- Begin helper code
- '''
- class NoChildException(Exception):
- """
- NoChildException is raised by the reproduce() method in the SimpleVirus
- and ResistantVirus classes to indicate that a virus particle does not
- reproduce. You can use NoChildException as is, you do not need to
- modify/add any code.
- """
- '''
- End helper code
- '''
- #
- # PROBLEM 2
- #
- from copy import copy
- class SimpleVirus(object):
- """
- Representation of a simple virus (does not model drug effects/resistance).
- """
- def __init__(self, maxBirthProb, clearProb):
- """
- Initialize a SimpleVirus instance, saves all parameters as attributes
- of the instance.
- maxBirthProb: Maximum reproduction probability (a float between 0-1)
- clearProb: Maximum clearance probability (a float between 0-1).
- """
- self.max_birth_prob, self.clear_prob = maxBirthProb, clearProb
- def getMaxBirthProb(self):
- """
- Returns the max birth probability.
- """
- return self.max_birth_prob
- def getClearProb(self):
- """
- Returns the clear probability.
- """
- return self.clear_prob
- def doesClear(self):
- """ Stochastically determines whether this virus particle is cleared from the
- patient's body at a time step.
- returns: True with probability self.getClearProb and otherwise returns
- False.
- """
- return random.random() < self.getClearProb()
- def reproduce(self, popDensity):
- """
- Stochastically determines whether this virus particle reproduces at a
- time step. Called by the update() method in the Patient and
- TreatedPatient classes. The virus particle reproduces with probability
- self.getMaxBirthProb * (1 - popDensity).
- If this virus particle reproduces, then reproduce() creates and returns
- the instance of the offspring SimpleVirus (which has the same
- maxBirthProb and clearProb values as its parent).
- popDensity: the population density (a float), defined as the current
- virus population divided by the maximum population.
- returns: a new instance of the SimpleVirus class representing the
- offspring of this virus particle. The child should have the same
- maxBirthProb and clearProb values as this virus. Raises a
- NoChildException if this virus particle does not reproduce.
- """
- if random.random() < self.getMaxBirthProb() * (1 - popDensity):
- return copy(self)
- else:
- raise NoChildException
- class Patient(object):
- """
- Representation of a simplified patient. The patient does not take any drugs
- and his/her virus populations have no drug resistance.
- """
- def __init__(self, viruses, maxPop):
- """
- Initialization function, saves the viruses and maxPop parameters as
- attributes.
- viruses: the list representing the virus population (a list of
- SimpleVirus instances)
- maxPop: the maximum virus population for this patient (an integer)
- """
- self.viruses, self.maximum_population = viruses, maxPop
- def getViruses(self):
- """
- Returns the viruses in this Patient.
- """
- return self.viruses
- def getMaxPop(self):
- """
- Returns the max population.
- """
- return self.maximum_population
- def getTotalPop(self):
- """
- Gets the size of the current total virus population.
- returns: The total virus population (an integer)
- """
- return len(self.getViruses())
- def _new_viruses(self):
- """
- - Determine whether each virus particle survives and updates the list
- of virus particles accordingly.
- """
- new_viruses = []
- for virus in self.getViruses():
- if not virus.doesClear():
- new_viruses.append(virus)
- return new_viruses
- def _try_reproduce(self, population_density):
- """
- - Based on this value of population density, determine whether each
- virus particle should reproduce and add offspring virus particles to
- the list of viruses in this patient.
- """
- new_viruses = []
- for virus in self.viruses:
- try:
- new_viruses.append(virus.reproduce(population_density))
- except NoChildException:
- pass
- return new_viruses
- def update(self):
- """
- Update the state of the virus population in this patient for a single
- time step. update() should execute the following steps in this order:
- - Determine whether each virus particle survives and updates the list
- of virus particles accordingly.
- - The current population density is calculated. This population density
- value is used until the next call to update()
- - Based on this value of population density, determine whether each
- virus particle should reproduce and add offspring virus particles to
- the list of viruses in this patient.
- returns: The total virus population at the end of the update (an
- integer)
- """
- self.viruses = self._new_viruses()
- max_population = float(self.getMaxPop())
- #print len(self.viruses), 'survive'
- self.viruses.extend(self._try_reproduce(self.getTotalPop() / max_population))
- return self.getTotalPop()
- class ResistantVirus(SimpleVirus):
- """
- Representation of a virus which can have drug resistance.
- """
- def __init__(self, maxBirthProb, clearProb, resistances, mutProb):
- """
- Initialize a ResistantVirus instance, saves all parameters as attributes
- of the instance.
- maxBirthProb: Maximum reproduction probability (a float between 0-1)
- clearProb: Maximum clearance probability (a float between 0-1).
- resistances: A dictionary of drug names (strings) mapping to the state
- of this virus particle's resistance (either True or False) to each drug.
- e.g. {'guttagonol':False, 'srinol':False}, means that this virus
- particle is resistant to neither guttagonol nor srinol.
- mutProb: Mutation probability for this virus particle (a float). This is
- the probability of the offspring acquiring or losing resistance to a drug.
- """
- SimpleVirus.__init__(self, maxBirthProb, clearProb)
- self.resistances, self.mutProb = resistances, mutProb
- def isResistantTo(self, drug):
- """
- Get the state of this virus particle's resistance to a drug. This method
- is called by getResistPop() in TreatedPatient to determine how many virus
- particles have resistance to a drug.
- drug: The drug (a string)
- returns: True if this virus instance is resistant to the drug, False
- otherwise.
- """
- return self.resistances.get(drug, False)
- def reproduce(self, popDensity, activeDrugs):
- """
- Stochastically determines whether this virus particle reproduces at a
- time step. Called by the update() method in the TreatedPatient class.
- A virus particle will only reproduce if it is resistant to ALL the drugs
- in the activeDrugs list. For example, if there are 2 drugs in the
- activeDrugs list, and the virus particle is resistant to 1 or no drugs,
- then it will NOT reproduce.
- Hence, if the virus is resistant to all drugs
- in activeDrugs, then the virus reproduces with probability:
- self.getMaxBirthProb * (1 - popDensity).
- If this virus particle reproduces, then reproduce() creates and returns
- the instance of the offspring ResistantVirus (which has the same
- maxBirthProb and clearProb values as its parent). The offspring virus
- will have the same maxBirthProb, clearProb, and mutProb as the parent.
- For each drug resistance trait of the virus (i.e. each key of
- self.resistances), the offspring has probability 1-mutProb of
- inheriting that resistance trait from the parent, and probability
- mutProb of switching that resistance trait in the offspring.
- For example, if a virus particle is resistant to guttagonol but not
- srinol, and self.mutProb is 0.1, then there is a 10% chance that
- that the offspring will lose resistance to guttagonol and a 90%
- chance that the offspring will be resistant to guttagonol.
- There is also a 10% chance that the offspring will gain resistance to
- srinol and a 90% chance that the offspring will not be resistant to
- srinol.
- popDensity: the population density (a float), defined as the current
- virus population divided by the maximum population
- activeDrugs: a list of the drug names acting on this virus particle
- (a list of strings).
- returns: a new instance of the ResistantVirus class representing the
- offspring of this virus particle. The child should have the same
- maxBirthProb and clearProb values as this virus. Raises a
- NoChildException if this virus particle does not reproduce.
- """
- if (all(self.isResistantTo(drug) for drug in activeDrugs) and
- random.random() < self.getMaxBirthProb() * (1 - popDensity)):
- resistances = copy(self.resistances)
- for drug in self.resistances:
- if random.random() < self.mutProb:
- resistances[drug] = not resistances[drug]
- return ResistantVirus(self.getMaxBirthProb(), self.getClearProb(), resistances, self.mutProb)
- raise NoChildException
- class TreatedPatient(Patient):
- """
- Representation of a patient. The patient is able to take drugs and his/her
- virus population can acquire resistance to the drugs he/she takes.
- """
- def __init__(self, viruses, maxPop):
- """
- Initialization function, saves the viruses and maxPop parameters as
- attributes. Also initializes the drugs being administered
- (which should initially include no drugs).
- viruses: The list representing the virus population (a list of
- virus instances)
- maxPop: The maximum virus population for this patient (an integer)
- """
- Patient.__init__(self, viruses, maxPop)
- self.drugs = set()
- def addPrescription(self, newDrug):
- """
- Administer a drug to this patient. After a prescription is added, the
- drug acts on the virus population for all subsequent time steps. If the
- newDrug is already prescribed to this patient, the method has no effect.
- newDrug: The name of the drug to administer to the patient (a string).
- postcondition: The drugs being administered to a patient is updated
- """
- self.drugs.add(newDrug)
- def getPrescriptions(self):
- """
- Returns the drugs that are being administered to this patient.
- returns: The drug names (strings) being administered to this
- patient.
- """
- return self.drugs
- def getResistPop(self, drugResist):
- """
- Get the population of virus particles resistant to the drugs listed in
- drugResist.
- drugResist: Which drug resistances to include in the population (a list
- of strings - e.g. ['guttagonol'] or ['guttagonol', 'srinol'])
- returns: The population of viruses (an integer) with resistances to all
- drugs in the drugResist list.
- """
- return sum(1 for virus in self.viruses if all(virus.isResistantTo(drug)
- for drug in drugResist))
- def _try_reproduce(self, population_density):
- """
- - Based on this value of population density, determine whether each
- virus particle should reproduce and add offspring virus particles to
- the list of viruses in this patient.
- The list of drugs being administered should be accounted for in the
- determination of whether each virus particle reproduces.
- """
- new_viruses = []
- for virus in self.viruses:
- try:
- new_viruses.append(virus.reproduce(population_density, self.getPrescriptions()))
- except NoChildException:
- pass
- return new_viruses
- def col(mat,j):
- v=[]
- rows=len(mat)
- for i in xrange(rows):
- v.append(mat[i][j])
- return v
- def transpose(m):
- n = []
- cols=len(m[0])
- for i in xrange(cols):
- n.append(col(m,i))
- return n
- #
- # PROBLEM 5
- #
- def simulationWithDrug(numViruses, maxPop, maxBirthProb, clearProb, resistances,
- mutProb, numTrials, start=150, timing=False):
- """
- Runs simulations and plots graphs for problem 5.
- For each of numTrials trials, instantiates a patient, runs a simulation for
- 150 timesteps, adds guttagonol, and runs the simulation for an additional
- 150 timesteps. At the end plots the average virus population size
- (for both the total virus population and the guttagonol-resistant virus
- population) as a function of time.
- numViruses: number of ResistantVirus to create for patient (an integer)
- maxPop: maximum virus population for patient (an integer)
- maxBirthProb: Maximum reproduction probability (a float between 0-1)
- clearProb: maximum clearance probability (a float between 0-1)
- resistances: a dictionary of drugs that each ResistantVirus is resistant to
- (e.g., {'guttagonol': False})
- mutProb: mutation probability for each ResistantVirus particle
- (a float between 0-1).
- numTrials: number of simulation runs to execute (an integer)
- """
- simulations = []
- resistant_pop =[]
- if timing:
- t0 = time.clock()
- for trial in range(numTrials):
- population = [ResistantVirus(maxBirthProb, clearProb, resistances, mutProb) for _ in range(numViruses)]
- patient = TreatedPatient(population, maxPop)
- current = []
- resistant = []
- if not trial % 10: print trial,
- for simulation in range(300):
- if simulation == start:
- patient.addPrescription("guttagonol")
- ## for drug in resistances:
- ## patient.addPrescription(drug)
- current.append(float(patient.update()))
- resistant.append(float(patient.getResistPop(['guttagonol'])))
- simulations.append(current)
- resistant_pop.append(resistant)
- if timing:
- print time.clock() - t0, 's'
- else:
- print
- x = [sum(step)/len(step) for step in transpose(simulations)]
- y = [sum(resist)/len(resist) for resist in transpose(resistant_pop)]
- return x,y
- ## print x
- ## print y
- if __name__ == '__main__':
- random.seed(0)
- x, y = simulationWithDrug(100, 1000, 0.1, 0.05,
- {'guttagonol': False}, 0.005, 100, timing=True)
- print x
- print y
Advertisement
Add Comment
Please, Sign In to add comment