Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

matrix multiplication

by etheral (Acolyte)
on Nov 18, 2011 at 16:49 UTC ( [id://938880]=perlquestion: print w/replies, xml ) Need Help??

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

#################################################################### ## MAIN #################################################################### my $x = [ [ 3, 2, 3 ], [ 5, 9, 8 ], ]; my $y = [ [ 4, 7 ], [ 9, 3 ], [ 8, 1 ], ]; my $z = get_multiplied_matrix($x, $y); print "$z\n"; #################################################################### ## SUBS #################################################################### sub get_multiplied_matrix { my ($matrix_1, $matrix_2) = @_; my ($matrix_1_rows, $matrix_1_columns) = matrix_dimension($matrix_1) +; my ($matrix_2_rows, $matrix_2_columns) = matrix_dimension($matrix_2) +; unless ($matrix_1_columns == $matrix_2_rows) { die "Matrices don't match: $matrix_1_columns != $matrix_2_rows"; } my $result = []; my ($i, $j, $k); for $i (range($matrix_1_rows)) { for $j (range($matrix_2_columns)) { for $k (range($matrix_1_columns)) { $result->[$i][$j] += $matrix_1->[$i][$k] * $matrix_2->[$k][$j]; } } } return $result; } sub range { 0 .. ($_[0] - 1) } sub vector_length { my $array_reference = $_[0]; my $type = ref $array_reference; if ($type ne "ARRAY") { die "$type is bad array ref for $array_refer +ence" } return scalar(@$array_reference); } sub matrix_dimension { my $matrix = $_[0]; my $rows = vector_length($matrix); my $columns = vector_length($matrix->[0]); return ($rows, $columns); }

I would like to print a matrix, not an array reference. Could you tell me how to do this? (it's my worst perl nightmare, tried to do something myself but successfully failed every time)

Replies are listed 'Best First'.
Re: matrix multiplication
by luis.roca (Deacon) on Nov 18, 2011 at 18:25 UTC

    Hi etheral,
    A slightly less involved solution may be trying Math::Matrix instead.

    #!/perl use strict; use warnings; use diagnostics; use Math::Matrix; my $x = new Math::Matrix ( [ 3, 2, 3 ], [ 5, 9, 8 ], ); my $y = new Math::Matrix ( [ 4, 7 ], [ 9, 3 ], [ 8, 1 ], ); my $z = $x->multiply($y); print "$z\n"; __END__ 54.00000 30.00000 165.00000 70.00000


    "...the adversities born of well-placed thoughts should be considered mercies rather than misfortunes." — Don Quixote
Re: matrix multiplication
by hbm (Hermit) on Nov 18, 2011 at 17:17 UTC
    my $x = [ [ 3, 2, 3 ], [ 5, 9, 8 ], ]; print "@$_\n" for @$x; # prints 3 2 3 5 9 8
Re: matrix multiplication
by johnny_carlos (Scribe) on Nov 18, 2011 at 17:01 UTC
    The easy way:
    use Data::Dumper; print Dumper $z;
Re: matrix multiplication
by ambrus (Abbot) on Nov 19, 2011 at 17:48 UTC

    Here's a fun way to test your matrix multiplication program.

    Choose a natural number $N, the size of your matrices. Here, I'll use

    our $N = 6;
    for brevity, but I recommend $N = 10; for your tests.

    Create the triangular matrices C and I with the following recursive constructions.

    our $C; for my $k (0 .. $N - 1) { for my $l (0 .. $N - 1) { my $e; if (0 == $k) { if (0 == $l) { $e = 1; } else { $e = 0; } } else { $e = 0; if (0 < $l) { $e += $$C[$k-1][$l-1]; } if ($l < $N - 1) { $e += $$C[$k-1][$l+1]; } } $$C[$k][$l] = $e; } } our $U; for my $k (0 .. $N - 1) { for my $l (0 .. $N - 1) { my $e; if (0 == $k) { if (0 == $l) { $e = 1; } else { $e = 0; } } elsif (1 == $k) { if (1 == $l) { $e = 2; } else { $e = 0; } } else { $e = -$$U[$k-2][$l]; if (0 < $l) { $e += 2 * $$U[$k-1][$l-1]; } } $$U[$k][$l] = $e; } }

    This will look something like this.

    =begin output C = ( 1 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 2 0 1 0 0 2 0 3 0 1 0 0 5 0 4 0 1 ) U = ( 1 0 0 0 0 0 0 2 0 0 0 0 -1 0 4 0 0 0 0 -4 0 8 0 0 1 0 -12 0 16 0 0 6 0 -32 0 32 ) =end output

    Now compute the matrix product C·CT, where CT is the transpose of C. For this, you'll of course need to write a matrix transposition function, but that should be easier than the matrix multiplication function.

    You should get a matrix like this:

    C*C^T = ( 1 0 1 0 2 0 0 1 0 2 0 5 1 0 2 0 5 0 0 2 0 5 0 14 2 0 5 0 14 0 0 5 0 14 0 42 )
    Note that any antidiagonal of this matrix contains the same number in all positions. This should be true for larger $N as well. If it's not, then either you have made a mistake in one of your functions, or I have made a mistake in this description.

    Further, compute the matrix C·U. You should get a diagonal matrix.

      Many-core Engine for Perl (MCE) comes with several examples demonstrating matrix multiplication in parallel across many cores. The readme contains benchmark results as well.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://938880]
Approved by keszler
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (2)
As of 2024-04-24 23:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found