
# file "RMH" -- a Metropolis-Hastings algorithm

# Proposal distribution: MVN(X_{n-1}, sigma^2 (1+|X_{n-1}|^2) I)

g = function(x) {
    if ( (x[1]<0) || (x[1]>5) || (x[2]<0) || (x[2]>4) )
	return(0)
    else
	return( abs( cos(sqrt(x[1]*x[2])) ) )
}

h = function(x) { return( exp(x[1]) + x[2]^2 ) }

qq = function(x,y) {
    return( 1/(1+sum(x^2))^2 *
		exp( - sum((y-x)^2) / ( 2 * sigma^2 * (1+sum(x^2))^2 ) ) )
}

M = 5000  # run length
B = 100  # amount of burn-in
X = c(5*runif(1),4*runif(1))  # overdispersed starting distribution (dim=2)
sigma = 0.1  # proposal scaling
x1list = x2list = hlist = rep(0,M)  # for keeping track of values

for (i in 1:M) {
    Y = X + sigma * (1 + sum(X^2)) * rnorm(2)  # proposal value (dim=2)
    U = runif(1)  # for accept/reject
    alpha = ( g(Y) * qq(Y,X) ) / ( g(X) * qq(X,Y) )   # for accept/reject
    if (U < alpha)
	X = Y  # accept proposal
    x1list[i] = X[1]
    x2list[i] = X[2]
    hlist[i] = h(X)
}

cat("mean of h is about", mean(hlist[(B+1):M]), "\n")

# plot(x1list, x2list, type='l')
# plot(x1list, type='l')
# plot(x2list, type='l')
# plot(hlist, type='l')

se1 =  sd(hlist[(B+1):M]) / sqrt(M-B)
cat("iid standard error would be about", se1, "\n")

# acf(x1list)

varfact <- function(xxx) { 2 * sum(acf(xxx, plot=FALSE)$acf) - 1 }
cat("true standard error is about", se1 * sqrt( varfact(hlist[(B+1):M]) ), "\n")

