(a[0][0] + a[0][1]) (a[1][0] + a[1][1]) (a[2][0] + a[2][1]) ... (a[N-1][0] + a[N-1][1])for which I'm trying to find general expressions for the 2^N terms involved when this is all multiplied out. Getting an expression for two of the terms is straightforward when the 2nd indices of the a coefficients are the same:
$C[0] = 1;
$C[$N-1] = 1;
for ($i=0; $i<$N; $i++) {
$C[0] *= $a->[$i]->[0];
$C[$N-1] *= $a->[$i]->[1];
}
but I'm stuck on the problem of getting the other
terms. Can someone see a way to do this? Thanks.
my $prod = 1; # multiplicative identity, of course
for ( @a )
{
my($x,$y) = @$_;
$prod *= $x + $y;
}
That does what you describe, but it's not 2^N. Not sure where the discrepancy lies...
my $mul = 1;
foreach my $i (@$ar) {
my $sum = 0;
foreach my $j (@$i) {
$sum += $j;
}
$mul *= $sum;
}
( arr[0][0] + arr[0][1] ) ( arr[1][0] + arr[1][1] )what I want to find is
C[0] = arr[0][0] arr[1][0] C[1] = arr[0][0] arr[1][1] C[2] = arr[0][1] arr[1][0] C[3] = arr[0][1] arr[1][1]It doesn't matter if the coefficients come out in this order, of course.
Your description does not adequately explain what you want, particularly the (a[N-1][0] + a[N-1][1]).
Indices from your example:
0,0 1,0 0,0 1,1 0,1 1,0 0,1 1,1Don't follow. They should be:
0,0 1,0 0,0 1,1 1,0 1,0 1,1 1,1 2,0 1,0 2,1 1,1 3,0 1,0 3,1 1,1 ...The wrong element is incrementing -- a[0][N-1] * a[1][0], a[0][N-1] * a[1][1].
Furthermore, this makes no sense. Are a[0][1] and a[1][1] use repeatedly throughout? If so, why not change them into constants?
Celebrate Intellectual Diversity
If 2^N could become m^n, then you could use a recursive solution:
#! perl -slw
use strict;
sub expand{
return @{ $_[0] } if @_ == 1;
map{
my $x = $_;
my @part = expand( @_ );
map{ $x * $_ } @part;
} @{ pop @_ };
}
my @mat = ( [ -1, 2 ], [ 3, -4 ] );
printf +("%s " x @mat ) . '= ', map{ "[ @$_ ] " } @mat;
print join ' ', expand( @mat );
@mat = ( [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], );
printf +("%s " x @mat ) . '= ', map{ "[ @$_ ] " } @mat;
print join ' ', expand( @mat );
@mat = ( [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ], );
printf +("%s " x @mat ) . '= ', map{ "[ @$_ ] " } @mat;
print join ' ', expand( @mat );
__END__
P:\test>junk
[ -1 2 ] [ 3 -4 ] = -3 6 4 -8
[ 1 2 ] [ 3 4 ] [ 5 6 ] = 15 30 20 40 18 36 24 48
[ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] = 28 56 84 35 70 105 42 84 126 32 64 96 40 80 120 48 96 144 36 72 108 45 90 135 54 108 162
my $n = $ARGV[0] || 5;
my @terms = qw( a[0][0] a[0][1] );
foreach my $i (1 .. $n) {
@terms = map { ("$_ a[$i][0]","$_ a[$i][1]") } @terms;
}
foreach my $i (0 .. $#terms) {
print "term[$i] = $terms[$i]\n";
}
term[0] = a[0][0] a[1][0] a[2][0] term[1] = a[0][0] a[1][0] a[2][1] term[2] = a[0][0] a[1][1] a[2][0] term[3] = a[0][0] a[1][1] a[2][1] term[4] = a[0][1] a[1][0] a[2][0] term[5] = a[0][1] a[1][0] a[2][1] term[6] = a[0][1] a[1][1] a[2][0] term[7] = a[0][1] a[1][1] a[2][1]So perhaps I have an off-by-one error, but certainly I'm generating 2^N terms.
[a1...an]' * [b1...bn] = [a1*b1 ... a1*bn; ...; an*b1 ... an*bn]which can be written "a_i * b_j" using physicists' tensor notation. For two 2-dimensional terms (i.e. matrices) you have a tensor product like "a_ij * b_kl", and you can generalize this to any rank (and to other operations besides "*"). I think [cpan://PDL] can compute outer products for low ranks, but you'll probably need to create an iterator or some such to avoid running out of memory with higher ranks.
#!/usr/bin/perl -wl
use strict;
use Data::Dumper;
my $N = 4;
my $size = 32;
my $arr = [[1, 2],
[3, 4],
[5, 6],
[7, 8]];
my @C;
foreach my $m (0..2**$N - 1) {
my $vec = "";
vec($vec, 0, $size) = $m;
my @bits = split(//, unpack("B*", $vec));
splice(@bits, 0, $size - $N);
# so @bits now contains the binary expansion of $m
# with exactly $N bits, as you can verify by uncommenting
# print join "::", @bits;
$C[$m] = 1;
# now we multiply the $N terms $arr->[i][j]
# where j is the i-th bit in the binary expansion of $m
$C[$m] *= $arr->[$_][$bits[$_]] for 0..$N-1;
}
print Dumper \@C;
also, this works for $N no more than 31(32?) - but you may have other problems (memory say), if you want to go above that.
Hope this helps.Are you multiplying polynomials? Taking the square root of a hamiltonian? Calculating the angular velocity of a catapulted gerbil? :)
Maybe it would help if you would link to an article describing the process you are trying to model in perl.
The problem arises in something we're looking at involving quantum entanglement - each of the a[i][0] + a[i][1] terms (i=0, 1, 2, ..., N-1) represents a two-level quantum state. N such terms multiplied together thus represents a product state of N two-level states. We're then seeing if a general state can be written in this form - if it cannot, then the degree to which it can't is a measure of the degree of entanglement.
I apologize if the motivation wasn't clear. At a mathematical level, it's a problem of multiplying N polynomials, each of which has two terms:
For N=2:
(a+b)*(c+d) = ac + ad + bc + bd
For N=3:
(a+b)*(c+d)*(e+f) = ace + acf + ade + adf +
+ bce + bcf + bde + bdf
What I was after was an explicit expression for
each of the 2**N
terms on the right-hand-side of these equations.
As for why one would want to do this beyond a homework question, this problem arises in theories of quantum computing, particularly in trying to write an arbitrary state in terms of what's called the computational basis for an N-qubit state.
#!/your/perl/here
use strict;
use warnings;
{ # closure for sub terms
my @term_list = ('A'..'Z', 'a'..'z');
sub terms
{
my $N = shift;
my $last = 2*$N-1;
my @pairs;
my $index = 0;
my $globber = '';
while ( $index < $last )
{
$globber .= '{'
. $term_list[$index++]
. ','
. $term_list[$index++]
. '}';
}
my $terms = join ' + ', glob($globber);
return $terms;
}
} # end closure for sub terms
foreach my $n (1..5)
{
my $terms = terms($n);
print "N=$n: <", $terms, ">\n";
}
exit;
__OUTPUT__
N=1:
N=2:
N=3:
N=4:
N=5:
-QM
--
Quantum Mechanics: The dreams stuff is made of
However, the module Math::Combinatorics can still be used to iterate through the 2**N subsets as well as the nCr combinations and the N! permutations.
Thank you, for pointing me to the "factorial"
Note to self: Don't transfer mathematical/technical terms from German to English without consulting a dictionary first.
Also, would you be able to give example code for the subset iteration with Math::Combinatorics?
If there is an easy way to do so, it has escaped me.
The closest I saw in the docs was that example to generate:
"Morse signals: diferent signals of 3 positions using the two symbols - and .".
Now Morse signals of length 3 are surely one-to-one and onto the subsets of a 3 element set (set elements = pos in signal; element not/contained = dot/dash)
This iteration is like computing 2**n as sumk=0..n nCk
At least this is not trivial application of the modules methods.
There are plenty of other iterators out there that give all the subsets, though - [cpan://List::PowerSet], [cpan://Data::PowerSet], [cpan://Algorithm::ChooseSubsets] - We just have to convert them to give a bit mask instead - ie:
use List::PowerSet qw/powerset_lazy/;
my @set = (0) x $N;
my @C = (1) x 2**$N;
my $M = 0;
my $ps_itr = powerset_lazy(0 .. $N-1);
while (my $ref_set = $ps_itr->()) {
$_ = 1 for local @set[@$ref_set];
$C[ $M ] *= $arr->[ $_ ][ $set[$_] ] for 0 .. $N-1;
$M++;
}
Everything but the troll
perlmonks.org content © perlmonks.org and BrowserUk, BUU, choedebeck, DungeonKeeper, educated_foo, ikegami, InfiniteSilence, ivancho, jdporter, pKai, QM, randyk, runrig, Scott7477, tphyahoo, trammell
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03