# HEADER #################################################### # This is file spam/tests/testthat/test-solve.R. # # It is part of the R package spam, # # --> https://CRAN.R-project.org/package=spam # # --> https://CRAN.R-project.org/package=spam64 # # --> https://git.math.uzh.ch/reinhard.furrer/spam # # by Reinhard Furrer [aut, cre], Florian Gerber [aut], # # Roman Flury [aut], Daniel Gerber [ctb], # # Kaspar Moesinger [ctb] # # HEADER END ################################################ rm(list = ls()) source("helper.R") library("testthat") library("spam", lib.loc = LIB.LOC) context("test-solve.R") # construct spd matrices (should be at least 3x3): n <- 10 set.seed(11) tt <- matrix(rnorm(n*n),n,n) tt <- t(tt) %*% tt tt[tt<0] <- 0 # I have seen that with R version 2.4.0 Patched (2006-11-25 r39997) # on i486-pc-linux-gnu, tt is not symmetric... tt <- tt-(tt-t(tt))/2 ss <- as.spam(tt) css <- chol(ss) ctt <- chol(tt[ordering(css),ordering(css)]) # solving system test_that("'solve' and derivatives", { b <- rnorm(n) spamtest_eq(solve(ss),solve(tt)) spamtest_eq(solve(ss,b),solve(tt,b)) spamtest_eq(t(as.spam(css))%*%as.spam(css), t(ctt)%*%ctt) spamtest_eq(t(as.spam(css))%*%as.spam(css), tt[ordering(css),ordering(css)]) spamtest_eq((t(as.spam(css))%*%as.spam(css))[ordering(css,inv=T),ordering(css,inv=T)], tt) spamtest_eq(backsolve(css,forwardsolve(css,b[ordering(css,inv=T)]))[ordering(css)], backsolve(ctt,forwardsolve(t(ctt),b),n)) #### ,n as patch spamtest_eq(backsolve(css,b[ordering(css,inv=T)])[ordering(css)], backsolve(ctt,b,n)) #### ,n as patch spamtest_eq(forwardsolve(css,b[ordering(css,inv=T)])[ordering(css)], forwardsolve(t(ctt),b)) spamtest_eq(forwardsolve(css,b)[ordering(css)], forwardsolve(t(ctt),b[ordering(css)])) spamtest_eq(forwardsolve(css,tt[ordering(css,inv=T),])[ordering(css),], forwardsolve(t(ctt),tt)) }) test_that("option 'chol.update'", { ss1 <- ss+diag.spam(dim(ss)[1]) spamtest_eq( chol(ss), update.spam.chol.NgPeyton(css, ss)) spamtest_eq( chol(ss, Rstruct=css), update.spam.chol.NgPeyton(css, ss)) sel <- which(ss[1,,drop=TRUE]!=0) ss1[1,sel[-1]] <- 0 ss2 <- ss ss2[n,1] <- .1 options(spam.cholsymmetrycheck=FALSE) spamtest_eq(as.spam(update.spam.chol.NgPeyton(css,ss1)), as.spam( chol(ss1))) spamtest_diff(as.spam(update.spam.chol.NgPeyton(css,ss1)), as.spam( chol(ss2))) }) # spam.options(trivalues=TRUE) # spam.options(trivalues=FALSE) options(spam.cholsymmetrycheck=TRUE) # methods for spam.chol.NgPeyton test_that("'spam.chol.NgPeyton'", { spamtest_eq(as.spam(css), ctt) spamtest_eq(as.matrix(css), as.matrix(ctt)) spamtest_eq(diag(css), diag(ctt)) spamtest_eq(length(css), length(ctt[ctt!=0])) spamtest_eq(dim(css), dim(ctt)) spamtest_eq(c(css), c(ctt)) }) test_that("option 'cholupdatesingular'\n", { ss3 <- spam(rep(1,4),2) ch3 <- chol( ss3+diag.spam(2)) options(spam.cholupdatesingular="null") spamtest_eq(is.null(update(ch3, ss3)),TRUE) options(spam.cholupdatesingular="warning") options(warn=1) expect_warning(update(ch3, ss3), "Singularity problem") options(spam.cholupdatesingular="error") expect_error(update(ch3, ss3), "Singularity problem") options(spam.cholupdatesingular="NULL") expect_error(update(ch3, ss3), "'cholupdatesingular' should be 'error', 'null' or 'warning'") }) # determinants test_that("'det' and derivatives", { spamtest_eq(det(ss),det(tt)) spamtest_eq(det(ss,log=T),det(tt,log=T)) spamtest_eq(determinant(ss)$mod,determinant(tt)$mod) spamtest_eq(determinant(ss,log=F)$mod,determinant(tt,log=F)$mod) spamtest_eq(det(chol(ss)),det(chol(tt))) spamtest_eq(2*sum(log(diag(css))), determinant(tt)$modulus) expect_error(det(spam(1,2,1)), "non-square") # det now gives an error if neg definite! (2.8) expect_error(det(spam(-1)), "not positive definit") # since 2.8: warning when passing arguments to det expect_warning(det(spam(1), pivot=FALSE), "will become defunct in the future") }) # orderings and derivatives test_that("'ordering' and derivatives", { tt5 <- matrix(c( 2,0,2,0,4,0,2,0,3),3) ss5 <- spam( c( 2,0,2,0,4,0,2,0,3),3) spamtest_eq(ordering(tt5),1:3) spamtest_eq(ordering(ss5),1:3) spamtest_eq(ordering(tt5,inv=T),3:1) spamtest_eq(ordering(ss5,inv=T),3:1) spamtest_eq(ordering(chol(ss5)),c(2,3,1)) spamtest_eq(ordering(chol(ss5),inv=T),c(3,1,2)) }) # spam triangular solves test_that("triangular solves", { ## We need to generate a upper triangular matrix first. ctt <- chol(tt) css <- as.spam(ctt) b <- rnorm(nrow(tt)) # a good way to test that we do not use the lower triangular part: ctt[2:10,1] <- NA # Recall: spamtest_eq(backsolve(ctt,forwardsolve(t(ctt),b),n), solve(tt,b)) # Now do testing: spamtest_eq(forwardsolve(t(css),b), forwardsolve(t(ctt),b)) spamtest_eq(forwardsolve(ss,b), forwardsolve(tt,b)) cs <- ss cs[upper.tri(cs)] <- 0 spamtest_eq(forwardsolve( cs ,b), forwardsolve( ss,b)) #### ,n as patch spamtest_eq(backsolve(css,b), backsolve(ctt,b, n)) spamtest_eq(backsolve(ss,b), backsolve(tt,b, n)) spamtest_eq(backsolve(t(cs),b), backsolve(tt,b, n)) spamtest_eq(backsolve(css,forwardsolve(t(css),b)), backsolve(ctt,forwardsolve(t(ctt),b), n)) })