#Script for comparing FGN/ARMA forecast performance
#This script requires a Beowulf cluster computer with Rmpi library
#attach library
library(FGN)
#input data
data(NileMin)
y<-NileMin
#ARMA(p,q) model order
p<-2
q<-1
#
nB<-10^4 #Number of bootstrap iterations
n<-length(y) #length of series
K<-100 #number of out-of-sample data values
n1<-n-K #length of training series
sdy<-sd(y) #sd of original series
#syd is the long-run prediction sd
outy<-FitFGN(y) #fix model for bootstrap
#
#combine all into together except outy,
inputdata=c(p,q,n,K)
onebootFGNARMA=function(outy,inputdata){
MAXIT <- 10
p <- inputdata[1]
q <- inputdata[2]
n <- inputdata[3]
K <- inputdata[4]
n1=n-K
#
#FGN fit to z1 and forecast using z2.
#FGN and ARMA use independent bootstraps
NotOK <- TRUE
ITER<-0
while (NotOK && ITER<MAXIT){
z<-Boot(outy)
z1<-z[1:n1] #training data
z2<-z[-(1:n1)] #testing data
outz1<-tryCatch(FitFGN(z1), error = function(e) FALSE)
if (!(is.logical(outz1))) NotOK <- FALSE
else ITER<-ITER+1
}
H<-outz1$H
mu<-outz1$muHat
rFGN<-var(z1)*FGNAcf(0:(n+3-1), H)
F<-TrenchForecast(c(z1,z2), rFGN, mu, n1, maxLead=3)$Forecasts
nF<-nrow(F)
err1<-z2-F[,1][-nF]
err2<-z2[-1]-F[,2][-c(nF,(nF-1))]
err3<-z2[-c(1,2)]-F[,3][-c(nF,(nF-1),(nF-2))]
rmse1<-sqrt(mean(err1^2))
rmse2<-sqrt(mean(err2^2))
rmse3<-sqrt(mean(err3^2))
FGNrmse<-c(ITER,rmse1,rmse2,rmse3)
#
#ARMA(p,q) fit to z1 and forecast using z2
NotOK <- TRUE
ITER<-0
while (NotOK && ITER<MAXIT){
z<-Boot(outy)
z1<-z[1:n1] #training data
z2<-z[-(1:n1)] #testing data
outz1<-tryCatch(arima(z1,c(p,0,q)), error = function(e) FALSE)
if (!(is.logical(outz1))) NotOK <- FALSE
else ITER<-ITER+1
}
z1<-z[1:n1] #training data
z2<-z[-(1:n1)] #testing data
phi<-theta<-numeric(0)
if (p>0) phi<-coef(ansz1)[1:p]
if (q>0) theta<-coef(ansz1)[(p+1):(p+q)]
zm<-coef(ansz1)[p+q+1]
sigma2<-ansz1$sigma2
r<-var(z)*ARMAacf(ar=phi, ma=theta, lag.max=n+3-1)
F<-TrenchForecast(c(z1,z2), r, zm, n1, maxLead=3)$Forecasts
err1<-z2-F[,1][-nF]
err2<-z2[-1]-F[,2][-c(nF,(nF-1))]
err3<-z2[-c(1,2)]-F[,3][-c(nF,(nF-1),(nF-2))]
rmse1<-sqrt(mean(err1^2))
rmse2<-sqrt(mean(err2^2))
rmse3<-sqrt(mean(err3^2))
ARMArmse<-c(ITER, rmse1, rmse2, rmse3)
#Average mse
c(FGNrmse, ARMArmse)
}
####################################################
#start Rmpi and setup R slaves
library(Rmpi)
#setup slaves
mpi.spawn.Rslaves()
#send data and function to all slaves
mpi.bcast.Robj2slave(inputdata)
mpi.bcast.Robj2slave(outy)
mpi.bcast.Robj2slave(onebootFGNARMA)
#tell slaves to load FGN
mpi.bcast.cmd(library(FGN))
#setup parallel RNG. seed can be specified.
mpi.setup.rngstream(19000713)
startTime<-proc.time()
#start parallel bootstrap
out <- mpi.parReplicate(nB, onebootFGNARMA(outy=outy,inputdata=inputdata))
failed<-apply(out[c(1,5),], 1, sum)
averRMSE=apply(out[-c(1,5),], 1, mean)
endTime<-proc.time()
totalTime<-endTime-startTime
totalTime<-(totalTime/3600)[3]
#
#tabulate result
tb<-matrix(c(averRMSE[1:3],sdy,failed[1],averRMSE[4:6],sdy,failed[2]),ncol=2)
dimnames(tb)<-list(c("lead1","lead2","lead3","infty","failed"),c("FGN","ARMA"))
#
#output and close R
save(tb, out, totalTime, file="tbBoot.Rdata") #
write(totalTime, "totalTimeMPI.txt")
write(t(round(tb,3)), file="tbMPI.txt", ncolumns=2)
print(paste("Elapsed Time = ", totalTime , "Hours"))
print(paste("nB = ",nB))
print(tb)
#close all slaves and quit
mpi.close.Rslaves()
mpi.quit()