GSL特征值顺序

时间:2016-04-19 17:52:27

标签: c sorting gsl eigenvalue

我正在使用GSL库中的函数gsl_eigen_nonsymm和/或gsl_eigen_symm来查找L x L矩阵M[i][j]的特征值,它也是时间t = 1,....,N的函数,所以我有{{1获得每个ti的特征值分配L×L矩阵M[i][j][t]并对每个t进行对角化。

问题是程序在一些迭代后给出了不同顺序的特征值。例如(L = 3),如果E[i][j] = M[i][j][t]t = 0 eigen[t = 0] = {l1,l2,l3}(0)我可能会t = 1,而我需要eigen[t = 1] = {l3,l2,l1}(1) 更具体一点:考虑矩阵{l1,l2,l3}(t)特征值将永远是(近似)M (t) ) = {{0,t,t},{t,0,2t},{t,t,0}}当我试图对角化它时(使用下面的代码)我得到了几次特征值结果的交换。有没有办法防止它?我不能只按它的大小对它们进行排序我需要它们始终处于相同的顺序(无论它是什么)先验。 (下面的代码只是解释我的问题的一个例子)

编辑:我不能只对它们进行排序,因为先验我不知道它们的价值,也不是因为统计波动它们每次都可靠地拥有l1 = -1.3 t , l2 = -t , l3 = 2.3 t这样的结构,这就是为什么我想知道是否有一种方法可以使算法的行为总是以相同的方式运行,这样特征值的顺序总是相同的,或者是否有一些技巧可以使它发生。

为了更清楚,我会尝试重新描述我在这里提出的玩具问题。我们有一个矩阵,它取决于时间,我可能是天真地,期望得到l1<l2<l3,而我所看到的是算法经常在不同的时间交换特征值,所以如果在lambda_1(t).....lambda_N(t)那么如果例如,我想看看lambda_1如何随着时间的推移而发展,因为算法会在不同的时间混合特征值。下面的程序只是我问题的分析玩具示例:下面矩阵的特征值是t = 1 I've got ( lambda_1,lambda_2,lambda_3 )(1) at time t = 2 (lambda_2,lambda_1,lambda_3)(2)但是程序可能会给我一个输出l1 = -1.3 t , l2 = -t , l3 = 2.3 t如前所述,我想知道那里是否有是一种使程序按特定方式对特征值进行排序的方法,尽管它们具有实际数值,因此我总是得到(l1,l2,l3)组合。我希望现在更清楚,请告诉我是不是。

(-1.3,-1,2.3)(1), (-2,-2.6,4.6)(2), etc

3 个答案:

答案 0 :(得分:2)

你的问题毫无意义。特征值对它们没有任何固有的顺序。听起来我想要定义类似于L_1(M_t),...,L_n(M_t)的M_t特征值,然后跟踪它们如何随时间变化。假设您的过程驱动M_t是连续的,那么您的特征值也是如此。换句话说,当您对M_t进行小的更改时,它们不会发生显着变化。因此,如果您通过强制执行L_1&lt;来定义排序。 L_2 ......&lt; L_n,那么对于t的微小变化,这种排序不会改变。当您有两个特征值交叉时,您需要决定如何分配更改。如果你有&#34;随机波动&#34;它们大于你的特征值之间的典型距离,那么这基本上是不可能的。

这是跟踪特征向量的另一种方法,可能会更好。为此,假设您的特征向量是v_i,其中包含组件v_ij。你做的是第一次&#34;规范化&#34;您的特征向量使得v_i1是非负的,即恰好翻转每个特征向量的符号。这将通过v_i1上的排序定义特征值的排序,v_i1是每个特征向量的第一个分量。这样,您仍然可以跟踪彼此交叉的特征值。但是,如果你的特征向量在第一个组件上交叉,那你就麻烦了。

答案 1 :(得分:1)

我认为你不能做你想做的事。当t更改输出更改时。

我的原始答案提到了对指针的排序,但是查看数据结构它无济于事。当计算出特征值时,将值存储在E中。您可以按如下方式查看它们。

gsl_eigen_nonsymm(E, eigen, w);
double *mdata = (double*)E->data;
printf("mdata[%i]    \t%lf\n", 0, mdata[0]);
printf("mdata[%i]    \t%lf\n", 4, mdata[4]);
printf("mdata[%i]    \t%lf\n", 8, mdata[8]);

以下代码是如何布置特征向量中的数据...

double *data  = (double*)eigen->data;
for(i = 0; i < L; i++) {
  printf("%d n  \t%zu\n", i, eigen->size);
  printf("%d    \t%lf\n", i, GSL_REAL(gsl_vector_complex_get(eigen, i)));
  printf("%d r  \t%lf\n", i, data[0]);
  printf("%d i  \t%lf\n", i, data[1]);
  printf("%d r  \t%lf\n", i, data[2]);
  printf("%d i  \t%lf\n", i, data[3]);
  printf("%d r  \t%lf\n", i, data[4]);
  printf("%d i  \t%lf\n", i, data[5]);
}   

如果,当您看到订单更改时可以检查此项,mdata中的数据顺序会发生变化而data中的顺序会发生变化,那么算法就没有固定的顺序,即您不能做你要求它做的事。如果订单在mdata中没有变化并且在data中发生变化,那么您有一个解决方案,但我真的怀疑情况会是这样。

答案 2 :(得分:0)

根据文档,这些函数返回无序:

  

https://www.gnu.org/software/gsl/manual/html_node/Real-Symmetric-Matrices.html

     

此函数计算实对称矩阵A的特征值。必须在w中提供适当大小的附加工作空间。 A的对角线和下三角形部分在计算过程中被破坏,但没有参考严格的上三角形部分。特征值存储在向量eval中并且是无序的。

即使是返回有序结果的函数,也可以通过简单的上升/下降幅度来实现:

  

https://www.gnu.org/software/gsl/manual/html_node/Sorting-Eigenvalues-and-Eigenvectors.html

     

该函数根据如上所示的参数sort_type的值,同时将存储在向量eval中的特征值和存储在矩阵evec的列中的对应的实特征向量按升序或降序排序。

如果你正在寻找特征值的时间演变,就像你一直在做和解决时间相关的表示,例如:

lambda_1(t).....lambda_N(t)

对于您的简单时间 - 标量示例,

l1 = -1.3 t , l2 = -t , l3 = 2.3 t

您确实对所有可能的解决方案进行了参数化,并且因为您已经为它们分配了标识符ln,所以您不会遇到退化问题。即使任何M[i][j]是t的非线性函数,它也不重要,因为系统本身是线性的,解决方案纯粹由特征方程计算(在求解lambda时将保持t不变)。