Lapack,很可能,没有任何计算行列式的例行程序。但是我们可以使用LU,QR或SVD分解来计算它。我更喜欢使用LU分解。现在,lapack使用一些dgetrf子程序将矩阵A分解成具有一些IPIV数组的PLU格式。我不知道如何处理这些信息。为了计算行列式,我只是乘以U矩阵的对角元素。但PLU格式的L和U是什么以及如何提取它们。我在C编程。
答案 0 :(得分:3)
Lapack的dgetrf()
计算一般M-by-N矩阵A的A=P*L*U
分解。假设一个可逆方阵A,其行列式可以作为乘积计算:
U
是一个上三角矩阵。因此,它的行列式是对角元素的乘积,它恰好是输出A
的对角元素。确实,请参阅how the output A is defined:
退出时,因子化
A = P*L*U
中的因子L和U; L的单位对角元素不存储。
L
是一个下三角矩阵,其中包含未存储的单位对角线元素。因此,它的决定因素总是1。
P
是一个置换矩阵,编码为转置的乘积(即2个周期或交换)。确实,请参阅dgetri()
以了解它是如何使用的。因此,其决定因素是1或-1,这取决于转置的数量是偶数还是奇数。因此,P
的行列式可以计算为:
int j;
double detp=1.;
for( j=0;j<n;j++){
if(j+1!=ipiv[j]){
// j+1 : following feedback of ead : ipiv is from Fortran, hence starts at 1.
// hey ! This is a transpose !
detp=-detp;
}
}
这种方法的复杂性主要是使用部分旋转的高斯消除的成本,即O(2 / 3n ^ 3)。
您可能会使用dgetc2()
或QR分解转为完全旋转,以提高准确性。由潘等人在Algebraic and Numerical Techniques for the Computation of Matrix Determinants中发出信号。等,结合方程4.8,4.9和命题4.1,决定因素的最终误差可能是ed=(a+eps*a*n^4)^{n-1}*eps*an^5=a^n*(1+eps*n^4)^{n-1}*n^5*eps
的标度,其中eps
是双精度(约1e-13),a是最大的矩阵A和n中的所有元素都是矩阵的大小。这意味着计算的行列式对于“大”矩阵不是很重要:见表,特别是使用PLU分解时的相对误差!本文还提供了一种跟踪误差传播并产生更好的误差估计的算法。
您也可以尝试Faddeev–Le Verrier algorithm ...
答案 1 :(得分:2)
L是单位对角矩阵,因此其行列式始终为1。对于P
,它可以是1
或-1
,具体取决于排列的奇数/偶数,但ipiv
是交换数组而非排列数组,因此您可以转换以下简单Python循环到C
det = 1
for i in range(len(ipiv)):
det *= u(i,i)
if ipiv[i] != i:
det *= -1
但请注意,如果矩阵的条件在条件方面存在问题,则乘法可以上溢或下溢。而只是使用SVD。