http://www.perlmonks.org?node_id=11138473

Lucero has asked for the wisdom of the Perl Monks concerning the following question:

Buenas, I'm trying to find the eigenvalues and eigenvectors of a matrix H using the Householder Method. Math::MatrixReal has many functions for this , one of them is sym_diagonalize(). The problem is that I use PDL to define H and when I run the program I get this error " Can't locate object method "sym_diagonalize" via package "PDL" ". Can't I use both modules in the same code or there is a mistake on how Im calling the functions?

use warnings; use strict; use PDL; use Math::MatrixReal; #Parámetros my $epsilon=4.52; my $d0=0.0030; my $Vprim=5; my $Dprim=4; #D/d0 #operadores P y X (NxN=15) my $P=(pdl[[ 0, -sqrt(1),0,0,0,0,0,0,0,0,0,0,0,0,0], [sqrt(1),0, -sqrt(2),0,0,0,0,0,0,0,0,0,0,0,0], [0, sqrt(2),0,-sqrt(3),0,0,0,0,0,0,0,0,0,0,0], [0,0,sqrt(3),0,-sqrt(4),0,0,0,0,0,0,0,0,0,0], [0,0,0,sqrt(4),0,-sqrt(5),0,0,0,0,0,0,0,0,0], [0,0,0,0,sqrt(5),0,-sqrt(6),0,0,0,0,0,0,0,0], [0,0,0,0,0,sqrt(6),0,-sqrt(7),0,0,0,0,0,0,0], [0,0,0,0,0,0,sqrt(7),0,-sqrt(8),0,0,0,0,0,0], [0,0,0,0,0,0,0,sqrt(8),0,-sqrt(9),0,0,0,0,0], [0,0,0,0,0,0,0,0,sqrt(9),0,-sqrt(10),0,0,0,0], [0,0,0,0,0,0,0,0,0,sqrt(10),0,-sqrt(11),0,0,0], [0,0,0,0,0,0,0,0,0,0,sqrt(11),0,-sqrt(12),0,0], [0,0,0,0,0,0,0,0,0,0,0,sqrt(12),0,-sqrt(13),0], [0,0,0,0,0,0,0,0,0,0,0,0,sqrt(13),0,-sqrt(14)], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,sqrt(14)] ]); my $X=(pdl[[0,sqrt(1),0,0,0,0,0,0,0,0,0,0,0,0,0], [sqrt(1),0, sqrt(2),0,0,0,0,0,0,0,0,0,0,0,0], [0, sqrt(2),0,sqrt(3),0,0,0,0,0,0,0,0,0,0,0], [0,0,sqrt(3),0,sqrt(4),0,0,0,0,0,0,0,0,0,0], [0,0,0,sqrt(4),0,sqrt(5),0,0,0,0,0,0,0,0,0], [0,0,0,0,sqrt(5),0,sqrt(6),0,0,0,0,0,0,0,0], [0,0,0,0,0,sqrt(6),0,sqrt(7),0,0,0,0,0,0,0], [0,0,0,0,0,0,sqrt(7),0,sqrt(8),0,0,0,0,0,0], [0,0,0,0,0,0,0,sqrt(8),0,sqrt(9),0,0,0,0,0], [0,0,0,0,0,0,0,0,sqrt(9),0,sqrt(10),0,0,0,0], [0,0,0,0,0,0,0,0,0,sqrt(10),0,sqrt(11),0,0,0], [0,0,0,0,0,0,0,0,0,0,sqrt(11),0,sqrt(12),0,0], [0,0,0,0,0,0,0,0,0,0,0,sqrt(12),0,sqrt(13),0], [0,0,0,0,0,0,0,0,0,0,0,0,sqrt(13),0,sqrt(14)], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,sqrt(14)] ]); # #trucamiento de H my $j=<STDIN>; #cambio la dimensión #parte 1 , selecciono corto columnas my $x1=slice($X,"0:$j:1"); my $p1=slice($P,"0:$j:1"); #parte 2 , selecciono corto filas my $k=0; my @index; while($k<$j+1){ push @index,$k; $k=$k+1; }; #operadores de dimensión $jx$j my $p2=$p1->dice_axis(1,[@index]); my $x2=$x1->dice_axis(1,[@index]); #verificando #print "$p2\n$x2\n"; my $a=$x2 x $x2; my $b= $x2 x $x2 x $x2 x $x2; my $c= $p2 x $p2; #print "$a\n$b\n$c\n"; my $H= -(($c)/4) + 4*($Vprim/($Dprim**4))*($b) - 4*($Vprim/($Dprim**2) +)*($a); my $l; my $v; ($l, $v) = $H->sym_diagonalize();

Replies are listed 'Best First'.
Re: PDL & Math::MatrixReal
by hippo (Bishop) on Nov 05, 2021 at 16:17 UTC

    You cannot call a method on an object which does not support that method. Your $H is not a Math::MatrixReal object so it does not support the sym_diagonalize method. Here's a trivial illustration:

    #!/usr/bin/env perl use strict; use warnings; use Math::MatrixReal; use CGI; # For example my $cgi = CGI->new; my $whassat = 'CGI'; print "\$cgi is an object of class $whassat\n" if $cgi->isa ($whassat) +; eval { my @res = $cgi->sym_diagonalize; }; # This will fail print $@ if $@; my $mmr = Math::MatrixReal->new_from_rows ( [[ 1 .. 3 ], [ 2, -99, 2 ] +, [ 3, 2, -7]] ); $whassat = 'Math::MatrixReal'; print "\$mmr is an object of class $whassat\n" if $mmr->isa ($whassat) +; my @res = $mmr->sym_diagonalize; # This will succeed print "First Eigenvalue: @{$res[0]->[0][0]}\n";

    If you copy-convert your $H into a Math::MatrixReal object then you can call sym_diagonalize on it.


    🦛

Re: PDL & Math::MatrixReal
by Fletch (Bishop) on Nov 05, 2021 at 16:27 UTC

    Just because both classes are a representation of a matrix doesn't mean any method will work on it; you can't ask a cat to bark or a dog to meow.

    Well, you can. Just not going to do anything as you've discovered.

    Unless you've got a reason for switching back and forth you're going to need to pick a representation and use that one; sounds like for your particular application between your two choices Math::MatrixReal may support more of the operations you need natively. Otherwise your choices are to implement what you need using PDL (I'm not finding easy hits looking for "pdl matrix diagonalize"), or convert from the one to the other, get the diagonal, then convert back. The first option's likely to be more efficient, but if you only need to go back and forth once or twice it may be worth the performance hit to not have to bother reimplementing things.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: PDL & Math::MatrixReal
by pryrt (Abbot) on Nov 05, 2021 at 16:25 UTC
    As ++hippo said, you cannot use the methods from one completely separate object type on another.

    If you are using PDL, so your data is already in that form, then you should use PDL methods... and PDL has a plethora of matrix operations, as matrices are one of its primary reasons for existing. For example, I think that eigens_sym or eigens is mostly likely going to give you the information you want.

      There is a PDL implementation of the Householder Method, but it's not on CPAN. I think you can install it using:
      cpanm https://github.com/run4flat/PDL-Fit-OO.git
      but I haven't tried it.
Re: PDL & Math::MatrixReal
by perlfan (Vicar) on Nov 05, 2021 at 19:14 UTC
    Quick note: PDL has a users mailing list and also in irc.perl.org under #pdl - friendly and responsive.