我需要计算一个大矩阵(大约 1000*1000 甚至更多)的特征值和特征向量。Matlab 运行速度非常快,但不保证准确性。我需要它非常准确(大约 1e-06 错误是可以的)并且在合理的时间内(一两个小时是可以的)。
我的矩阵是对称的并且非常稀疏。确切的值是:对角线上的值,主对角线下方的对角线上,以及主对角线上方的对角线。例子:
我怎样才能做到这一点?C++ 对我来说是最方便的。
我需要计算一个大矩阵(大约 1000*1000 甚至更多)的特征值和特征向量。Matlab 运行速度非常快,但不保证准确性。我需要它非常准确(大约 1e-06 错误是可以的)并且在合理的时间内(一两个小时是可以的)。
我的矩阵是对称的并且非常稀疏。确切的值是:对角线上的值,主对角线下方的对角线上,以及主对角线上方的对角线。例子:
我怎样才能做到这一点?C++ 对我来说是最方便的。
MATLAB 不保证准确性
我觉得这种说法不合理。您基于什么理由说您可以找到比 MATLAB 高度精细的计算算法(显着)更准确的实现?
并且...使用 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 矩阵非常 病态:
>> cond(A)
ans =
1.6551e+003
一般的经验法则是,对于 10 k的条件数,您可能会损失多达k位的准确性(除了由于算术方法的精度损失而导致数值方法丢失的数据之外)。
因此,在您的情况下,我希望结果准确到 10 -3的近似误差。
如果您不反对使用第三方库,那么我在使用Armadillo线性代数库方面取得了巨大成功。
对于下面的例子,arma
是他们喜欢使用的命名空间,vec
是一个向量,mat
是一个矩阵。
arma::vec getEigenValues(arma::mat M) {
return arma::eig_sym(M);
}
您也可以将数据直接序列化,MATLAB
反之亦然。
您的系统是三对角系统和(对称)托普利茨矩阵。我猜想 eigen 和 Matlabeig
有特殊情况来处理这样的矩阵。在这种情况下,特征值有一个封闭形式的解决方案(参考 (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++(或使用 Matlabcodgen
生成使用此或的 C/C++ 代码eig
)。但是,您的矩阵仍然是病态的。请记住,准确度估计是最坏的情况。