2022-10-06 12:25:40 +00:00
|
|
|
#' Higher Order Singular Value Decomposition
|
|
|
|
#'
|
|
|
|
#' @param X multi-dimensional array (at least a matrix)
|
|
|
|
#' @param nu Number of Singula Vector per mode. Defaults to a complete HO-SVD.
|
|
|
|
#' @param eps tolerance for detecting linear dependence in columns of a matrix.
|
|
|
|
#' Used for rank deduction and passed to \code{\link{qr}}.
|
|
|
|
#'
|
|
|
|
#' @export
|
|
|
|
HOSVD <- function(X, nu = NULL, eps = 1e-07) {
|
2023-11-14 13:35:43 +00:00
|
|
|
if (!is.null(nu)) {
|
2022-10-06 12:25:40 +00:00
|
|
|
stopifnot(all(nu <= dim(X)))
|
|
|
|
}
|
|
|
|
|
|
|
|
# Compute per mode singular vectors
|
|
|
|
Us <- Map(function(i) {
|
|
|
|
xx <- mcrossprod(X, , i)
|
|
|
|
La.svd(xx, if (is.null(nu)) qr(xx, tol = eps)$rank else nu[i], 0)$u
|
|
|
|
}, seq_along(dim(X)))
|
|
|
|
# Compute Core tensor
|
|
|
|
C <- mlm(X, Map(t, Us))
|
|
|
|
|
|
|
|
list(C = C, Us = Us)
|
|
|
|
}
|
2023-11-14 13:35:43 +00:00
|
|
|
|
|
|
|
SVD <- function(A) .Call("C_svd", A)
|