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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。