perlcartesian-productpdl

How to perform cartesian product in PDL


I want to take an arbitrary 1D vector a = [k] and b = [m] and form the matrix of ordered pairs c = [2 x k x m] such that $c->(:,(i),(j)) = [ $a->(i), $b->(j) ]. I.e. the set of all ordered pairs of the elements in a and b a.k.a the cartesian product.

Of course I could use a loop and the [glue] function to accomplish this, but that isn't in the spirit of Perl/PDL. Is there a fancy method that involves slices, dummy dimensions, and glue that gets me there?

Also, using Math::Cartesian::Product (as answered here: In Perl, how can I get the Cartesian product of multiple sets? is cheating! :3 I want straight perl/PDL and hopefully learn something in the process.


Solution

  • I got something that meets my criteria:

    my $a = pdl 1,2,3,4;
    my $b = pdl 5,6,7;
    print "a = $a\n";
    print "b = $b\n";
    print "dummy dimensioned:\n";
    $a = $a->dummy(0,$b->dim(0));
    print "a".$a->shape." = $a\n";
    
    $b = $b->dummy(0, $a->dim(1))->transpose;
    print "b".$b->shape." = $b\n";
    
    print "Glued together:\n"
    my $c = $a->dummy(0,1)->glue(0, $b->dummy(0,1));
    print "c".$c->shape." = $c\n";
    

    a = [1 2 3 4]  
    b = [5 6 7]  
    dummy dimensioned:  
    a[3 4] = 
    [
     [1 1 1]
     [2 2 2]
     [3 3 3]
     [4 4 4]
    ]
    
    b[3 4] = 
    [
     [5 6 7]
     [5 6 7]
     [5 6 7]
     [5 6 7]
    ]  
    Glued together:  
    c[2 3 4] = [[[1 5][1 6][1 7]][[2 5][2 6][2 7]][[3 5][3 6][3 7]][[4 5][4 6][4 7]]]