Random walks are, well, very random. At any point in time, they can chose to take a step to the left, to the right, front or back.
The path of somebody walking a random walk of a 5000 steps on a plane looks like this, with the starting point being the blue dot, and the end of the path being the red dot:
Pretty chaotic.
But when you let them, these random walks will actually create beautiful, structured, patterns for you.
The code below is inspired by a book of Mark Buchanan, called Ubiquity. In this book it is shown that random events are not necessarily just the unstructured, chaotic, drunken trails, but can pretty amazingly lead to structured, beautiful patterns. This is officially called: “Diffusion-limited aggregation”.
What it is, step by step:
When about eight thousand particles have found each other this way, the result is quite striking:
To show how this image was generated, some code below:
nr <- 400; # even number of rows
nc <- 400; # even number of columns
n <- 10000; # number of random walk steps
count = 0; # needed for border seed setting
firstwalk = 1; # needed to calculate random walks
for(i in 1:10) {
# ---- create random walk starting at the origin of the matrix [0,0]
x <- cumsum(sample(c(-1, 0, 1), n, TRUE))
y <- cumsum(sample(c(-1, 0, 1), n, TRUE))
# Is this the first walk?
if(firstwalk==1){
# randomly choose boundary point to start from
if (count %% 4 == 0) {xs <- floor(runif(1,1,nr)); ys <- 0}
if (count %% 4 == 1) {ys <- floor(runif(1,1,nc)); xs <- 0}
if (count %% 4 == 2) {xs <- floor(runif(1,1,nr)); ys <- nc}
if (count %% 4 == 3) {ys <- floor(runif(1,1,nr)); xs <- nr}
} else {
xs = rw[length(x),][1]; #last x coor of the previous rw
ys = rw[length(x),][2]; #last y coor of the previous rw
}
x <- x+xs
y <- y+ys
# ---- Set random walk boundaries to stay confined within matrix
for(i in 1:n){
if (x[i] < 0) {x[i:n] <- x[i:n]+1}
if (x[i] > nr) {x[i:n] <- x[i:n]-1}
if (y[i] < 0) {y[i:n] <- y[i:n]+1}
if (y[i] > nc) {y[i:n] <- y[i:n]-1}
}
# ---- random walk array:
rw <- unname(cbind(x,y));
# ---- detect when random walk hits a point of value 1 in m
s <- unname(which(m==1, arr.ind=TRUE))
sp <- paste0(s[,1],".",s[,2]);
rwp <- paste0(rw[,1],".",rw[,2]);
hit <- which(rwp%in%sp,arr.ind = TRUE)[1] # get first hit
# act if there is a hit:
if (!is.na(hit)) {
# set value = 1 at location of last step of rw prior to hitting
m[rw[hit-1,1],rw[hit-1,2]] = 1;
firstwalk = 1;
count <- count + 1;
cat("Hit number:", count, "\n")
} else {
# no hit: do another walk starting at end of this one
firstwalk = 0;
}
# Show the random walks real time:
par(mar=c(10,10,2,2))
plot(x,y,xlim=c(0,nr),ylim=c(0,nc),type="l")
points(x[1],y[1],"pch"=19,col = "blue") #begin point
points(x[length(x)],y[length(y)],"pch"=19,col = "red") #end point
points(s,"pch"=".",col = "gray") #matrix m values 1
} # end of for loop
## Hit number: 1
## Hit number: 2
## Hit number: 3
The current day and time is Tue Mar 07 11:07:45 2017