就像 Brian Borchers 在他的评论中所说,行列式可以从 Cholesky 因子的对角线条目中确定。
理论:
考虑 Cholesky 分解
其中
RTR=STMS,
然后
det(M)=det(SRTRST)=det(S)det(RT)det(R)det(ST)=det(R)2.
由于是三角形的,它的特征值是对角线条目,因此
R
log det(M)=2log det(R)=2∑ilog(Rii).
代码:
执行此操作的 Matlab 代码是,例如,
[R,~,S] = chol(M);
log_det_chol = sum(2*log(diag(R)));
在 python 中,可以使用 scikits.sparse.cholmod 包从稀疏 Cholesky 分解计算对数行列式。从链接页面解释,执行此操作的代码是:
from scikits.sparse.cholmod import cholesky
R = cholesky(M)
log_det_chol = R.logdet()
如果您只想考虑非零特征值,您可以对的对角线的非零条目求和。R
测试用例:
我在使用 Dirichlet BC 的二维有限差分拉普拉斯算子上针对 Matlab 内置的 det() 函数进行了测试,得到了高达 400×400 左右的矩阵的精确一致性,之后使用 matlab 的 det() 得到 Inf,而cholesky 方法在我的笔记本电脑上达到百万倍的规模没有问题。下面是代码,供参考:
n = 20; % M is n^2-by-n^2. Matlab's det() returns Inf for n=25+
M = gallery('poisson',n);
[R,~,S] = chol(M);
log_det_chol = sum(2*log(diag(R))),
log_det = log(det(M))
内存注意事项:
由于此方法基于 Cholesky 分解,因此它继承了速度和稳定性。
对于大问题,使用这种方法的瓶颈可能是内存。特别是,使用具有良好旋转(Matlab 很好)的 Cholesky 分解,您可以预期需要内存,其中是划分自由分成不同的部分。O(s2)s
例如,在具有 n×n 网格的 2D 问题中,将域分成两部分的 1D 分离器具有的自由度。因此所需的内存量为,与存储右侧的数量级相同。s=O(n)O(n2)
一个 3D n×n×n 问题有一个 2D 分离器前端,其自由度为内存。s=O(n2)O(n4)