# # fields is a package for analysis of spatial data written for # the R software environment. # Copyright (C) 2022 Colorado School of Mines # 1500 Illinois St., Golden, CO 80401 # Contact: Douglas Nychka, douglasnychka@gmail.edu, # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with the R software environment if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # or see http://www.r-project.org/Licenses/GPL-2 ##END HEADER ##END HEADER # this is a test script to verify the likelihood computations are # correct with the eigen decomposition format used in Krig # see Krig.flplike for the concise computation. # suppressMessages(library(fields)) options( echo=FALSE) test.for.zero.flag<- 1 # utility function foor testing REML.test <- function(x, y, rho, sigma2, theta, nu = 1.5) { Tmatrix <- fields.mkpoly(x, 2) qr.T <- qr(Tmatrix) N <- length(y) Q2 <- qr.yq2(qr.T, diag(1, N)) ys <- t(Q2) %*% y N2 <- length(ys) A <- (rho * Matern(rdist(x, x), range = theta, smoothness = nu) + sigma2 * diag(1, N)) A <- t(Q2) %*% A %*% Q2 Ac <- chol(A) w <- backsolve(Ac, ys, transpose = TRUE) REML.like <- (N2/2) * log(2 * pi) + (1/2) * 2 * sum(log(diag(Ac))) + (1/2) * t(w) %*% w REML.like <- -1 * REML.like ccoef <- rho * Q2 %*% solve(A) %*% ys return(list(REML.like = REML.like, A = A, ccoef = ccoef, quad.form = t(w) %*% w, rhohat = (t(w) %*% w/N2) * rho, det = 2 * sum(log(diag(Ac))), N2 = N2)) } data( ozone2) x<- ozone2$lon.lat y<- ozone2$y[16,] is.good <- !is.na( y) x<- x[is.good,] y<- y[is.good] aRange<- 2.0 # check log likelihood calculation nu<- 1.5 lambda<- .2 out<- mKrig( x,y, aRange=aRange,Covariance="Matern", smoothness=nu, lambda=lambda) # peg sigma and tau as MLEs from mKrig sigma <- out$summary["sigma2"] tau2<- sigma*lambda N<- length( y) dd<- rdist( x,x) M<- sigma* Matern( dd, range= aRange, smoothness=nu) + tau2* diag( 1, N) X<- fields.mkpoly( x, 2) Mi<- solve( M) betahat<- solve(t(X)%*%Mi%*%X)%*% t(X)%*% Mi%*% y res<- y - X%*%betahat ccoef<- ( Mi%*% ( res))*sigma # sanity check that estimates are the same test.for.zero( ccoef, out$c.coef, tag="check ccoef") # find full log likelihood chol(M)-> cM lLike<- -(N/2)*log(2*pi) - (1/2)* (2*sum( log( diag(cM)))) - (1/2)* t(res)%*% Mi %*% res test.for.zero( lLike, out$summary["lnProfileLike.FULL"], tag="llike profile from mKrig") # formula for full likelihood using peices from mKrig # lLike.test<- -(N/2)*log(2*pi) - (1/2)* out$lnDetCov - (1/2)*(N)*log( sigma) - (1/2)*out$quad.form/sigma # test.for.zero( lLike, lLike.test, tag="llike full verses sigmahat") # REML check nu<- 1.5 aRange<- .6 obj<- Krig( x,y, aRange=aRange,Covariance="Matern", smoothness=nu ) # sanity check that c coefficients agree with Krig sigma<- 500 lambda<- .2 tau2<- lambda*sigma hold<- REML.test( x,y,sigma, tau2, aRange, nu=1.5) ccoef2<- Krig.coef( obj, lambda)$c test.for.zero( hold$ccoef, ccoef2, tag="ccoefs") # check RSS with Krig decomposition. RSS1<- sum( (lambda*ccoef2)**2) lD <- obj$matrices$D * lambda RSS2 <- sum(((obj$matrices$u * lD)/(1 + lD))^2) test.for.zero( RSS2, RSS1, tag=" RSS using matrices") # check quadratic form with Krig D.temp<- obj$matrices$D[ obj$matrices$D>0] A3test<- (1/lambda)* obj$matrices$V %*% diag((D.temp*lambda)/ (1 +D.temp*lambda) )%*% t( obj$matrices$V) test.for.zero(solve(A3test), hold$A/sigma, tol=5e-8) Quad3<- sum( D.temp*(obj$matrices$u[obj$matrices$D>0])^2/(1+lambda*D.temp)) test.for.zero( hold$quad.form, Quad3/sigma, tag="quad form") # test determinants N2<- length( D.temp) det4<- -sum( log(D.temp/(1 + D.temp*lambda)) ) det1<- sum( log(eigen( hold$A/sigma)$values)) test.for.zero( det1, det4, tag="det" ) # test REML Likelihood lLikeREML.test<--1*( (N2/2)*log(2*pi) - (1/2)*(sum( log(D.temp/(1 + D.temp*lambda)) ) - N2*log(sigma)) + (1/2)*sum( lD*(obj$matrices$u)^2/(1+lD)) /(lambda*sigma) ) test.for.zero( hold$REML.like, lLikeREML.test, tag="REML using matrices") cat("all done with likelihood tests", fill=TRUE) options( echo=TRUE)