2022-03-22 15:26:24 +00:00
|
|
|
#' Matricization
|
|
|
|
#'
|
2022-10-06 12:25:40 +00:00
|
|
|
#' @param T multi-dimensional array
|
|
|
|
#' @param modes axis indices along to matricize
|
|
|
|
#' @param dims dimension of \code{T} befor matricization
|
|
|
|
#' @param inv boolean to determin if the inverse operation should be performed
|
2022-03-22 15:26:24 +00:00
|
|
|
#'
|
2022-10-06 12:25:40 +00:00
|
|
|
#' @returns matrix of dimensions \code{dims[modes]} by \code{prod(dims)[-modes]}
|
|
|
|
#' or tensor of dimensions \code{dims} iff \code{inv} is true.
|
|
|
|
#'
|
|
|
|
#' @examples
|
2023-11-14 13:35:43 +00:00
|
|
|
#' stopifnot(all.equal(
|
|
|
|
#' mat(1:12, 2, dims = c(2, 3, 2)),
|
|
|
|
#' matrix(c(
|
|
|
|
#' 1, 2, 7, 8,
|
|
|
|
#' 3, 4, 9, 10,
|
|
|
|
#' 5, 6, 11, 12
|
|
|
|
#' ), 3, 4, byrow = TRUE)
|
|
|
|
#' ))
|
|
|
|
#'
|
2022-10-06 12:25:40 +00:00
|
|
|
#' A <- array(rnorm(2 * 3 * 5), dim = c(2, 3, 5))
|
|
|
|
#' stopifnot(exprs = {
|
|
|
|
#' all.equal(A, mat(mat(A, 1), 1, dim(A), TRUE))
|
|
|
|
#' all.equal(A, mat(mat(A, 2), 2, dim(A), TRUE))
|
|
|
|
#' all.equal(A, mat(mat(A, 3), 3, dim(A), TRUE))
|
|
|
|
#' all.equal(A, mat(mat(A, c(1, 2)), c(1, 2), dim(A), TRUE))
|
|
|
|
#' all.equal(A, mat(mat(A, c(1, 3)), c(1, 3), dim(A), TRUE))
|
|
|
|
#' all.equal(A, mat(mat(A, c(2, 3)), c(2, 3), dim(A), TRUE))
|
|
|
|
#'
|
|
|
|
#' all.equal(t(mat(A, 1)), mat(A, c(2, 3)))
|
|
|
|
#' all.equal(t(mat(A, 3)), mat(A, c(1, 2)))
|
|
|
|
#' })
|
|
|
|
#'
|
2022-03-22 15:26:24 +00:00
|
|
|
#' @export
|
2022-10-06 12:25:40 +00:00
|
|
|
mat <- function(T, modes, dims = dim(T), inv = FALSE) {
|
|
|
|
modes <- as.integer(modes)
|
2022-03-22 15:26:24 +00:00
|
|
|
|
2022-10-06 12:25:40 +00:00
|
|
|
stopifnot(exprs = {
|
|
|
|
length(T) == prod(dims)
|
|
|
|
all(modes <= length(dims))
|
|
|
|
})
|
|
|
|
|
|
|
|
perm <- c(modes, seq_along(dims)[-modes])
|
|
|
|
if (inv) {
|
|
|
|
dim(T) <- dims[perm]
|
|
|
|
perm <- order(perm)
|
|
|
|
} else {
|
|
|
|
dim(T) <- dims
|
2022-03-22 15:26:24 +00:00
|
|
|
}
|
|
|
|
|
2022-10-06 12:25:40 +00:00
|
|
|
T <- aperm(T, perm)
|
|
|
|
|
|
|
|
if (inv) {
|
|
|
|
dim(T) <- dims
|
|
|
|
} else {
|
|
|
|
dim(T) <- c(prod(dims[modes]), prod(dims[-modes]))
|
2022-03-22 15:26:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
T
|
|
|
|
}
|
2022-10-06 12:25:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
# #' Inverse Matricization
|
|
|
|
# #'
|
|
|
|
# #' @param T matrix of dimensions \code{dims[mode]} by \code{prod(dims[-mode])}
|
|
|
|
# #' @param mode axis along the original matricization
|
|
|
|
# #' @param dims dimension of the original tensor
|
|
|
|
# #'
|
|
|
|
# #' @returns multi-dimensional array of dimensions \code{dims}
|
|
|
|
# #'
|
|
|
|
# #' @examples
|
|
|
|
# #' p <- c(2, 3, 5)
|
|
|
|
# #' A <- array(rnorm(prod(p)), dim = p)
|
|
|
|
# #' stopifnot(expr = {
|
|
|
|
# #' all.equal(A, mat.inv(mat(A, 1), 1, p))
|
|
|
|
# #' all.equal(A, mat.inv(mat(A, 2), 2, p))
|
|
|
|
# #' all.equal(A, mat.inv(mat(A, 3), 3, p))
|
|
|
|
# #' })
|
|
|
|
# #'
|
|
|
|
# #' @export
|
|
|
|
# mat.inv <- function(T, modes, dims) {
|
|
|
|
# modes <- as.integer(modes)
|
|
|
|
|
|
|
|
# stopifnot(exprs = {
|
|
|
|
# length(T) == prod(dims)
|
|
|
|
# any(length(dims) < modes)
|
|
|
|
# })
|
|
|
|
|
|
|
|
# dim(T) <- c(dims[modes], dims[-modes])
|
|
|
|
# T <- aperm(T, order(c(modes, seq_along(dims)[-modes])))
|
|
|
|
# dim(T) <- c(prod(dims[modes]), prod(dims[-modes]))
|
|
|
|
|
|
|
|
# T
|
|
|
|
# }
|