Search code examples
rrandom-walk

How do I put arena limits on a random walk?


I'm building a biased correlated random walk, and I've managed to build the RW, and bias it for westerly movement.

The issue: I need the walk to be bound on one (or all) side(s).

The current code is:

walk<-function(n.times){ 
   plot(524058:542800,2799758:2818500,type="n",
      xlab="Easting",ylab="Northing")#aren‌​a 
      y<-2815550 ##startY 
      x<-542800 #startX
      N<-4000
      E<-4000
      points(x,y,pch=16,col="red",cex=1)
      for (i in 1:n.times) {
          yi <- sample(c(N,N/2,N/4,N/8,N/12,N/16,
                      0,-N,-N/2,-N/4,-N/8,-N/12,-N/16),1)      
          xi<-sample(c(E,E/12,E/16, 0,-E,-E/2,-E/4,-E/8,-E/12,-E/16),1)       
          lines(c(x,x+xi),c(y,y+yi),col="blue")
          x<-x+xi
          y<-y+yi 
      }
   }
   iterations<-125 
   walk(iterations) 

So far the closest I've come is using

 if(y>2818500 | y<2799758 | x>542800 | x<524058)  break 

which simply stops the walk if it leaves the arena.


Solution

  • A slightly cleaned-up version of the function: the primary change is the addition of a repeat {} loop that will re-pick the step until the new location is within the limits (could also use a while() {} loop).

    update: didn't read the problem statement carefully enough, forgot the bias. This code incorporates the bias in the same way that the OP's code does. For N-S movement the mean step length is 0; for the E-W movement, by leaving out some of the positive step possibilities, we get mean(steps.x) equal to -0.0875; since the step possibilities are uniformly sampled, the walk drifts to the left by an average of 0.0875*stepsize[1] units per step.

     walk <- function(n.times=125,
                   xlim=c(524058,542800),
                   ylim=c(2799758,2818500),
                   start=c(542800,2815550),
                   stepsize=c(4000,4000)) {
        ## blank plot of arena
        plot(c(0,0),type="n",xlim=xlim,ylim=ylim,
               xlab="Easting",ylab="Northing") 
        ## extract starting point
        x <- start[1]
        y <- start[2]
        ## define potential step sizes
        steps <- 1/c(1,2,4,8,12,16)
        ## all possible positive or negative steps for N-S movement
        steps.y <- c(steps,-steps,0)
        ## bias E-W movement by leaving out some positive steps
        steps.x <- c(steps[c(1,5,6)],-steps,0)
        ## plot starting location
        points(x,y,pch=16,col="red",cex=1)
        for (i in 1:n.times) {
            repeat {
               ## pick jump sizes
               xi <- stepsize[1]*sample(steps.x,1)
               yi <- stepsize[2]*sample(steps.y,1)
               ## new candidate locations
               newx <- x+xi
               newy <- y+yi
               ## IF new locations are within bounds, then
               ##    break out of the repeat{} loop (otherwise
               ##    try again)
               if (newx>xlim[1] && newx<xlim[2] &&
                   newy>ylim[1] && newy<ylim[2]) break
            }
            lines(c(x,newx),c(y,newy),col="blue") ## draw move
            ## set new location to candidate location
            x <- newx
            y <- newy
        }
    }
    set.seed(101)
    walk(1000)
    

    enter image description here