Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何快速准确地获得特征值和特征向量?_C++_Matlab_Linear Algebra_Eigenvector_Eigenvalue - Fatal编程技术网

C++ 如何快速准确地获得特征值和特征向量?

C++ 如何快速准确地获得特征值和特征向量?,c++,matlab,linear-algebra,eigenvector,eigenvalue,C++,Matlab,Linear Algebra,Eigenvector,Eigenvalue,我需要计算一个大矩阵的特征值和特征向量(大约1000*1000甚至更多)。Matlab工作速度非常快,但不能保证准确性。我需要这是相当准确的(大约1e-06的错误是可以的),并在一个合理的时间内(一个或两个小时是可以的) 我的矩阵是对称的,非常稀疏。精确值为:对角线上的值,主对角线下方的对角线上的值,以及主对角线上方的对角线上的值。例如: 我该怎么做?C++对我来说是最方便的。 如果你不反对使用第三方库,我已经使用线性代数库取得了很大的成功。 对于下面的示例,arma是他们喜欢使用的名称空间,

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

我的矩阵是对称的,非常稀疏。精确值为:对角线上的值,主对角线下方的对角线上的值,以及主对角线上方的对角线上的值。例如:


我该怎么做?C++对我来说是最方便的。

如果你不反对使用第三方库,我已经使用线性代数库取得了很大的成功。

对于下面的示例,
arma
是他们喜欢使用的名称空间,
vec
是向量,
mat
是矩阵

arma::vec getEigenValues(arma::mat M) {
    return arma::eig_sym(M);
}
您还可以将数据直接序列化到
MATLAB
中,反之亦然

MATLAB不能保证精度

我觉得这种说法不合理。你凭什么说你能找到一个(明显)比MATLAB高度精确的计算算法更精确的实现

而且。。。使用MATLAB,在不到半秒钟的时间内计算以下内容:

%// Generate the input matrix
X = ones(1000);
A = triu(X, -1) + tril(X, 1) - X;

%// Compute eigenvalues
v = eig(A);
很快,好吧

我需要非常准确(关于1e-06的错误是可以的)

请记住,准确求解特征值与找到特征多项式的根有关。这个特定的1000x1000矩阵非常:

对于10k的条件数,您可能会损失高达k位的精度(由于算术方法的精度损失,数值方法可能会损失的精度除外)

因此,在您的情况下,我希望结果准确到大约10-3的误差。

您的系统是和a(对称的)。我猜eigen和Matlab的
eig
有处理此类矩阵的特殊情况。在这种情况下,有一个错误()。在矩阵的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生成使用这个或<代码> EG<<代码>的C/C++代码)。但是,您的矩阵仍然是病态的。请记住,准确度估计是最糟糕的情况。

这与其说是编程问题,不如说是数学问题。看一看:看看犰狳或艾根,然后使用最适合您需要的产品。Seigen太慢了(或者可能它有我不知道的配置选项?)。这是一个编程问题,因为我不想自己写,我想用一些现成的东西。这是如何回答这个问题的?OP想计算C++中的特征值,你告诉他MATLAB是精确的。@ TylerJandreau问题是关于精确计算特征值,并且我推断,如果MATLAB足够精确,就足够了。对于这种类型的矩阵,似乎不可能以要求的精度计算特征值,因此没有理由不满意MATLAB的答案。你为什么否决我的答案?谢谢!但是为什么[V,D]=eig(A)和D=eig(A)给出不同的特征值作为答案,我应该使用哪一个?另外,我认为数值方法的精度损失可能很大,我可以设置吗?Matlab没有说明答案的准确度,因此我不能真正相信它。@EllaShar如答案中所述,您可以使用。我怀疑你能找到一个明显优于MATLAB的数值算法。最准确的方法可能是通过解析的方法来解决这个问题,但它并不总是可行的。这帮了大忙!你知道这种差异的原因是什么吗?你能帮我试一下吗?我试着使用eigen,但速度太慢了。谢谢直接使用arma::eig_sym()而不是封装到函数中会更快。简单使用
vec v=eig_sym(M)。Armadillo也有功能,例如使用“分治”算法,这对于大型矩阵要快得多。谢谢,但我不想免费下载Armadillo,它应该比eigen库更快吗?如果您可以运行它并进行检查,这将是最好的。“dc”算法的缺点是什么?有多不准确?在eigen中是否有类似的东西(我已经有了)?再次感谢@霍奇勒很好的分析答案,+1。然而,在表达式
v=1-2*cos(pi*k./(n+1))
中不应该有加号而不是减号吗?(根据文章)@EitanT:PDF文章和维基百科使用不同的符号。我猜这是惯例,因为它只是改变了特征值的顺序(
cos
是一个偶数函数),这只在需要特征向量时才起作用。哇,这真是太棒了!我想知道为什么eigen不这么做(我想是因为它太慢了)。PDF也有特征向量的分析公式。@EllaShar虽然我绝对不会因为不接受我的答案而感到难过,但我真的看不出
eig(a)
和显式计算之间有什么实际区别。虽然
eig(A)
没有闪电般的快(但仍然相当快),但它能够产生相同的结果(并且可能使用相同的优化),这是更容易理解的方法。也许我在这里遗漏了什么,但既然你已经用内置函数为你完成了,为什么还要重新实现它呢?@EllaShar:我对eigen一无所知,但速度慢可能与它没有根据最快的数学和线性代数库编译,内存分配不当,或者你做错了什么事(你得做点什么)
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