# Random Walk Metropolis algorithm for MacKay's (2003, Fig. 29.12) 'toy' problem
# MacKay wants "to illustrate how slowly a random walk explores a state space"(p.369)
# R-Code by PCM 2016/02/10
library(lattice)
## Warning: package 'lattice' was built under R version 3.2.3
linear_density_graph <- function(r=-0.5, s=20.5) {
# uniform density, MacKay, p.369
curve((x-x+1)*(1/21), from=r, to=s, type="l", xlab="x", ylab="f(x)", lwd=3,
main="Uniform Proposal Density p(x) = 1/21", col="steelblue")
# vertical lines from (xi1, yi1=0) to (xi2, yi2=1/21)
for(i in r:s) {lines(c(i,i),c(0,1/21),type="l",col="steelblue",lwd=1)}
legend(x=2,y=0.15, legend="area under density f(x) is 1 ")
}
linear_density_graph()

P <- function(x) # uniform target pmf P(x) (29.33)
{if (x %in% c(0:20)) 1.0/21.0 else 0}
flip <- function(p=0.5) rbinom(1,1,p) # one Bernoulli trial (inspired by WebChurch)
rQ <- function(x) # proposal function
{x + flip()*2-1} # rQ ~ Q(xp | x) (29.34)
pQ <- function(xp,x) # proposal density
{if(abs(xp-x)==1) 0.5 else 0} # pQ(xp,x) = Q(rQ | x) (29.34)
# lower bound on number of iterations of a Metropolis method (29.32)
T <- function(len, eps) (len/eps)^2 # MacKay's "Rule-of-Thumb", 2003, p.367
cat("\nRandom walk Metropolis-Hastings (MH) algorithm, MacKay, 2003, Fig.29.12\n")
##
## Random walk Metropolis-Hastings (MH) algorithm, MacKay, 2003, Fig.29.12
cat(" R-Code by PCM 2016/02/10\n")
## R-Code by PCM 2016/02/10
nt <- 480000 # total nr of steps
nthin <- 300 # thin-factor
maxsteps <- 100000 # max MH-steps for trace-plot
cat("total number of MH-steps = ", nt)
## total number of MH-steps = 480000
T_est <- T(20,1)
print(sprintf("MacKay's rule of thumb %f iterations for one independent sample", T_est))
## [1] "MacKay's rule of thumb 400.000000 iterations for one independent sample"
print(sprintf("MacKay's rule of thumb %f independent samples within total of %i samples", nt/T_est, nt))
## [1] "MacKay's rule of thumb 1200.000000 independent samples within total of 480000 samples"
steps <- c(1:nt) # abcissa in plot
flips <- matrix(0,nt)
for(i in 1:nt) {flips[i] <- flip()} # Bernouilli trials
hist(flips,breaks=seq(-0.5,1.5,1),main="Distribution of Steps (left = -1 and right = +1)",col="steelblue")

x <- matrix(10,nt) # states x[t]; start state x[1] = 10
xpt <- matrix(0,nt) # proposals xp[t] = x'[t]
importance_ratio <- matrix(0,nt) # initials
proposal_ratio <- matrix(0,nt) # initials
alpha <- matrix(0,nt) # initial alpha
accept <- matrix(0,nt) # initially no acceptance
p_acc <- matrix(0,nt) # initial P(acceptance)
#
# MH-loop
#
for (t in 1:nt) {
xt <- x[t]
xp <- rQ(xt) # xp = x' = proposal
xpt[t] <- xp
importance_ratio[t] <- P(xp)/P(xt)
proposal_ratio[t] <- pQ(xp,xt)/pQ(xt,xp)
alpha[t] <- importance_ratio[t]/proposal_ratio[t]
p_acc[t] <- min(1, alpha[t]) # P(Acceptance)
x[t+1] <-
if(flip(p_acc[t]) == TRUE)
{accept[t] <- 1; xp; } # accept ...
else x[t] # ... or reject proposal xp = x'
}
if(nt <= maxsteps) plot(steps,xpt,type="l",col="steelblue",main="Random walk MH: trace of proposals xp (MacKay, p.368)")
hist(xpt,main=sprintf("Distribution of %i proposed states xp",nt),breaks=c(-2.5:22.5),col="steelblue")

