Я пытаюсь вычислить мощность -0.5 следующей матрицы:
S <- matrix(c(0.088150041, 0.001017491 , 0.001017491, 0.084634294),nrow=2)
В Matlab результат равен (S^(-0.5)
):
S^(-0.5)
ans =
3.3683 -0.0200
-0.0200 3.4376
Я пытаюсь вычислить мощность -0.5 следующей матрицы:
S <- matrix(c(0.088150041, 0.001017491 , 0.001017491, 0.084634294),nrow=2)
В Matlab результат равен (S^(-0.5)
):
S^(-0.5)
ans =
3.3683 -0.0200
-0.0200 3.4376
Через некоторое время появилось следующее решение:
"%^%" <- function(S, power)
with(eigen(S), vectors %*% (values^power * t(vectors)))
S%^%(-0.5)
Результат дает ожидаемый ответ:
[,1] [,2]
[1,] 3.36830328 -0.02004191
[2,] -0.02004191 3.43755430
> library(expm)
> solve(sqrtm(S))
[,1] [,2]
[1,] 3.36830328 -0.02004191
[2,] -0.02004191 3.43755429
Квадратный корень матрицы не обязательно является уникальным (большинство действительных чисел имеют не менее 2 квадратных корней, поэтому это не просто матрицы). Существует несколько алгоритмов для генерации квадратного корня матрицы. Другие продемонстрировали подход с использованием expm и собственных значений, но разложение Холецкого - это еще одна возможность (см. Функцию chol
).
Чтобы расширить этот ответ за пределы квадратных корней, следующая функция exp.mat()
обобщает "матрицу" Moore-Penrose pseudoverse" и позволяет один для вычисления экспоненциальности матрицы посредством сингулярного декомпозиции (SVD) (даже работает для не квадратных матриц, хотя я не знаю, когда это понадобится).
exp.mat()
функция:#The exp.mat function performs can calculate the pseudoinverse of a matrix (EXP=-1)
#and other exponents of matrices, such as square roots (EXP=0.5) or square root of
#its inverse (EXP=-0.5).
#The function arguments are a matrix (MAT), an exponent (EXP), and a tolerance
#level for non-zero singular values.
exp.mat<-function(MAT, EXP, tol=NULL){
MAT <- as.matrix(MAT)
matdim <- dim(MAT)
if(is.null(tol)){
tol=min(1e-7, .Machine$double.eps*max(matdim)*max(MAT))
}
if(matdim[1]>=matdim[2]){
svd1 <- svd(MAT)
keep <- which(svd1$d > tol)
res <- t(svd1$u[,keep]%*%diag(svd1$d[keep]^EXP, nrow=length(keep))%*%t(svd1$v[,keep]))
}
if(matdim[1]<matdim[2]){
svd1 <- svd(t(MAT))
keep <- which(svd1$d > tol)
res <- svd1$u[,keep]%*%diag(svd1$d[keep]^EXP, nrow=length(keep))%*%t(svd1$v[,keep])
}
return(res)
}
S <- matrix(c(0.088150041, 0.001017491 , 0.001017491, 0.084634294),nrow=2)
exp.mat(S, -0.5)
# [,1] [,2]
#[1,] 3.36830328 -0.02004191
#[2,] -0.02004191 3.43755429
Другие примеры можно найти здесь.