library(rmarkdown)
library(knitr)
set.seed(33)
Populations are always changing. Sometimes changes are the result of humans interfering with food webs or habitats. But even when humans do not interfere, populations will still naturally shift up and down or fluctuate. As an example, consider the interactive system of snowshoe hare and Canada lynx. Data collected by the Hudson Bay Company since the 1700s shows a regular history of cyclical population booms and busts in the snowshoe hare population and a slightly delayed population boom and bust in the lynx population. One theory that has been proposed to descibe this cyclical is that the lynx population determines the hare population. As the number of hares increases, so does the numbers of lynx that survive to eat them. Soon, there are too many lynx for the number of hares and the lynx eat away their favorite food until they too suffer a population decline until the hare population can start growing again.
Use function() to construct a function and assign it to the object hareLynx. This function should have the following attributes and perform the following computations:
(1) Take in as arguments the objects hareSpeed, lynxSpeed, hareStarting,
lynxStarting, timeSteps, gridSize, and displayImage with default values of
0.XX, 0.XX, XXX, XXX, and TRUE, respectively
(2) Initialize a blank data frame with a number of rows equal to timeStpes and
2 columns with the names "Hares" and "Lynx" and assign it to the object
totalAnimals
(3) Initialize a blank data frame with a number of rows equal to the sum of
hareStarting and lynxStarting, and 4 columns with the names "Status",
"Species", "Row", and "Column" and assign it to the object animalData
(4) Set the first hareStarting values in animalData$Species to 1 (representing
hares) and the last lynxStarting values in animalData$Species to 2
(representing lynx)
(5) Set all values in animalData$Status to 1 (representing that the animal is
alive)
(6) Use sample() to assign a random row and a random column to each individual
in animalData such that no two hares and no two lynx share the same cell
(7) Initialize one blank matrices with gridSize rows and gridSize columns and
assign it to the object latticeImage
(8) Use for() to construct a loop that will repeat the following computations
timeSteps times:
(a) Set all values in latticeImage to 0
(b) Use for() to construct a for loop that will cycle through every
individual in animalData and perform the following computations for
each individual:
(i) Use if() to determine if the individual is alive and if it is
a lynx; if it is, perform the following:
(A) Use if() and runif() to determine if the lynx should
attempt to move to a neighboring cells based on lynxSpeed
(B) If the lynx should attempt to move, use sample() to pick
one of the four neighboring cells for the lynx to attempt
to move into
(C) Use if() to determine if that cell is already occupied by
another lynx
(D) If that cell is unoccupied, move the lynx into that cell
by updating the lynx's Row and Column location in
animalData
(ii) Use if() to determine if the individual is alive and if it is
a hare; if it is, perform the following:
(A) Use if() and runif() to determine if the hare should
attempt to move to a neighboring cells based on hareSpeed
(B) If the hare should attempt to move, use sample() to pick
one of the four neighboring cells for the hare to attempt
to move into
(C) Use if() to determine if that cell is already occupied by
by another hare
(D) If that cell is unoccupied, move the hare into that cell
by updating the hare's Row and Column location in
animalData
(E) Use if() to determine if the hare's new location is
already occupied by a lynx
(F) If the hare's new location is already occupied by a lynx,
set the hare's Status to 0 (representing that the hare has
been eaten by the lynx and is now dead)
(c) Use for() to construct a for loop that will cycle through every
individual in animalData and assign their Animal value (1 for hare
and 2 for lynx) to the corresponding cell in latticeImage, assuming
that they are alive
(d) Use if() to determine if the argument displayImage is equal to TRUE;
if it is, use image(t(latticeImage), col = c("gray", "green", "red"))
to display latticeImage and Sys.sleep(0.25) to pause the loop before
continuing to its next iteration
(e) Use sum() to calculate the total number of alive hares and lynx in
animalData and assign them to the corresponding row in totalAnimals
(9) Use return() to return totalTrees once the function is complete
Hint 1: Neither hares nor lynx can move beyond the boundaries of the lattice -
the function if() will come in handy to determine if not all 4 nearest
neighbors should be checked when determining movements for each animal
Hint 2: It will help to run segments of the code individually (which should not
be knitted) before combining everything into a single function
hareLynx<- function(hareSpeed=0.75,lynxSpeed=0.75,hareStarting=10, lynxStarting=3, timeSteps=20, gridSize=10, displayImage=TRUE) {
#initialize data frame
totalAnimals<-data.frame(Hares=c(rep(NA,timeSteps)) ,Lynx=c(rep(NA,timeSteps)))
animalData<-data.frame(Status=c(rep(NA,hareStarting+lynxStarting)),Species=c(rep(NA,hareStarting+lynxStarting)),
Row=c(rep(NA,hareStarting+lynxStarting)),Column=c(rep(NA,hareStarting+lynxStarting)))
animalData$Species[c(1:hareStarting)]<-1
animalData$Species[c((hareStarting+1):(hareStarting+lynxStarting))]<-2
animalData$Status<-1
#assigning rows and columns to animals
animalData$Row[c(1:hareStarting)]<-sample(c(1:gridSize),hareStarting)
animalData$Column[c(1:hareStarting)]<-sample(c(1:gridSize),(hareStarting))
animalData$Row[c((hareStarting+1):(hareStarting+lynxStarting))]<-sample(c(1:gridSize),(lynxStarting))
animalData$Column[c((hareStarting+1):(hareStarting+lynxStarting))]<-sample(c(1:gridSize),(lynxStarting))
latticeImage<-matrix(nrow = gridSize ,ncol = gridSize)
for(i in 1:timeSteps){
#set image to all 0s
latticeImage[,]<-0
for(j in 1:(hareStarting+lynxStarting)){
#if alive and lynx
if(animalData$Status[j]==1 & animalData$Species[j]==2){
if (runif(1) < lynxSpeed) {
#where is it going rows.
if(animalData$Row[j]>1 & animalData$Row[j]< gridSize){
possiblerow<-((sample(c(-1,1),1)) + animalData$Row[j])
}
if(animalData$Row[j]==1){
possiblerow<-((sample(c(1),1)) + animalData$Row[j])
}
if(animalData$Row[j]==gridSize){
possiblerow<-((sample(c(-1),1)) + animalData$Row[j])
}
#where is it going cols.
if(animalData$Column[j]>1& animalData$Column[j]< gridSize){
possiblecol<-((sample(c(-1,1),1)) + animalData$Column[j])
}
if(animalData$Column[j]==1){
possiblecol<-((sample(c(1),1)) + animalData$Column[j])
}
if(animalData$Column[j]==gridSize){
possiblecol<-((sample(c(-1),1)) + animalData$Column[j])
}
pick<-sample(c("row","col"),1)
if(pick=="row"){
if(any(animalData$Row==possiblerow & animalData$Column==animalData$Column[j] & animalData$Species==2)){
} else{
animalData$Row[j]<-possiblerow}}
if(pick=="col"){
if(any(animalData$Row==animalData$Row[j] & animalData$Column==possiblecol & animalData$Species==2)){
} else{
animalData$Column[j]<-possiblecol
}}
}}
#if alive and hare
if(animalData$Status[j]==1 & animalData$Species[j]==1){
if (runif(1) < hareSpeed) {
#where is it going rows.
if(animalData$Row[j]>1 & animalData$Row[j]< gridSize){
possiblerow<-((sample(c(-1,1),1)) + animalData$Row[j])
}
if(animalData$Row[j]==1){
possiblerow<-((sample(c(1),1)) + animalData$Row[j])
}
if(animalData$Row[j]==gridSize){
possiblerow<-((sample(c(-1),1)) + animalData$Row[j])
}
#where is it going cols.
if(animalData$Column[j]>1& animalData$Column[j]< gridSize){
possiblecol<-((sample(c(-1,1),1)) + animalData$Column[j])
}
if(animalData$Column[j]==1){
possiblecol<-((sample(c(1),1)) + animalData$Column[j])
}
if(animalData$Column[j]==gridSize){
possiblecol<-((sample(c(-1),1)) + animalData$Column[j])
}
pick2<-sample(c("row","col"),1)
if(pick2=="row"){
if(any(animalData$Row==possiblerow & animalData$Column==animalData$Column[j] & animalData$Species==2)){
} else{
animalData$Row[j]<-possiblerow}}
if(pick2=="col"){
if(any(animalData$Row==animalData$Row[j] & animalData$Column==possiblecol & animalData$Species==2)){
} else{
animalData$Column[j]<-possiblecol
}}
}
if(any(animalData$Row==animalData$Row[j] & animalData$Column==animalData$Column[j] & animalData$Species==2)){
animalData$Status[j]<-0
}
}}
for(r in 1:(hareStarting+ lynxStarting)){
if(animalData$Status[r]==1){
latticeImage[animalData$Row[r],animalData$Column[r]]<-animalData$Species[r]
}
}
if(displayImage==TRUE){
image(t(latticeImage), col = c("gray", "green", "red"))
Sys.sleep(0.25)
}
totalAnimals$Hares[i]<- sum(animalData$Species==1 & animalData$Status==1)
totalAnimals$Lynx[i]<-sum(animalData$Species==2 & animalData$Status==1)
}
return(totalAnimals)
}