0

次のメソッドを含む Perl プログラムがあります。

  • detマトリックスの行列式を見つけること。
  • identityMatrix n 行 n 列の単位行列を返します (主対角線に 1、残りは 0)。
  • matrixAdd 2 つの行列を一緒に加算します。
  • matrixScalarMultiply整数に行列を掛けること。

たとえば、行列A - Iの行列式を簡単に見つけることができます。

ここに画像の説明を入力

(0です)

しかし、 A-RIの行列式を見つけたい場合はどうすればよいでしょうか。

ここに画像の説明を入力

この場合、整数値ではなく、次の行に沿って特性多項式解 (別名、変数を含む行列式) を解くプログラムを作成します。

ここに画像の説明を入力

これを処理する方法について何か提案はありますか? 以下のコード:

#!/usr/bin/perl
#perl Solver.pl

use strict;
use warnings;

### solve the characteristic polynomial det(A - RI) 

my @A = ( # 3x3, det = -3
   [1, 3, -3],
   [1, 0, 0],
   [0, 1, 0],
);

# test_matrix = A - I
my $test_matrix = matrixAdd( \@A, 
    matrixScalarMultiply( identityMatrix(3), -1 ) );

print "\nTest:\n";
for( my $i = 0; $i <= $#$test_matrix; $i++ ){ 
    print "[";
    for( my $j = 0; $j <= $#$test_matrix; $j++ ){
        $j == $#$test_matrix ? print $test_matrix->[$i][$j], "]\n" : 
            print $test_matrix->[$i][$j], ", ";
    }
}

my $dd = det ($test_matrix);
print "det = $dd \n";



# recursively find determinant of a real square matrix
# only call on n by n matrices where n >= 2
#
# arg0 = matrix reference
sub det{
    my ($A) = @_;

    #base: 2x2 matrix
    if( $#$A + 1 == 2 ){ #recall $#$A == last index of A
        return $A->[0][0]*$A->[1][1] - $A->[1][0]*$A->[0][1];
    }

    #cofactor expansion for matrices > 2x2
    my $answer = 0;
    for( my $col = 0; $col <= $#$A; $col++ ){
        my $m = (); #sub matrix
        my $multiplier = $A->[0][$col];
        if( $col % 2 == 1 ){    #+, -, +, -, ...
            $multiplier *= -1;
        }

        for( my $i = 1; $i <= $#$A; $i++ ){ 
            #j is indexer for A, k for m
            for( my ($j, $k) = (0, 0); $j <= $#$A; $j++ ){
                $m->[$i-1][$k++] = $A->[$i][$j] unless $j == $col;
            }
        }

        $answer += $multiplier*det( $m );
    }#end cofactor expansion

    return $answer;
}#end det()


# return reference to an n by n identity matrix
# can do this in Perl!
#
# arg0 = dimension 'n'
sub identityMatrix{
    my $n = shift;
    my @ret;

    for (my $i = 0; $i < $n; $i++ ){
        for (my $j = 0; $j < $n; $j++ ){
            $ret[$i][$j] = $i == $j ? 1 : 0;
        }
    }

    return \@ret;   
}


# return reference to an n by n matrix which is the sum
# of two different n by n matrices, "a" and "b"
#
# arg0, 1 = references to the pair of matrices to add
sub matrixAdd{
    my @ret;
    my ($a, $b) = ($_[0], $_[1]);

    for (my $i = 0; $i <= $#$a; $i++ ){
        for (my $j = 0; $j <= $#$a; $j++ ){
            $ret[$i][$j] = $a->[$i][$j] + $b->[$i][$j];
        }
    }

    return \@ret;
}


# return reference to a matrix multiplied by a given scalar
#
# arg0 = reference to matrix
# arg1 = scalar to multiply by
sub matrixScalarMultiply{
    my @ret;
    my ($a, $multiplier) = ($_[0], $_[1]);

    for (my $i = 0; $i <= $#$a; $i++ ){
        for (my $j = 0; $j <= $#$a; $j++ ){
            $ret[$i][$j] = $a->[$i][$j] * $multiplier;
        }
    }

    return \@ret;
}
4

1 に答える 1