我需要计算一个大矩阵(约1000 * 1000甚至更多)的特征值和特征向量。 Matlab的工作速度非常快,但并不能保证准确性。我需要这个非常准确(约1e-06错误是可以的)并且在合理的时间内(一两个小时没问题)。
我的矩阵是对称的,非常稀疏。确切的值是:在对角线上,在主对角线下方的对角线上,以及在它上方的对角线上。例如:
Example Matrix http://img692.imageshack.us/img692/2269/zb2u.png
我该怎么做? C ++对我来说最方便。
答案 0 :(得分:5)
MATLAB无法保证准确性
我觉得这个说法不合理。基于什么理由,您可以找到比MATLAB高度精炼的计算算法更精确的实现?
AND ...使用MATLAB的eig
,以下计算时间不到半秒:
%// Generate the input matrix
X = ones(1000);
A = triu(X, -1) + tril(X, 1) - X;
%// Compute eigenvalues
v = eig(A);
很快就好了!
我需要这个非常准确(约1e-06错误就可以了)
请记住,精确求解特征值与寻找特征多项式的根有关。这个特定的1000x1000矩阵非常 ill-conditioned:
>> cond(A)
ans =
1.6551e+003
A general rule of thumb是条件数为10 k 的情况,您可能会损失高达 k 的精度数字(在由于算术方法的精度损失,数值方法会丢失的顶部。)
所以在你的情况下,我希望结果准确到10 -3 的近似误差。
答案 1 :(得分:4)
如果您不反对使用第三方库,我使用Armadillo线性代数库取得了巨大成功。
对于下面的示例,arma
是他们喜欢使用的命名空间,vec
是一个向量,mat
是一个矩阵。
arma::vec getEigenValues(arma::mat M) {
return arma::eig_sym(M);
}
您也可以将数据直接序列化为MATLAB
,反之亦然。
答案 2 :(得分:3)
您的系统是tridiagonal和(对称)Toeplitz matrix。我猜想eigen和Matlab的eig
有特殊情况来处理这样的矩阵。在这种情况下有closed-form solution for the eigenvalues(reference (PDF))。在Matlab中你的矩阵就是这样:
n = size(A,1);
k = (1:n).';
v = 1-2*cos(pi*k./(n+1));
这可以通过注意特征值以1
为中心进一步优化,因此只需计算其中一半:
n = size(A,1);
if mod(n,2) == 0
k = (1:n/2).';
u = 2*cos(pi*k./(n+1));
v = 1+[u;-u];
else
k = (1:(n-1)/2).';
u = 2*cos(pi*k./(n+1));
v = 1+[u;0;-u];
end
我不确定如何使用简单的代码获得更快更准确的效果(除了使用特征向量和优化执行细化步骤之外)。上面应该能够非常容易地翻译成C ++(或者使用Matlab的codgen
生成使用它或eig
的C / C ++代码。但是,你的矩阵仍然是病态的。请记住,准确性的估计是最坏的情况。