1
我試圖在C++中實現Cholesky分解,這是以前在lapack dpotrf_中實現的。C++,Lapack喬列斯基分解實現不準確的結果
Cholesky分解:R' * R = A
代碼:
#include <iostream>
#include <armadillo>
long my_chol(
arma::mat &R,
const arma::mat A,
long lda
)
{
arma::arma_debug_check((A.is_square() == false), "chol(): given matrix must be square sized");
arma::arma_debug_check((lda<std::max(1l,(long)A.n_rows)), "chol(): LDA must be equal to or greater than max(1,N)");
double sum;
long i, j, k;
long n = A.n_rows;
if(lda==(long)A.n_rows)
R=A;
else
{
R.zeros(lda,A.n_rows);
R.submat(0,lda-1,0,A.n_rows-1)=A;
}
for(i=0; i<n; ++i)
for(j=i+1; j<n; ++j)
R(j,i)=0;
for(i=0; i<n; ++i)
{
/* j == i */
sum = R(i,i);
for(k=(i-1); k>=0; --k)
sum -= R(k,i)*R(k,i);
if (sum > 0.0)
R(i,i) = sqrt(sum);
else
{
R(0) = sum; /* tunnel negative diagonal element to caller */
return (long)i+1;
}
for(j=(i+1); j<n; ++j)
{
sum = R(i,j);
for(k=(i-1); k>=0; --k)
sum -= R(k,i) * R(k,i);
R(i,j) = sum/R(i,i);
}
}
return 0;
}
我使用以下代碼測試此函數:
int main()
{
arma::mat A={{10, 3, 5},{3, 60, 7},{5, 7, 9}};
arma::mat B;
my_chol(B,A,3);
std::cout<<"---------------------------\n";
std::cout<<"A:\n";
A.print();
std::cout<<"B:\n";
B.print();
std::cout<<"---------------------------\n";
return 0;
}
,這是結果:
---------------------------
A:
10.0000 3.0000 5.0000
3.0000 60.0000 7.0000
5.0000 7.0000 9.0000
B:
3.1623 0.9487 1.5811
0 7.6877 0.7935
0 0 2.4229
---------------------------
但在八度測試相同的矩陣給了我不同的結果:
A=[10,3,5;3,60,7;5,7,9];
chol(A)
3.16228 0.94868 1.58114
0.00000 7.68765 0.71543
0.00000 0.00000 2.44707
雖然結果看起來近,它們之間有細微的差別。
R23
和R33
略有不同。我檢查了結果。從八度的結果是正確的,我的一個不是:
R=[3.1623,0.9487,1.5811;0,7.6877,0.7935;0,0,2.4229];
R'*R
ans =
10.0001 3.0001 4.9999
3.0001 60.0008 7.6002
4.9999 7.6002 9.0000
爲什麼我的代碼給出了錯誤的結果?