Rev 5017 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
#### Currently a collection of simple tests## (since 'Matrix' takes long to load, rather have fewer source files!)library(Matrix)source(system.file("test-tools.R", package = "Matrix"))# identical3() etcoptions(verbose = TRUE)# to show message()s### Matrix() ''smartness''(d4 <- Matrix(diag(4)))(z4 <- Matrix(0*diag(4)))(o4 <- Matrix(1+diag(4)))(tr <- Matrix(cbind(1,0:1)))(m4 <- Matrix(cbind(0,rbind(6*diag(3),0))))dm4 <- Matrix(m4, sparse = FALSE)class(mN <- Matrix(NA, 3,4)) # NA *is* logicalstopifnot(validObject(d4), validObject(z4), validObject(o4),validObject(m4), validObject(dm4), validObject(mN))assert.EQ.mat(dm4, as(m4, "matrix"))assert.EQ.mat(mN, matrix(NA, 3,4))sL <- Matrix(, 3,4, sparse=TRUE)# -> "lgC"trS <- Matrix(tr, sparse=TRUE)# failed in 0.9975-11stopifnot(isValid(d4, "diagonalMatrix"), isValid(z4, "diagonalMatrix"),isValid(tr, "triangularMatrix"), isValid(trS, "triangularMatrix"),all(is.na(sL@x)), ## not yet: all(is.na(sL)),!any(sL, na.rm=TRUE), all(!sL, na.rm=TRUE),validObject(Matrix(c(NA,0), 4, 3, byrow = TRUE)),validObject(Matrix(c(NA,0), 4, 4)),isValid(Matrix(c(NA,0,0,0), 4, 4), "sparseMatrix"))## large sparse ones: these now directly "go sparse":str(m0 <- Matrix(0, nrow=100, ncol = 1000))str(l0 <- Matrix(FALSE, nrow=100, ncol = 200))stopifnot(all(!l0),identical(FALSE, any(l0)))## with dimnames:m. <- matrix(c(0, 0, 2:0), 3, 5)dimnames(m.) <- list(LETTERS[1:3], letters[1:5])(m0 <- m <- Matrix(m.))m@Dimnames[[2]] <- m@Dimnames[[1]]## not valid anymore:(val <- validObject(m, test=TRUE)); stopifnot(is.character(val))dm <- as(m0, "denseMatrix")stopifnot(identical(rcond(dm), rcond(m.)),all.equal(rcond(dm), 0.4899474520656))rm(m)###-- Sparse Triangular :g5 <- new("dgCMatrix", Dim = c(5L, 5L),x = c(10, 1, 3, 10, 1, 10, 1, 10, 10),i = c(0L,2L,4L, 1L, 3L,2L,4L, 3L, 4L),p = c(0L, 3L, 5L, 7:9))t5 <- as(g5, "triangularMatrix") # works fine (but slowly) FIXMEstopifnot(class(t5) == "dtCMatrix",identical(t5, tril(g5)))(t1 <- new("dtTMatrix", x= c(3,7), i= 0:1, j=3:2,Dim= as.integer(c(4,4))))## Diagonal o SparseI4 <- Diagonal(4)D4 <- Diagonal(4, x=1:4)validObject(t2 <- t1 + I4)validObject(tt2 <- t(t1) + I4)validObject(t1c <- as(t1, "CsparseMatrix"))validObject(t2c <- as(t2, "CsparseMatrix"))stopifnot(validObject(t1),isValid(2 * I4, "diagonalMatrix"),isValid(D4 * 3, "diagonalMatrix"),isValid(I4 / 5, "diagonalMatrix"),isValid(D4 / 2, "diagonalMatrix"),identical(t1, t(t(t1))),identical(t1c, t(t(t1c))),isValid(t1c + I4,"triangularMatrix"), isValid(t2c + I4,"triangularMatrix"),c(class(t2), class(t1c), class(t2c), class(tt2)) == "dtCMatrix",identical(t(tt2), t2))assert.EQ.mat(t1, as(t1c, "matrix"))## as(<diag>, <anything>) :str(cls <- names(getClass("Matrix")@subclasses))# all Matrix classesfor(cl in cls)if(canCoerce(I4, cl)) {cat(cl,":")M <- as(I4, cl)M. <- as(D4, cl)stopifnot(diag(4) == as(M,"matrix"),if(is(cl,"dMatrix")) diag(x=1:4) == as(M.,"matrix") else TRUE)cat(" [Ok]\n")}## from 0-diagonal to unit-diagonal triangular {low-level step}:tu <- t1 ; tu@diag <- "U"tucu <- as(tu, "dtCMatrix")validObject(cnu <- Matrix:::diagU2N(cu))# <- testing diagU2Nstopifnot(validObject(cu), validObject(tu. <- as(cu, "dtTMatrix")),validObject(tt <- as(cu, "TsparseMatrix")),## NOT: identical(tu, tu.), # since T* is not unique!identical(cu, as(tu., "dtCMatrix")),length(cnu@i) == length(cu@i) + nrow(cu),identical(cu, Matrix:::diagN2U(cnu)),# <- testing diagN2Uall(cu >= 0, na.rm = TRUE), all(cu >= 0),any(cu >= 7),validObject(tcu <- t(cu)),validObject(ttu <- t(tu)))assert.EQ.mat(cu, as(tu,"matrix"), tol=0)assert.EQ.mat(cnu, as(tu,"matrix"), tol=0)## <sparse> o <numeric> (of length > 1):stopifnot(isValid(tm <- tu * 1:8, "sparseMatrix"),identical4(tm, cu * 1:8, 1:8 * cu, 1:8 * tu))cu[1,2] <- tu[1,2] <- NAmu <- as(tu,"matrix")stopifnot(isValid(cu, "CsparseMatrix"), isValid(cu, "triangularMatrix"),isValid(tu, "TsparseMatrix"), isValid(tu, "triangularMatrix"),identical(cu * 1:8, tu * 1:8), # but are no longer triangularall(cu >= 0, na.rm=TRUE), !all(cu >= 1), is.na(all(tu >= 0)))assert.EQ.mat(cu * 1:8, mu * 1:8)## tu. is diag "U", but tu2 not:tu2 <- as(as(tu., "generalMatrix"), "triangularMatrix")assert.EQ.mat(cu, mu, tol=0)stopifnot(identical3(cu[cu > 1], tu [tu > 1], mu [mu > 1]),identical3(cu <= 1, tu <= 1, as(mu <= 1, "lMatrix")),# all lgeMatrixidentical3(cu[cu <= 1], tu[tu <= 1], mu[mu <= 1]),identical3(cu , triu(cu ), t(t(cu))),identical3(tu , triu(tu ), t(t(tu))),identical3(tu., triu(tu.), t(t(tu.))),identical(tu2, triu(tu2)),identical(tcu , tril(tcu)),identical(ttu , tril(ttu)),identical(t(tu), tril(t(tu))))assert.EQ.mat(triu(cu), as.matrix(triu(as.matrix(cu))))for(k in -1:1)assert.EQ.mat(tril(cu,k), as.matrix(tril(as.matrix(cu),k)))(dtr <- Matrix(local({m <- diag(2); m[1,2] <- 3;m})))identical(dtr, triu(dtr))assert.EQ.mat(tril(dtr), diag(2))(t4 <- new("dgTMatrix", i = 3:0, j = 0:3, x = rep(1,4), Dim = as.integer(c(4,4))))c4 <- as(t4, "CsparseMatrix")## the same but "dsT" (symmetric)M <- Matrix(c(0, rep(c(0,0:1),4)), 4,4)#ok warningtt <- as(M, "TsparseMatrix")stopifnot(all.equal(triu(t4) + tril(t4), c4),all.equal(triu(tt) + tril(tt), c4))###-- Numeric Dense: Crossprod & Solveset.seed(123)mm. <- mm <- Matrix(rnorm(500 * 150), nc = 150)stopifnot(validObject(mm))xpx <- crossprod(mm)stopifnot(identical(mm, mm.),# once upon a time, mm was altered by crossprod()validObject(xpx))str(mm) # 'dge*"str(xpx)# 'dpo*"xpy <- crossprod(mm, rnorm(500))res <- solve(xpx, xpy)str(xpx)# now with Cholesky factorstopifnot(validObject(xpx),validObject(xpy),validObject(res))stopifnot(all.equal(xpx %*% res, xpy, tol= 1e-12))lp <- xpx >= 1slp <- as(lp, "sparseMatrix")ltlp <- lp[ lower.tri(lp) ]sltlp <- slp[ lower.tri(slp) ]dim(ij <- which(lower.tri(lp), arr.ind = TRUE))ss <- slp[ij] # now fast (!)stopifnot(identical4(lp[ij], ltlp, sltlp, as(lp, "matrix")[ij]),identical(ss, sltlp),isValid(lp, "lsyMatrix"), lp@uplo == "U")###-- more solve() methods {was ./solve.R }## first for "dgeMatrix" and all kinds of RHS :(m6 <- 1 + as(diag(0:5), "dgeMatrix"))rcond(m6)I6 <- as(diag(6), "dgeMatrix")stopifnot(all.equal(I6, m6 %*% solve(m6)),all.equal(I6, solve(m6) %*% m6) )(i6 <- solve(m6, Matrix(1:6)))stopifnot(identical(i6, as(cbind(c(-4, rep(1,5))), "dgeMatrix")),identical(i6, solve(m6, 1:6)),identical(i6, solve(m6, matrix(1:6))),identical(i6, solve(m6, matrix(c(1,2,3,4,5,6)))))## solve(<sparse>)(m <- t1+ t(t1) + Diagonal(4))i.m <- solve(as.mat(m))I1 <- m %*% i.mo4 <- diag(I1)im <- solve(m)(I2 <- m %*% im)(ms <- as(m, "symmetricMatrix"))## solve(<sparse>, <sparse>):s.mm <- solve(m,m)s.mms <- solve(m, ms)## these now work "fully-sparse"s.ms2 <- solve(ms, ms)s.msm <- solve(ms, m)I4c <- as(Matrix(diag(4),sparse=TRUE), "generalMatrix")stopifnot(isValid(im, "Matrix"), isValid(I2, "Matrix"), class(I4c) == "dgCMatrix",all.equal(I1, I2, tol = 1e-14),all.equal(diag(4), as.mat(I2), tol = 1e-12),all.equal(s.mm, I2, tol = 1e-14),all.equal(s.mms, I2, tol = 1e-14),all.equal(s.ms2, s.msm, tol = 4e-15),all.equal(s.ms2, I4c , tol = 4e-15),abs(o4 - 1) < 1e-14)###-- row- and column operations {was ./rowcolOps.R }set.seed(321)(m1 <- round(Matrix(rnorm(25), 5), 2))m1k <- Matrix(round(rnorm(1000), 2), 50, 20)m.m <- as(m1k, "matrix")stopifnot(all.equal(colMeans(m1k), colMeans(m.m)),all.equal(colSums (m1k), colSums (m.m)),all.equal(rowMeans(m1k), rowMeans(m.m)),all.equal(rowSums (m1k), rowSums (m.m)))###-- kronecker for nonsparse uses Matrix(.):stopifnot(isValid(kr <- kronecker(m1, m6), "Matrix"))assert.EQ.mat(kr,kronecker(as(m1, "matrix"),as(m6, "matrix")), tol = 0)## sparse:(kt1 <- kronecker(t1, tu))kt2 <- kronecker(t1c, cu)stopifnot(identical(Matrix:::uniq(kt1), Matrix:::uniq(kt2)))## but kt1 and kt2, both "dgT" are different since entries are not ordered!ktf <- kronecker(as.matrix(t1), as.matrix(tu))if(FALSE) # FIXME? our kronecker treats "0 * NA" as "0" for structural-0assert.EQ.mat(kt2, ktf, tol= 0)(cs1 <- colSums(kt1))NA.or.True <- function(x) is.na(x) | xeq <- (cs1 == colSums(as(kt1, "matrix")))stopifnot(NA.or.True(eq), identical(is.na(eq), is.na(cs1)))nt1 <- as(kt1, "nMatrix") # no NA's anymore(ng1 <- as(as(nt1, "generalMatrix"),"CsparseMatrix")) # ngCdg1 <- as(ng1, "dMatrix")# dgClt1 <- kt1 > 5nt1 <- as(lt1, "nMatrix")(colSums(nt1, sparseResult = TRUE))(colSums(kt1, sparseResult = TRUE)) # dsparse, with NA(colSums(lt1, sparseResult = TRUE)) # isparse, with NA(colSums(lt1, sparseResult = TRUE, na.rm = TRUE))(colSums(nt1, sparseResult = TRUE)) # isparse, no NA## check correct sparseness of both:for(M in list(kt1, nt1, ng1, dg1, lt1, nt1)) {m <- as(M, "matrix")for(na.rm in c(FALSE,TRUE)) {cs <- colSums(M, na.rm = na.rm)cs. <- colSums(M, na.rm = na.rm, sparseResult = TRUE)rs <- rowSums(M, na.rm = na.rm)rs. <- rowSums(M, na.rm = na.rm, sparseResult = TRUE)stopifnot(isValid(cs., "sparseVector"), identical(cs, as(cs., "vector")),isValid(rs., "sparseVector"), identical(rs, as(rs., "vector")),{eq <- cs == colSums(m, na.rm = na.rm) ; ineq <- is.na(eq)all(ineq | eq) && identical(ineq, is.na(cs)) },{eq <- rs == rowSums(m, na.rm = na.rm) ; ineq <- is.na(eq)all(ineq | eq) && identical(ineq, is.na(rs)) } )}}## coercion from "dpo" or "dsy"xx <- as(xpx, "dsyMatrix")stopifnot(isSymmetric(xxS <- as(xx, "sparseMatrix")),isSymmetric(xpxS <- as(xpx, "sparseMatrix")))tm <- matrix(0, 8,8)tm[cbind(c(1,1,2,7,8),c(3,6,4,8,8))] <- c(2,-30,15,20,80)(tM <- Matrix(tm)) ## dtC(mM <- Matrix(m <- (tm + t(tm)))) ## dsCmT <- as(mM, "dsTMatrix")gC <- as(as(mT, "dgTMatrix"), "dgCMatrix")## Check that 'mT' and gC print properly :pr.mT <- capture.output(mT)nn <- unlist(strsplit(gsub(" +\\.", "", sub("^....", "", pr.mT[-(1:2)])), " "))stopifnot(as.numeric(nn[nn != ""]) == m[m != 0],capture.output(gC)[-1] == pr.mT[-1])assert.EQ.mat(tM, tm, tol=0)assert.EQ.mat(gC, m, tol=0)assert.EQ.mat(mT, m, tol=0)stopifnot(isValid(mM, "dsCMatrix"), isValid(tM, "dtCMatrix"), identical(mT, as(mM, "TsparseMatrix")), identical(gC, as(mM, "generalMatrix"))## coercions general <-> symmetric, identical(as(as(mM, "generalMatrix"), "symmetricMatrix"), mM), identical(as(as(mM, "dgTMatrix"), "symmetricMatrix"), mT), identical(as(as(tM, "generalMatrix"),"triangularMatrix"), tM), identical(tM + Diagonal(8), tMD <- Diagonal(8) + tM), isValid(tMD, "dtCMatrix"))eM <- eigen(mM) # works thanks to base::as.matrix hack in ../R/zzz.Rstopifnot(all.equal(eM$values,{ v <- c(162.462112512353, 30.0665927567458)c(v, 15, 0, 0, 160-v[1], -15, -v[2])}, tol=1e-14))##--- symmetric -> pos.def. needs valid test:m5 <- Matrix(diag(5) - 1)if(FALSE) { # FIXME: this as(.,.) happily "works"assertError(mpo <- as(m5, "dpoMatrix"))validObject(mpo) #-> TRUE FIXME? it is *not* really pos.definite!}###-- dense nonzero pattern:class(m <- Matrix(TRUE,2,2)) # lsy(n <- as(m, "nMatrix")) # nsyvalidObject(n)## 1)as(n,"CsparseMatrix") # used to give CHOLMOD error: invalid xtype...ls2 <- as(m, "CsparseMatrix") # works fine## and really 'm' and 'n' are interally slot identical (!!!)as(n,"sparseMatrix")as(m,"sparseMatrix")### -- now when starting with nsparse :nT <- new("ngTMatrix",i = as.integer(c(0, 1, 0)),j = as.integer(c(0, 0, 1)), Dim = as.integer(c(2,2)),Dimnames = list(NULL, NULL))(nC <- as(nT, "ngCMatrix"))str(nC)# of course, no 'x' slotstopifnot(identical(tt <- as(nT,"denseMatrix"), # lgeas(as(nT, "lMatrix"),"denseMatrix")))ttas(nC,"denseMatrix")###-- sparse nonzero pattern : ----------(nkt <- as(as(as(kt1, "generalMatrix"), "CsparseMatrix"), "ngCMatrix"))# okdkt <- as(nkt, "denseMatrix")(clt <- crossprod(nkt))stopifnot(isValid(nkt, "ngCMatrix"),isValid(clt, "nsCMatrix"))crossprod(clt) ## a warning: crossprod() of symmetric## a Csparse with *repeated* entry is not valid!assertError(new("ngCMatrix", p = c(0L,2L), i = c(0L,0L), Dim = 2:1))### "d" <-> "l" for (symmetric) sparse :data(KNex)mm <- KNex$mmxpx <- crossprod(mm)## extract nonzero patternnxpx <- as(xpx, "nsCMatrix")show(nxpx) ## now ok, since subsetting worksr <- nxpx[1:2,]lmm <- as(mm, "lgCMatrix")nmm <- as(lmm, "nMatrix")xlx <- crossprod(lmm)x.x <- crossprod(nmm)## now A = lxpx and B = xlx should be close, but not quite the same## since <x,y> = 0 is well possible when x!=0 and y!=0 .## However, A[i,j] != 0 ==> B[i,j] != 0:A <- as(as(nxpx, "lMatrix"), "TsparseMatrix")B <- as(as(xlx, "lMatrix"), "TsparseMatrix")ij <- function(a) a@i + ncol(a) * a@jstopifnot(all(ij(A) %in% ij(B)))l3 <- upper.tri(matrix(,3,3))stopifnot(isValid(c3 <- as(l3, "CsparseMatrix"), "CsparseMatrix"),# lgCis(c3, "lMatrix"))(M <- Matrix(l3))stopifnot(isValid(M, "ltCMatrix"),isValid(M2 <- M %x% M, "triangularMatrix"), # is "dtT" (why not "dtC" ?)dim(M2) == c(9,9), identical(M2, kronecker(M,M)))M3 <- M %x% M2 #ok(cM3 <- colSums(M3, sparse=TRUE))identical(as.vector(cM3),as(rev(rowSums(M3, sparse=TRUE)), "vector"))M. <- M2 %x% M # gave infinite recursion## diagonal, sparse & interactionsstopifnot(isValid(as(Diagonal(3), "TsparseMatrix"), "TsparseMatrix"),isValid(X <- Diagonal(7) + 1.5 * tM[1:7,1:7], "sparseMatrix"),isValid(X, "triangularMatrix"),isValid(XX <- X - chol(crossprod(X)), "triangularMatrix"))XXXXX <- as(drop0(XX), "dsCMatrix")stopifnot(identical(XX, Matrix(0, nrow(X), ncol(X))))M <- Matrix(m., sparse = FALSE)(sM <- Matrix(m.))class(dlM <- M >= 1)stopifnot(identical(dlM, !(M < 1)),isValid(sM, "sparseMatrix"),isValid(dlM, "denseMatrix"))(lM <- as(dlM, "sparseMatrix"))lM2 <- as(dlM, "CsparseMatrix") #-> now oklM0 <- Matrix:::as_Csparse(dlM)stopifnot(identical3(lM, lM2, lM0))selectMethod("coerce", c("lgeMatrix", "CsparseMatrix"),useInherited = c(from = TRUE, to = FALSE))ms0 <- Matrix(c(0,1,1,0), 2,2)ms <- as(ms0, "TsparseMatrix")cs <- as(ms, "CsparseMatrix")ll <- as(ms, "lMatrix")lt <- as(ll, "lgTMatrix")nn <- as(cs, "nsparseMatrix")l2 <- as(cs, "lsparseMatrix")nt <- triu(nn)n3 <- as(nt, "lsparseMatrix")da <- nt + t(nt)dm <- nt * t(nt) + dastopifnot(isValid(ms, "dsTMatrix"),as(ms0,"matrix") == as(ll, "matrix"), # coercing num |-> logas(lt, "matrix") == as(ll, "matrix"),identical(ms, as(ll, "dMatrix")),identical4(as(ll, "CsparseMatrix"), as(cs, "lMatrix"),# lsC*as(nn, "lsparseMatrix"), l2),identical3(da, dm, as(cs, "generalMatrix")), # dgC*identical(as(da, "lMatrix"), as(lt, "CsparseMatrix")) # lgC*)cat('Time elapsed: ', proc.time(),'\n') # "stats"if(!interactive()) warnings()