Introductory Activity:
Review the code you wrote last time and decide what you need to finish today.
The following is a good goal for the end of today. Results from the simulation are found below the code.
Moose Class:
class Moose {
var mooseAgeMaturity = 5 // age a moose needs to be to reproduce
var mooseLongevityAge = 100 // number of years a moose will live naturally
var age = 0
var alive = true // moose is alive or dead
var vegetationNeededToSurvive = 0.01 // each moose needs to eat 1% worth of the islands vegetation per year
var mooseBirthRate = 0.75 // each moose will create 0.75 moose each year once it’s old enough to mate
var starvation = 0
var environment: Environment
init(in environment: Environment, age: Int) {
mooseAgeMaturity = 5
let deltaLife = Int.random(in: -6 ... 6) // randomize the longevity of a moose - simulation not very sensitive to this feature
mooseLongevityAge = 20 + deltaLife
self.age = age
alive = true
vegetationNeededToSurvive = 0.002 // fraction of the region's vegetation a single moose eats per year
mooseBirthRate = 0.75 // fraction of a moose another moose gives birth to, assuming it is mature enough
starvation = 0 // counter to keep track of how many years a moose has gone without sufficient food
self.environment = environment
}
func canEat() -> Bool {
// current vegetation cover in the region is a fraction from 0.0 to 1.0
// randomize the probability that a moose finds itself in the vegetated fraction of the region and can eat sufficiently for a year
let randomNumber = Double.random(in: 0.0 ... 1.0)
if randomNumber > environment.vegCover {
return false
}
return true
}
func liveForYear() {
// If a moose doesn’t find food for two years in a row, it dies
// If a moose survives until mooseLongevityAge, it dies
if canEat() {
age += 1
environment.vegCover -= vegetationNeededToSurvive
} else {
starvation += 1
}
if starvation >= 2 { alive = false }
if age >= mooseLongevityAge { alive = false }
}
}
Environment Class:
class Environment {
var vegCover = 1.0
let vegatationRegrowthRate = 0.1 // rate at which vegetation regrows each year
var mooseArray = [Moose]() // create an empty array of moose
func updateVegetation() {
// grow vegetation cover for a year
vegCover += vegatationRegrowthRate
if vegCover > 1.0 { vegCover = 1.0 }
}
// update simulation population
func updateMoosePopulation() {
var newMooseArray = [Moose]()
var newMooseBabies = 0.0
// check and see if there are any dead moose, of so, remove them from the mooseArray
for i in mooseArray.indices {
let thisMoose = mooseArray[i]
// each moose experiences a year
thisMoose.liveForYear()
// determine how many new moose will be born this year
if thisMoose.alive {
newMooseArray.append(thisMoose)
if thisMoose.age >= thisMoose.mooseAgeMaturity {
newMooseBabies += thisMoose.mooseBirthRate
}
}
}
// have moose reproduce
let numberOfBabies = Int(newMooseBabies)
// add new moose babies to the herd
for _ in 0 ..< numberOfBabies {
newMooseArray.append(Moose(in: self, age: 0))
}
mooseArray = newMooseArray
}
}
Simulation Class:
class Simulation {
let numberOfInitialMoose = 80
let simulationLength = 1000 // number of years for the simulation
var year = 0 // year of the simulation
var environment = Environment()
var numberOfMooseInSimulation: Int { // a computed property that return the current number of moose in herd
return environment.mooseArray.count
}
init() { // initialize the simulation
environment = Environment()
for _ in 0 ..< numberOfInitialMoose {
let initialAge = Int.random(in: 1 ... 30)
environment.mooseArray.append(Moose(in: environment, age: initialAge))
}
}
// Simulation of Isle Royale Moose
func simulateYear() {
environment.updateVegetation()
environment.updateMoosePopulation()
}
func runSimulation() {
for year in 0 ..< simulationLength {
simulateYear()
print("\(year), \(numberOfMooseInSimulation), \(environment.vegCover * 100.0)")
}
}
}
Main Program:
The main program is short and sweet. Create a single instance of the Simulation class and call the runSimulation method on the instance.
var sim001 = Simulation()
sim001.runSimulation()
Simulation Results:
Summary Activity:
Discuss the results of the 1000-year simulation:
Questions:
- How realistic is the model?
- Does the model match the observations in any ways (not enough moose; ~25 cycle of moose population expansion and decay)
- Ideas on how we can make the simulation match observations more accurately (decrease amount moose eats per year? increase moose birth rates? increase vegetation growth rates
Homework?
What kinds of systematic experiments would you like to run with our model?
Spend the last 5 minutes dividing up simulation experiments for each student to perform. Use the questions above to guide the experiments. Have the students write clear hypotheses before leaving class and performing the experiments.