#Here the attributes (or data) and methods (or behaviours) for each object are defined #Population is defined as an array which will hold the "individuals" objects class Population < Array alias_method :old_init, :initialize def initialize(num = 0, val = nil, &proc) if block_given? num.times {|i| self.push (yield i)} else old_init(num, val) end end end #This is the individual class Individual #The various attributes for each individual animal are assigned # they are variables that hold: # alive (=1) or dead (alive = 0) # pregnant (mother = 1) or barren (mother = 0) # the age of the animal (continuous integer, ages) # disease status (infected = 0 or 1) attr_writer :sex, :alive, :mother, :ages, :infected def initialize(sex, alive = 1,mother = 0, ages=0, infected=0) @sex = sex @alive = alive @mother = mother @ages = ages @infected = infected end #This just tells the computer what to do if I call a "puts" (= print) def to_s "Sex: #{@sex} Alive: #{@alive} Pregnant: #{@mother} Age: #{@ages} Infected: #{@infected}\n " end # I defined the exp function here def exp(num) (2.71828182845904523536)**num end # these are accessor functions that allow the main portion of the program # to access individual object's attributes: def sex @sex end def alive @alive end def mother @mother end def ages @ages end def infected @infected end #These are the various methods or behaviours that each critter can do: #Choose sex def chooseSex if rand < 0.5 @sex = "M" else @sex = "F" end end # Get infected (McCarty infection probability function) def infect(n,nInfectious) r = rand p = 1-(1-1/n)**(nInfectious*2) if @infected ==0 if r < p @infected = 1 else @infected = 0 end elsif @infected ==1 #These are animals that have been infected, but in a latent state for one year r1 = rand if r1 < 0.09 @infected = 2 #Stay latent elsif (r1 >= 0.09) and (r1 < 0.99) @infected=3 #Become infectious else @infected = 7 #Dead end elsif @infected == 2 #These have been latent for one year if rand < 0.9 @infected = 4 #become infectious else @infected=7 #die end elsif @infected == 3 #these are infectious if rand < 0.955 @infected = 7 #these are dead else @infected = 5 end elsif @infected >= 4 @infected = 7 end end #Disease status- and age-specific survival curve (Siler model - lx is the survivorship) def survive if @sex == "M" lx1= exp(-0*(1-exp(-9*@ages))-0.329*@ages-0.00017*(exp(2*@ages)-1)) lx2= exp(-0*(1-exp(-9*(@ages+1)))-0.329*(@ages+1)-0.00017*(exp(2*(@ages+1))-1)) sx=lx2/lx1 if @infected ==7 @alive = 0 else if rand>sx @alive = 0 else @alive = 1 end end elsif @sex == "F" lx1= exp(-0.01*(1-exp(-9*@ages))-0.158*@ages-0*(exp(2*@ages)-1)) lx2= exp(-0.01*(1-exp(-9*(@ages+1)))-0.158*(@ages+1)-0.000*(exp(2*(@ages+1))-1)) sx=lx2/lx1 if @infected ==7 @alive = 0 else if rand>sx @alive = 0 else @alive = 1 end end end end #Reproduction curve (age independent above 2, but a function of pop size) def reproduce(n) if @sex == "F" if @ages > 1 if rand>exp(2.5-0.005*n)/(1+exp(2.5-0.005*n)) @mother = 0 else @mother = 1 end else @mother= 0 end else @mother = 0 end end #This ages each animal def age @ages+=1 end end #****************************************************************************** #This is the main portion of the model # Number of time steps t = 50 #Initial pop size males= Population.new(250) {Individual.new("M",1,0,3,0)} females = Population.new(250) {Individual.new("F",1,0,3,0)} n = 500.0 population = [] population = males + females #Here you enter the initial number of infected critters: 4.times {population<1 mums += 1 end } if n < 1000 mult = 2 - 0.0000018*(n**2) babies = mums*mult babies = Integer(babies) end #A new array is created to hold the new babies newBabies = Population.new(babies) {Individual.new("N",1,0,0,0)} #Choose sex newBabies.each { |member| member.chooseSex } #And then is added to the population array population = population + newBabies #Infect critters population.each { |member| member.infect(n,nInfectious) } #Determine if critters are going to die population.each { |member| member.survive } #Delete dead critters population.delete_if{|member| member.alive ==0} #Age critters population.each { |member| member.age } #Count live critters n = 0.0 population.each { |member| if member.alive == 1 n= n+1 end } #Count infected critters nInfected = 0.0 population.each { |member| if member.infected > 1 nInfected = nInfected+1 end } #Count infectious critters nInfectious = 0.0 population.each { |member| if member.infected >= 3 nInfectious = nInfectious+1 end } #Here, the data are put into storage arrays: popSize[i] = n numberInfected[i]=nInfected numberInfectious[i]=nInfectious #Just prints stuff to the screen: #puts "Year no. #{i}" #puts population puts "Time: #{i} Number infectious: #{nInfectious} Number infected: #{nInfected} Population size: #{n}" end #here ends the time loop #Now the data are sent to files results = File.new("results", "w") results.puts popSize results.close infectedResults = File.new("infectedresults", "w") infectedResults.puts numberInfected infectedResults.close infectiousResults = File.new("infectiousresults", "w") infectiousResults.puts numberInfectious infectiousResults.close finalAge = File.new("finalAge", "w") finalAge.puts population finalAge.close puts "--PRESS ENTER TO CONTINUE--" fun = gets #******************************************************************************