if(nt <= maxsteps) plot(steps,x[-(nt+1)],type="l",main="Random walk MH: trace of states x (MacKay, p.368)",col="steelblue")
hist(x,main=sprintf("Distribution of States (%i samples)",nt),breaks=c(-0.5:20.5),col="steelblue")

acf(x,lag.max=min(nt*.10,1000),main="ACF(x)", col="steelblue")

if(nt <= maxsteps) plot(steps,importance_ratio,type="l",main="Trace: importance_ratio[t] <- P(xp) / P(xt)",col="steelblue")
if(nt <= maxsteps) densityplot(importance_ratio,main="Density plot: importance_ratio[t] <- P(xp) / P(xt)",col="steelblue",lwd=2)
if(nt <= maxsteps) plot(steps,proposal_ratio,type="l",main="Trace: proposal_ratio[t] <- pQ(xp,xt) / pQ(xt,xp)",col="steelblue")
if(nt <= maxsteps) densityplot(proposal_ratio,main="Density plot: proposal_ratio[t] <- pQ(xp,xt) / pQ(xt,xp)",col="steelblue",lwd=2)
if(nt <= maxsteps) plot(steps,alpha,type="l",main="Trace: alpha <- importance_ratio / proposal_ratio",col="steelblue")
if(nt <= maxsteps) densityplot(alpha,main="Density plot: alpha <- importance_ratio / proposal_ratio",col="steelblue",lwd=2)
if(nt <= maxsteps) plot(steps,p_acc,type="l",main="Trace: P(Acceptance) <- min(1,alpha)",col="steelblue")
percentage_of_acceptance <- mean(accept)*100.0
acceptance_rate <- mean(p_acc[])
if(nt <= maxsteps) legend(x=0,y=0.4,legend=sprintf("PercentageOfTotalAcceptance = %f",percentage_of_acceptance))
if(nt <= maxsteps) legend(x=0,y=0.2,legend=sprintf("Acceptance Rate = %f",acceptance_rate))
if(nt <= maxsteps) densityplot(p_acc,main="Density plot: P(Acceptance) <- min(1,alpha)",col="steelblue",lwd=2)
print(sprintf("Percentage of acceptance = %f", percentage_of_acceptance))
## [1] "Percentage of acceptance = 95.310000"
print(sprintf("acceptance-rate = %f", acceptance_rate))
## [1] "acceptance-rate = 0.953100"
# excluding samples by thinning
nthinned <- round(nt/nthin)
print(sprintf("Number of samples (after thinning) = %i", nthinned))
## [1] "Number of samples (after thinning) = 1600"
x <- x[seq(from=1,to=nt,by=nthin)]
accept <- accept[seq(from=1,to=nt,by=nthin)]
p_acc <- p_acc[seq(from=1,to=nt,by=nthin)]
print(sprintf("Percentage(AcceptanceDecisions) = %f (Thinned)", mean(accept)*100.0))
## [1] "Percentage(AcceptanceDecisions) = 95.562500 (Thinned)"
print(sprintf("AcceptanceRate = %f (Thinned)", mean(p_acc)))
## [1] "AcceptanceRate = 0.955625 (Thinned)"
if(nt <= maxsteps) plot(x, type="l", main="MH-Trace for x (Thinned)", col="steelblue")
hist(x,main=sprintf("Distribution of (thinned) States (%i samples)",nthinned),breaks=c(-0.5:20.5),col="steelblue")

acf(x, main="ACF(m) (Thinned)")

x_est <- mean(x)
sdx_est <- sd(x)
print(sprintf("mean(x) = %f (Thinned)", x_est))
## [1] "mean(x) = 9.790625 (Thinned)"
print(sprintf("sd(x) = %f (Thinned)", sdx_est))
## [1] "sd(x) = 6.032685 (Thinned)"
#