STAT 360 Lab 21: Agent-Based Simulations (Part 1)

Name: Regina

Set Up Work Space

Load R Libraries

library(rmarkdown)
library(knitr)

Set the Seed

set.seed(33)

The Snowshoe Hare and Canada Lynx System

Background:

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.

Constructing the hareLynx Function

Exercise 1:

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)  
   
  }