On Mon, 9 Aug 2010 20:25:53 -0700 (PDT), David <> wrote:
>All,
>
>I have no experience with Perl modules that do linear algebra. I've
>searched CPAN and see several.
>
>Can someone advise me on what to use? I'd like to have the ability to
>start with a matrix with integer entries, put it in reduced row
>echelon form, with all of the entries as rational numbers, such as:
>
>
>A =
>
> 4 0 0 2
> -1 -3 0 1
> 0 2 0 -1
>
>
>ans =
>
> 1 0 0 1/2
> 0 1 0 -1/2
> 0 0 0 0
>
>Suggestions? This has to be in perl.
>
>D.
Try this, only tested on your matrix.
And the swapped rows (redo) didn't come into
play on your matrix. I just guess its a redo
but don't know.
Code is based on Pseudo code from wikipedia.
-sln
---------------------------
use strict;
use warnings;
#
my @Matrix = (
[ 4, 0, 0, 2 ],
[ -1, -3, 0, 1 ],
[ 0, 2, 0, -1 ],
);
my @Mreduced = GetReducedRowEchelonForm( @Matrix);
print "\n";
print "@{$_}\n" for (@Matrix);
print "------ \n";
print "@{$_}\n" for (@Mreduced);
exit;
#
sub GetReducedRowEchelonForm
{
return () unless
@_ && ref $_[0] eq "ARRAY";
my @M;
for my $k (0 .. $#_) {
$M[$k] = [@{$_[$k]}];
}
my $lead = 0;
my $rowCount = @M - 1;
my $columnCount = @{$M[0]} - 1;
FUNC:
for my $r (0 .. $rowCount)
{
last FUNC if $columnCount <= $lead;
my $i = $r;
while( $M[$i][$lead] == 0) {
$i++;
if ( $rowCount == $i) {
$i = $r;
$lead++;
last FUNC if $columnCount == $lead;
}
last FUNC if $i > $rowCount;
}
if ($i != $r) {
my $irow = $M[$i];
$M[$i] = $M[$r];
$M[$r] = $irow;
redo FUNC; # swapped rows, should we redo? Don't know.
}
my $divisor = $M[$r][$lead];
foreach my $rowval ( @{$M[$r]} ) {
$rowval /= $divisor;
}
for $i (0 .. $rowCount) {
if ($i != $r) {
my $multiplier = $M[$i][$lead];
for my $ndx (0 .. $columnCount) {
$M[$i][$ndx] -= $multiplier * $M[$r][$ndx];
}
}
}
$lead++;
}
return @M;
}
__END__
http://en.wikipedia.org/wiki/Row_echelon_form
The following pseudocode converts a matrix to reduced row-echelon form:
function ToReducedRowEchelonForm(Matrix M) is
lead := 0
rowCount := the number of rows in M
columnCount := the number of columns in M
for 0 <= r < rowCount do
if columnCount <= lead then
stop function
end if
i = r
while M[i, lead] = 0 do
i = i + 1
if rowCount = i then
i = r
lead = lead + 1
if columnCount = lead then
stop function
end if
end if
end while
if i != r then Swap rows i and r
Divide row r by M[r, lead]
for 0 <= i < rowCount do
if i != r do
Subtract M[i, lead] multiplied by row r from row i
end if
end for
lead = lead + 1
end for
end function