2

我需要计算一个大矩阵(大约 1000*1000 甚至更多)的特征值和特征向量。Matlab 运行速度非常快,但不保证准确性。我需要它非常准确(大约 1e-06 错误是可以的)并且在合理的时间内(一两个小时是可以的)。

我的矩阵是对称的并且非常稀疏。确切的值是:对角线上的值,主对角线下方的对角线上,以及主对角线上方的对角线。例子:

示例矩阵

我怎样才能做到这一点?C++ 对我来说是最方便的。

4

3 回答 3

5

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的近似误差。

于 2013-10-29T08:16:23.523 回答
4

如果您不反对使用第三方库,那么我在使用Armadillo线性代数库方面取得了巨大成功。

对于下面的例子,arma是他们喜欢使用的命名空间,vec是一个向量,mat是一个矩阵。

arma::vec getEigenValues(arma::mat M) {
    return arma::eig_sym(M);
}

您也可以将数据直接序列化,MATLAB反之亦然。

于 2013-10-29T03:39:18.690 回答
3

您的系统是三对角系统和(对称)托普利茨矩阵。我猜想 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)。但是,您的矩阵仍然是病态的。请记住,准确度估计是最坏的情况。

于 2013-10-29T16:18:00.780 回答