我正在尝试使用 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)
。到目前为止一切顺利,请注意这里的“列”特征向量显示为行[...,...,等等],我很高兴,但有一些问题:
有时我需要得到按升序或降序排序的特征值 [ 23.285687 4.3552833 277.10958 0.79058644 367.06761 144.39125] 的结果,我该如何得到这个?
在上述工作之后,$matrix2如何 释放用于对象的内存 ?$matrix3
对于进一步的向量/矩阵处理:是否有很好的 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)
要回答您的第一个问题如何对特征值进行排序:您可以使用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)