Cholesky-methods
位于 Matrix
包(package)。 说明
计算 实对称矩阵 的旋转 Cholesky 分解,其具有一般形式
或(等效地)
其中 是置换矩阵, 是单位下三角矩阵, 是对角矩阵, 。第二个等式仅适用于正半定 ,其中 的对角线条目是非负的,并且 是明确定义的。
denseMatrix
的方法基于 LAPACK 例程 dpstrf
、 dpotrf
和 dpptrf
构建。后两者不排列行或列,因此 是单位矩阵。
sparseMatrix
的方法基于 CHOLMOD 例程 cholmod_analyze
和 cholmod_factorize_p
构建。
用法
Cholesky(A, ...)
## S4 method for signature 'dsyMatrix'
Cholesky(A, perm = TRUE, tol = -1, ...)
## S4 method for signature 'dspMatrix'
Cholesky(A, ...)
## S4 method for signature 'dsCMatrix'
Cholesky(A, perm = TRUE, LDL = !super, super = FALSE,
Imult = 0, ...)
## S4 method for signature 'ddiMatrix'
Cholesky(A, ...)
## S4 method for signature 'generalMatrix'
Cholesky(A, uplo = "U", ...)
## S4 method for signature 'triangularMatrix'
Cholesky(A, uplo = "U", ...)
## S4 method for signature 'matrix'
Cholesky(A, uplo = "U", ...)
参数
A |
要因式分解的 finite 、对称矩阵或 |
perm |
指示 |
tol |
finite 数字容差,仅在 |
LDL |
一个逻辑,指示单纯因式分解是否应计算为 |
super |
指示因式分解是否应使用超节点算法的逻辑。另一种选择是单纯算法。设置 |
Imult |
finite 号码。因式分解的矩阵为 |
uplo |
一个字符串, |
... |
传入或传出方法的更多参数。 |
细节
请注意,调用 Cholesky
的结果继承自 CholeskyFactorization
但不是 Matrix
。仅需要矩阵的用户应考虑使用 chol
,其方法是 Cholesky
的简单包装器,仅返回上三角 Cholesky 因子 ,通常作为 triangularMatrix
。然而,更原则性的方法是根据需要从 CholeskyFactorization
对象构造因子,例如,如果 x
是对象,则使用 expand1(x, "L")
。
Cholesky(A, perm = TRUE)
对于密集 A
的行为有些例外,因为它期望不检查 A
是否为正半定。通过构造,如果 是半正定的并且精确算法遇到零主元,则未因式分解的尾随子矩阵是零矩阵,并且没有什么可做的。因此,当有限精度算法遇到小于 tol
的主元时,它会发出警告而不是错误信号,并将尾随子矩阵归零,以保证 是半正定的,即使 不是。因此,在出现警告时测试 的正半定性的一种方法是分析错误
有关详细信息,请参阅示例和 LAPACK 工作笔记 (“LAWN”) 161。
值
表示分解的对象,继承自虚拟类 CholeskyFactorization
。对于传统矩阵 A
,具体类是 Cholesky
。对于继承自 unpackedMatrix
、 packedMatrix
和 sparseMatrix
的 A
,具体类分别是 Cholesky
、 pCholesky
和 dCHMsimpl
或 dCHMsuper
。
例子
showMethods("Cholesky", inherited = FALSE)
set.seed(0)
## ---- Dense ----------------------------------------------------------
## .... Positive definite ..............................................
n <- 6L
(A1 <- crossprod(Matrix(rnorm(n * n), n, n)))
(ch.A1.nopivot <- Cholesky(A1, perm = FALSE))
(ch.A1 <- Cholesky(A1))
stopifnot(exprs = {
length(ch.A1@perm) == ncol(A1)
isPerm(ch.A1@perm)
is.unsorted(ch.A1@perm) # typically not the identity permutation
length(ch.A1.nopivot@perm) == 0L
})
## A ~ P1' L D L' P1 ~ P1' L L' P1 in floating point
str(e.ch.A1 <- expand2(ch.A1, LDL = TRUE), max.level = 2L)
str(E.ch.A1 <- expand2(ch.A1, LDL = FALSE), max.level = 2L)
stopifnot(exprs = {
all.equal(as(A1, "matrix"), as(Reduce(`%*%`, e.ch.A1), "matrix"))
all.equal(as(A1, "matrix"), as(Reduce(`%*%`, E.ch.A1), "matrix"))
})
## .... Positive semidefinite but not positive definite ................
A2 <- A1
A2[1L, ] <- A2[, 1L] <- 0
A2
try(Cholesky(A2, perm = FALSE)) # fails as not positive definite
ch.A2 <- Cholesky(A2) # returns, with a warning and ...
A2.hat <- Reduce(`%*%`, expand2(ch.A2, LDL = FALSE))
norm(A2 - A2.hat, "2") / norm(A2, "2") # 7.670858e-17
## .... Not positive semidefinite ......................................
A3 <- A1
A3[1L, ] <- A3[, 1L] <- -1
A3
try(Cholesky(A3, perm = FALSE)) # fails as not positive definite
ch.A3 <- Cholesky(A3) # returns, with a warning and ...
A3.hat <- Reduce(`%*%`, expand2(ch.A3, LDL = FALSE))
norm(A3 - A3.hat, "2") / norm(A3, "2") # 1.781568
## Indeed, 'A3' is not positive semidefinite, but 'A3.hat' _is_
ch.A3.hat <- Cholesky(A3.hat)
A3.hat.hat <- Reduce(`%*%`, expand2(ch.A3.hat, LDL = FALSE))
norm(A3.hat - A3.hat.hat, "2") / norm(A3.hat, "2") # 1.777944e-16
## ---- Sparse ---------------------------------------------------------
## Really just three cases modulo permutation :
##
## type factorization minors of P1 A P1'
## 1 simplicial P1 A P1' = L1 D L1' nonzero
## 2 simplicial P1 A P1' = L L ' positive
## 3 supernodal P1 A P2' = L L ' positive
data(KNex, package = "Matrix")
A4 <- crossprod(KNex[["mm"]])
ch.A4 <-
list(pivoted =
list(simpl1 = Cholesky(A4, perm = TRUE, super = FALSE, LDL = TRUE),
simpl0 = Cholesky(A4, perm = TRUE, super = FALSE, LDL = FALSE),
super0 = Cholesky(A4, perm = TRUE, super = TRUE )),
unpivoted =
list(simpl1 = Cholesky(A4, perm = FALSE, super = FALSE, LDL = TRUE),
simpl0 = Cholesky(A4, perm = FALSE, super = FALSE, LDL = FALSE),
super0 = Cholesky(A4, perm = FALSE, super = TRUE )))
ch.A4
s <- simplify2array
rapply2 <- function(object, f, ...) rapply(object, f, , , how = "list", ...)
s(rapply2(ch.A4, isLDL))
s(m.ch.A4 <- rapply2(ch.A4, expand1, "L")) # giving L = L1 sqrt(D)
## By design, the pivoted and simplicial factorizations
## are more sparse than the unpivoted and supernodal ones ...
s(rapply2(m.ch.A4, object.size))
## Which is nicely visualized by lattice-based methods for 'image'
inm <- c("pivoted", "unpivoted")
jnm <- c("simpl1", "simpl0", "super0")
for(i in 1:2)
for(j in 1:3)
print(image(m.ch.A4[[c(i, j)]], main = paste(inm[i], jnm[j])),
split = c(j, i, 3L, 2L), more = i * j < 6L)
simpl1 <- ch.A4[[c("pivoted", "simpl1")]]
stopifnot(exprs = {
length(simpl1@perm) == ncol(A4)
isPerm(simpl1@perm, 0L)
is.unsorted(simpl1@perm) # typically not the identity permutation
})
## One can expand with and without D regardless of isLDL(.),
## but "without" requires L = L1 sqrt(D), which is conditional
## on min(diag(D)) >= 0, hence "with" is the default
isLDL(simpl1)
stopifnot(min(diag(simpl1)) >= 0)
str(e.ch.A4 <- expand2(simpl1, LDL = TRUE), max.level = 2L) # default
str(E.ch.A4 <- expand2(simpl1, LDL = FALSE), max.level = 2L)
stopifnot(exprs = {
all.equal(E.ch.A4[["L" ]], e.ch.A4[["L1" ]] %*% sqrt(e.ch.A4[["D"]]))
all.equal(E.ch.A4[["L."]], sqrt(e.ch.A4[["D"]]) %*% e.ch.A4[["L1."]])
all.equal(A4, as(Reduce(`%*%`, e.ch.A4), "symmetricMatrix"))
all.equal(A4, as(Reduce(`%*%`, E.ch.A4), "symmetricMatrix"))
})
## The "same" permutation matrix with "alternate" representation
## [i, perm[i]] {margin=1} <-> [invertPerm(perm)[j], j] {margin=2}
alt <- function(P) {
P@margin <- 1L + !(P@margin - 1L) # 1 <-> 2
P@perm <- invertPerm(P@perm)
P
}
## Expansions are elegant but inefficient (transposes are redundant)
## hence programmers should consider methods for 'expand1' and 'diag'
stopifnot(exprs = {
identical(expand1(simpl1, "P1"), alt(e.ch.A4[["P1"]]))
identical(expand1(simpl1, "L"), E.ch.A4[["L"]])
identical(Diagonal(x = diag(simpl1)), e.ch.A4[["D"]])
})
## chol(A, pivot = value) is a simple wrapper around
## Cholesky(A, perm = value, LDL = FALSE, super = FALSE),
## returning L' = sqrt(D) L1' _but_ giving no information
## about the permutation P1
selectMethod("chol", "dsCMatrix")
stopifnot(all.equal(chol(A4, pivot = TRUE), E.ch.A4[["L."]]))
## Now a symmetric matrix with positive _and_ negative eigenvalues,
## hence _not_ positive semidefinite
A5 <- new("dsCMatrix",
Dim = c(7L, 7L),
p = c(0:1, 3L, 6:7, 10:11, 15L),
i = c(0L, 0:1, 0:3, 2:5, 3:6),
x = c(1, 6, 38, 10, 60, 103, -4, 6, -32, -247, -2, -16, -128, -2, -67))
(ev <- eigen(A5, only.values = TRUE)$values)
(t.ev <- table(factor(sign(ev), -1:1))) # the matrix "inertia"
ch.A5 <- Cholesky(A5)
isLDL(ch.A5)
(d.A5 <- diag(ch.A5)) # diag(D) is partly negative
## Sylvester's law of inertia holds here, but not in general
## in finite precision arithmetic
stopifnot(identical(table(factor(sign(d.A5), -1:1)), t.ev))
try(expand1(ch.A5, "L")) # unable to compute L = L1 sqrt(D)
try(expand2(ch.A5, LDL = FALSE)) # ditto
try(chol(A5, pivot = TRUE)) # ditto
## The default expansion is "square root free" and still works here
str(e.ch.A5 <- expand2(ch.A5, LDL = TRUE), max.level = 2L)
stopifnot(all.equal(A5, as(Reduce(`%*%`, e.ch.A5), "symmetricMatrix")))
## Version of the SuiteSparse library, which includes CHOLMOD
.SuiteSparse_version()
参考
The LAPACK source code, including documentation; see https://netlib.org/lapack/double/dpstrf.f, https://netlib.org/lapack/double/dpotrf.f, and https://netlib.org/lapack/double/dpptrf.f.
The CHOLMOD source code; see
https://github.com/DrTimothyAldenDavis/SuiteSparse,
notably the header file ‘CHOLMOD/Include/cholmod.h’
defining cholmod_factor_struct
.
Lucas, C. (2004). LAPACK-style codes for level 2 and 3 pivoted Cholesky factorizations. LAPACK Working Note, Number 161. https://www.netlib.org/lapack/lawnspdf/lawn161.pdf
Chen, Y., Davis, T. A., Hager, W. W., & Rajamanickam, S. (2008). Algorithm 887: CHOLMOD, supernodal sparse Cholesky factorization and update/downdate. ACM Transactions on Mathematical Software, 35(3), Article 22, 1-14. doi:10.1145/1391989.1391995
Amestoy, P. R., Davis, T. A., & Duff, I. S. (2004). Algorithm 837: AMD, an approximate minimum degree ordering algorithm. ACM Transactions on Mathematical Software, 17(4), 886-905. doi:10.1145/1024074.1024081
Golub, G. H., & Van Loan, C. F. (2013). Matrix computations (4th ed.). Johns Hopkins University Press. doi:10.56021/9781421407944
也可以看看
类 Cholesky
、 pCholesky
、 dCHMsimpl
和 dCHMsuper
及其方法。
类 dpoMatrix
、 dppMatrix
和 dsCMatrix
。
通用函数 chol
,用于获取上三角 Cholesky 因子 作为矩阵或 Matrix
。
通用函数 expand1
和 expand2
,用于根据结果构造矩阵因子。
通用函数 BunchKaufman
、 Schur
、 lu
和 qr
用于计算其他因式分解。
相关用法
- R Cholesky-class 密集 Cholesky 分解
- R CHMfactor-class 稀疏 Cholesky 分解
- R CAex 阿尔伯斯的示例矩阵与“困难”特征分解
- R CsparseMatrix-class 列压缩形式稀疏矩阵的“CsparseMatrix”类
- R dtrMatrix-class 三角形稠密数值矩阵
- R facmul-methods 乘以矩阵因式分解的因数
- R solve-methods 函数求解矩阵包中的方法
- R updown-methods 更新和降级稀疏 Cholesky 分解
- R bdiag 构建分块对角矩阵
- R printSpMatrix 灵活格式化和打印稀疏矩阵
- R symmetricMatrix-class 包矩阵中对称矩阵的虚拟类
- R all.equal-methods 函数 all.equal() 的矩阵封装方法
- R boolmatmult-methods 布尔算术矩阵乘积:%&% 和方法
- R ltrMatrix-class 三角密集逻辑矩阵
- R Hilbert 生成希尔伯特矩阵
- R nearPD 最近正定矩阵
- R lsyMatrix-class 对称密集逻辑矩阵
- R symmpart-methods 矩阵的对称部分和偏斜(对称)部分
- R sparseMatrix 从非零项构建一般稀疏矩阵
- R dgCMatrix-class 压缩、稀疏、面向列的数值矩阵
- R Subassign-methods “[<-”的方法 - 分配给“矩阵”的子集
- R ldenseMatrix-class 密集逻辑矩阵的虚拟类“ldenseMatrix”
- R norm-methods 矩阵范数
- R ngeMatrix-class 一般密集非零模式矩阵的“ngeMatrix”类
- R diagonalMatrix-class 对角矩阵的“diagonalMatrix”类
注:本文由纯净天空筛选整理自R-devel大神的英文原创作品 Methods for Cholesky Factorization。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。