R Under development (unstable) (2025-08-17 r88631 ucrt) -- "Unsuffered Consequences" Copyright (C) 2025 The R Foundation for Statistical Computing Platform: x86_64-w64-mingw32/x64 R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R. > library(Matrix, quietly=TRUE) > library(sparsesvd) > > ## Stress test: > ## - apply sparsesvd() to a large number of random sparse nonnegative matrices > ## - check that original matrix M can be reconstructed with reasonable accuracy > ## - compare truncated SVD against first components of full SVD > > ## Run interactively with: > ## R --slave -f stress_test.R --args > ## (all arguments are optional with default values set below) > argv <- commandArgs(trailingOnly=TRUE) > argc <- length(argv) > > ## arguments and their default values > n.run <- if (argc >= 1) as.integer(argv[1]) else 100 # number of runs > k <- if (argc >= 2) as.integer(argv[2]) else 500 # k = number of rows of M > n <- if (argc >= 3) as.integer(argv[3]) else 100 # n = number of columns of M > r <- if (argc >= 4) as.integer(argv[4]) else 10 # r = rank of truncated SVD > torture <- if (argc >= 5) as.logical(argv[5]) else FALSE # run with gctorture()? > fillrate <- if (argc >= 6) as.numeric(argv[6]) else .10 # fill rate of sparse matrix (10%) > tol <- if (argc >= 7) as.numeric(argv[7]) else 1e-6 # acceptable approx. error per cell > > cat("sparsesvd() Stress Test:\n") sparsesvd() Stress Test: > cat(sprintf(" - %d runs testing full and rank-%d sparse SVD\n", n.run, r)) - 100 runs testing full and rank-10 sparse SVD > cat(sprintf(" - based on %d x %d nonnegative matrix with %.1f%% nonzero cells\n", k, n, 100 * fillrate)) - based on 500 x 100 nonnegative matrix with 10.0% nonzero cells > cat(sprintf(" - reconstruction accuracy < %g, gctorture() is %s\n", tol, if (torture) "ON" else "OFF")) - reconstruction accuracy < 1e-06, gctorture() is OFF > > ## approximate matrix comparison > assert.mat.equal <- function (x, y, tol=1e-6, msg="") { + if (!all(dim(x) == dim(y))) stop(sprintf("error: matrix dimensions differ %s", msg)) + err <- max(abs(x - y)) + if (err > tol) stop(sprintf("approximation error %g > tolerance %g %s", err, tol, msg)) + } > > ## now perform n.run iterations of the test procedure > gctorture(torture) > > pb <- txtProgressBar(min=0, max=n.run, style=3) | | | 0%> for (i in 1:n.run) { + setTxtProgressBar(pb, i) + x <- ifelse(runif(k * n) < fillrate, runif(k * n), 0) + M <- matrix(x, k, n) # random non-negative matrix with specified fill rate + Ms <- Matrix(M, sparse=TRUE) + + ## complete sparse SVD + svdM <- sparsesvd(Ms) + R <- with(svdM, u %*% diag(d) %*% t(v)) # reconstructed matrix + assert.mat.equal(R, M, tol=tol, msg=sprintf("(full SVD at iteration #%d)", i)) + + ## complete sparse SVD of transposed matrix + svdMt <- sparsesvd(t(Ms)) + R <- with(svdMt, v %*% diag(d) %*% t(u)) # reconstructed matrix + assert.mat.equal(R, M, tol=tol, msg=sprintf("(full transposed SVD at iteration #%d)", i)) + + Mr <- with(svdM, u[, 1:r] %*% diag(d[1:r]) %*% t(v[, 1:r])) # r-dimensional approximation + + ## truncated sparse SVD + svdMr <- sparsesvd(Ms, rank=r) + Rr <- with(svdMr, u %*% diag(d) %*% t(v)) # reconstructed r-dim approximation + assert.mat.equal(Rr, Mr, tol=tol, msg=sprintf("(%d-rank truncated SVD at iteration #%d)", r, i)) + + ## truncated sparse SVD of transposed matrix + svdMrt <- sparsesvd(t(Ms), rank=r) + Rr <- with(svdMrt, v %*% diag(d) %*% t(u)) # reconstructed r-dim approximation + assert.mat.equal(Rr, Mr, tol=tol, msg=sprintf("(%d-rank truncated transposed SVD at iteration #%d)", r, i)) + } | |= | 1% | |= | 2% | |== | 3% | |=== | 4% | |==== | 5% | |==== | 6% | |===== | 7% | |====== | 8% | |====== | 9% | |======= | 10% | |======== | 11% | |======== | 12% | |========= | 13% | |========== | 14% | |========== | 15% | |=========== | 16% | |============ | 17% | |============= | 18% | |============= | 19% | |============== | 20% | |=============== | 21% | |=============== | 22% | |================ | 23% | |================= | 24% | |================== | 25% | |================== | 26% | |=================== | 27% | |==================== | 28% | |==================== | 29% | |===================== | 30% | |====================== | 31% | |====================== | 32% | |======================= | 33% | |======================== | 34% | |======================== | 35% | |========================= | 36% | |========================== | 37% | |=========================== | 38% | |=========================== | 39% | |============================ | 40% | |============================= | 41% | |============================= | 42% | |============================== | 43% | |=============================== | 44% | |================================ | 45% | |================================ | 46% | |================================= | 47% | |================================== | 48% | |================================== | 49% | |=================================== | 50% | |==================================== | 51% | |==================================== | 52% | |===================================== | 53% | |====================================== | 54% | |====================================== | 55% | |======================================= | 56% | |======================================== | 57% | |========================================= | 58% | |========================================= | 59% | |========================================== | 60% | |=========================================== | 61% | |=========================================== | 62% | |============================================ | 63% | |============================================= | 64% | |============================================== | 65% | |============================================== | 66% | |=============================================== | 67% | |================================================ | 68% | |================================================ | 69% | |================================================= | 70% | |================================================== | 71% | |================================================== | 72% | |=================================================== | 73% | |==================================================== | 74% | |==================================================== | 75% | |===================================================== | 76% | |====================================================== | 77% | |======================================================= | 78% | |======================================================= | 79% | |======================================================== | 80% | |========================================================= | 81% | |========================================================= | 82% | |========================================================== | 83% | |=========================================================== | 84% | |============================================================ | 85% | |============================================================ | 86% | |============================================================= | 87% | |============================================================== | 88% | |============================================================== | 89% | |=============================================================== | 90% | |================================================================ | 91% | |================================================================ | 92% | |================================================================= | 93% | |================================================================== | 94% | |================================================================== | 95% | |=================================================================== | 96% | |==================================================================== | 97% | |===================================================================== | 98% | |===================================================================== | 99% | |======================================================================| 100%> close(pb) > > proc.time() user system elapsed 5.32 0.26 5.54