PDL /向量和矩阵代数/对称矩阵的特征值排序

aga*_*ve6 6 perl pdl

我正在尝试使用 Perl 模块eigens_sym 的强大功能来计算对称矩阵的特征向量PDL

use strict; # Be pessimistic and careful with interpretations in the compilation stage, before the very execution of this program . Doubts may abort execution, probably with error messages to stdout 

use PDL ;   # Load the PDL extension of Perl 



my $matrix ; # declare this variable 

# Set $matrix to my matrix A 

$matrix = new PDL(
                [
                    [  2 ,  1 ,  9 ,  2 , -6 ,  5 , ] ,
                    [  0 ,  5 ,  3 ,  0 , -8 , -3 , ] ,
                    [  1 ,  0 ,  5 ,  1 , -6 ,  5 , ] ,
                    [ -4 , -6 , -7 ,  2 , -1 ,  5 , ] ,
                    [  5 , -2 ,  3 ,  1 , -8 ,  3 , ] ,
                    [  1 , -6 ,  9 , -2 ,  9 ,  5 , ]

                ]
               ) ; 

print "\nA: \n" ; 

print $matrix ; 

# Make and display $matrix2 = The transposition of A 

    my $matrix2 =  $matrix -> transpose ;

    print "\nA* : \n" ; 

    print $matrix2 ; 

my $matrix3 = $matrix2 x $matrix ; # Here $matrix3 is set to the matrix product A* A : 

print "\nA*A : \n" ; 

print $matrix3 ; 
Run Code Online (Sandbox Code Playgroud)

数学上说,对于任何由实数组成的方阵 A,A* A 总是对称的(并且是半定正的,但这对于 eigens_sym PDL 的函数来说不是必需的),并且可以帮助我们了解对于理解 A 和这对我们意味着一切

my ($ev,$e) = eigens_sym $matrix3 ;  # X-rated matrix, id est:  Compute the eigenvalues and the eigenvectors of A* A   !
Run Code Online (Sandbox Code Playgroud)

换句话说:对角化 A* A ,这对于任何实数对称矩阵总是可能的,但随着矩阵维数的增加可能会非常困难。

print "\nEigenvalues with eigenvectors of A*A : \n\n" ; 

print $e ;  # The eigenvalues 

print $ev ; # " The eigenvectors are returned in COLUMNS of the returned PDL "
Run Code Online (Sandbox Code Playgroud)

印刷 :

A: 

[
 [ 2  1  9  2 -6  5]
 [ 0  5  3  0 -8 -3]
 [ 1  0  5  1 -6  5]
 [-4 -6 -7  2 -1  5]
 [ 5 -2  3  1 -8  3]
 [ 1 -6  9 -2  9  5]
]


A*A : 

[
 [ 47  10  75   0 -45  15]
 [ 10 102   6   0 -78 -76]
 [ 75   6 254  -6 -44  80]
 [  0   0  -6  14 -46  18]
 [-45 -78 -44 -46 282 -20]
 [ 15 -76  80  18 -20 118]
]


Eigenvalues with eigenvectors of A*A : 

[ 23.285687  4.3552833  277.10958 0.79058644  367.06761  144.39125]

[
 [  0.86502676   0.39257997  0.090239841 -0.070634235  -0.25470872  -0.14000255]
 [ -0.36255636   0.53399064  -0.40332417  -0.31499006  -0.16574127  -0.54226155]
 [ -0.19994359  -0.20028032   0.58246948      0.19444  -0.60114242  -0.42598184]
 [ -0.14771441   0.50816552 -0.082459683   0.81070439 -0.092150685   0.21775057]
 [-0.037584019   0.29620226   0.55789823  0.032583693   0.69935299  -0.33082462]
 [ -0.23889757   0.41791719   0.41456683  -0.44685776  -0.22066884   0.58994146]
]
Run Code Online (Sandbox Code Playgroud)

。到目前为止一切顺利,请注意这里的“列”特征向量显示为行[...,...,等等],我很高兴,但有一些问题:

  1. 有时我需要得到按升序或降序排序的特征值 [ 23.285687 4.3552833 277.10958 0.79058644 367.06761 144.39125] 的结果,我该如何得到这个?

  2. 在上述工作之后,$matrix2如何 释放用于对象的内存 ?$matrix3

  3. 对于进一步的向量/矩阵处理:是否有很好的 Perl 教程和手册PDL

顺便说一句/只是对 Perl 系统中 PDL 模块安装的评论/我在 Perl 之后安装了 PDL:第一次运行时,由于我的 Perl 系统中缺少许多模块(PDL 是一个大模块),我遇到了依赖问题,截至2023 年 11 月 我通过从命令行运行解决了这个严重的问题

#     $ sudo perl -MCPAN -e 'shell' 
#     <etc etc>
#     cpan[1]> install PDL 

# This automatic installation took several minutes to run and was apparently successful, although some error messages were issued
Run Code Online (Sandbox Code Playgroud)

Håk*_*and 4

要回答您的第一个问题如何对特征值进行排序:您可以使用qsort函数:

# Sort eigenvalues in ascending order
my $sorted_ev_asc = qsort($e);

# Sorted eigenvalues in descending order
my $sorted_ev_desc = $sorted_ev_asc->slice("-1:0");
Run Code Online (Sandbox Code Playgroud)

对于第二个问题:如何释放 的内存$matrix3?Perl 自动管理变量的内存,通常不需要显式释放内存。但是,如果要显式释放 PDL 变量占用的内存,可以使用null函数。

$matrix3 = PDL->null;
Run Code Online (Sandbox Code Playgroud)

对于第三个问题:哪里可以找到PDL矩阵运算的教程?例如,查看此页面:https ://metacpan.org/pod/PDL::MatrixOps

更新

要对特征向量进行排序,您可以使用qsorti函数:

my ($evec,$eval) = eigens_sym $matrix3 ;  # Make the eigenvector 
# Get the indices of the sorted elements
my $indices = qsorti($eval);
# Sort eigenvectors based on the permutation indices
my $sorted_eigenvalues = $eval->slice($indices);
# Sort eigenvectors based on the permutation indices
my $sorted_eigenvectors = $evec->slice(':', $indices);
Run Code Online (Sandbox Code Playgroud)

编辑2

要更改输出中的有效位数,可以在本地(或全局)设置一个名为doubleformat的包变量。例如:

local $PDL::doubleformat = "%10.16g";  # Set to the desired precision
# Print sorted eigenvalues
say "Eigenvalues in ascending order: $sorted_eigenvalues";
Run Code Online (Sandbox Code Playgroud)

其输出如下:

Eigenvalues in ascending order: 

  [-104.0242117201316  -50.37924528190175  -4.799244776313021 
     55.46970789893607 117.6355876358277  225.0974062435826
  ]
Run Code Online (Sandbox Code Playgroud)