Spoiler alert: If you participate in The Weekly Challenge, don't read further if you haven't solved week 170 yet.

Kronecker product is a matrix operation that uses elements of one matrix to multiply the second matrix. Mohammad shows this example:

A = [ 1 2 ] [ 3 4 ] B = [ 5 6 ] [ 7 8 ] A x B = [ 1 x [ 5 6 ] 2 x [ 5 6 ] ] [ [ 7 8 ] [ 7 8 ] ] [ 3 x [ 5 6 ] 4 x [ 5 6 ] ] [ [ 7 8 ] [ 7 8 ] ] = [ 1x5 1x6 2x5 2x6 ] [ 1x7 1x8 2x7 2x8 ] [ 3x5 3x6 4x5 4x6 ] [ 3x7 3x8 4x7 4x8 ] = [ 5 6 10 12 ] [ 7 8 14 16 ] [ 15 18 20 24 ] [ 21 24 28 32 ]

When I saw matrices, I immediately thought PDL. After finding a solution, I tried searching for existing solutions, and found the following at Rosetta Code:

#!/usr/bin/perl use strict; use warnings; use PDL; use PDL::NiceSlice; sub kron{ my $A = shift; my $B = shift; my ($r0, $c0) = $A->dims; my ($r1, $c1) = $B->dims; my $kron = zeroes($r0 * $r1, $c0 * $c1); for(my $i = 0; $i < $r0; ++$i){ for(my $j = 0; $j < $c0; ++$j){ $kron( ($i * $r1) : (($i + 1) * $r1 - 1), ($j * $c1) : (($j + 1) * $c1 - 1) ) .= $A($i,$j) * $B; } } return $kron; }

Wait, loops? The whole point of PDL is to hide loops. And indeed, my solution doesn't involve them. Also, a benchmark shows my solution is more than twice faster than the Rosetta Code one.

I'm far from an expert on PDL or matrices in general. But it seems we can easily multiply each element in a matrix by the same number, but it's not so easy to multiply them by different numbers. But we can multiply each element by a matrix, so we just need to "inflate" the matrix, so instead of

[ 1 2 ] [ 3 4 ]

we'd have

[ 1 1 ] [ 2 2 ] [ 1 1 ] [ 2 2 ] [ 3 3 ] [ 4 4 ] [ 3 3 ] [ 4 4 ]

That's what dummy does (two dummies, in fact, one in each dimension). Multiplying this with the second matrix gives us a result that has all the expected numbers, but a bit different dimensions.

[ 5 6 ] [ 10 12 ] [ 7 8 ] [ 14 16 ] [ 15 18 ] [ 20 24 ] [ 21 24 ] [ 28 32 ]

Fortunately, PDL has all the needed methods to reshuffle the submatrices into the expected result.

It seems correct (it passes the test shown in the challenge and in the Wikipedia page), but my PDL is not so strong. Maybe it can be further improved?

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

In reply to Kronecker Product by choroba

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.