Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Arbitrarily Many Nested Loops

Reply
Thread Tools

Arbitrarily Many Nested Loops

 
 
Jacob JKW
Guest
Posts: n/a
 
      03-30-2006
This is what I have:

-------------
#!perl

for (my $i = 0; $i<=$n_ra->[0]; $i++) {
for (my $j = 0; $j<=$n_ra->[1]; $j++) {
for (my $k = 0; $k<=$n_ra->[2]; $k++) {
$prob_ra->[$i+$j+$k] += (
$f_raa->[0]->[$i] *
$f_raa->[1]->[$j] *
$f_raa->[2]->[$k] *
);
}
}
-------------
But that's obviously messy and more imprtantly I'd like to be able to
decide at run time to have how nested levels to go (probably be on the
order of 50 or 60). I assume that there's a canonical manner in which
this should be handled (using closures I'd guess) but I can't
sufficiently summarize my issue to make it Google-able.

Any advice?


Many Thanks,
J.

 
Reply With Quote
 
 
 
 
A. Sinan Unur
Guest
Posts: n/a
 
      03-30-2006
"Jacob JKW" <> wrote in news:1143679874.629703.156690
@u72g2000cwu.googlegroups.com:

> This is what I have:
>
> -------------
> #!perl
>
> for (my $i = 0; $i<=$n_ra->[0]; $i++) {
> for (my $j = 0; $j<=$n_ra->[1]; $j++) {
> for (my $k = 0; $k<=$n_ra->[2]; $k++) {
> $prob_ra->[$i+$j+$k] += (
> $f_raa->[0]->[$i] *
> $f_raa->[1]->[$j] *
> $f_raa->[2]->[$k] *
> );
> }
> }
> -------------
> But that's obviously messy and more imprtantly I'd like to be able to
> decide at run time to have how nested levels to go (probably be on the
> order of 50 or 60). I assume that there's a canonical manner in which
> this should be handled (using closures I'd guess) but I can't
> sufficiently summarize my issue to make it Google-able.
>
> Any advice?


You need to work a little on explaining the problem and algorithm.
Neither the code snippet above nor your verbal description makes any
sense to me, but I am curious to understand why such a monstrosity is
needed.

Sinan

--
A. Sinan Unur <>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://augustmail.com/~tadmc/clpmisc...uidelines.html

 
Reply With Quote
 
 
 
 
Ilya Zakharevich
Guest
Posts: n/a
 
      03-30-2006
[A complimentary Cc of this posting was sent to
A. Sinan Unur
<>], who wrote in article <Xns9795CB63AB7DAasu1cornelledu@127.0.0.1>:
> You need to work a little on explaining the problem and algorithm.
> Neither the code snippet above nor your verbal description makes any
> sense to me


I'm afraid the problem is on your side. The explanation-by-code looks
absolutely clear to me.

Looks like there is a multi-dimensional array of unknown-in-advance
dimension. It is known that it is "rectangular"; the sizes are stored
in another vector (one size per dimension).

One wants a CONVENIENT way to run through the elements of this array.

One hint to OP: since you do not know the dimension at compile
time, you cannot be sure that the index of 1st,2nd,3rd etc
dimensions is $k, $l, $m etc. So the only solution is to have the
running index to be an array too: $I[0], $I[1], $I[3] etc.

This more or less immediately suggests a possible solution...

Hope this helps,
Ilya

P.S. One could also use Math:ari's forvec(); might be a little bit
heavy-weight solution, but maybe then you will find some use for
other functions in Math:ari too.
 
Reply With Quote
 
John W. Krahn
Guest
Posts: n/a
 
      03-30-2006
Jacob JKW wrote:
> This is what I have:
>
> -------------
> #!perl
>
> for (my $i = 0; $i<=$n_ra->[0]; $i++) {
> for (my $j = 0; $j<=$n_ra->[1]; $j++) {
> for (my $k = 0; $k<=$n_ra->[2]; $k++) {
> $prob_ra->[$i+$j+$k] += (
> $f_raa->[0]->[$i] *
> $f_raa->[1]->[$j] *
> $f_raa->[2]->[$k] *
> );
> }
> }
> -------------
> But that's obviously messy and more imprtantly I'd like to be able to
> decide at run time to have how nested levels to go (probably be on the
> order of 50 or 60). I assume that there's a canonical manner in which
> this should be handled (using closures I'd guess) but I can't
> sufficiently summarize my issue to make it Google-able.


Easy enough to do in perl:

my $index_var = 'aa';
my @var_names = map '$' . $index_var++, 0 .. $#$n_ra;

my $nested_loop = join( '',
map "\t" x $_
. 'for ( my '
. $var_names[ $_ ]
. ' = 0; '
. $var_names[ $_ ]
. ' <= $n_ra->[ '
. $_
. ' ]; '
. $var_names[ $_ ]
. "++ ) {\n", 0 .. $#$n_ra )
. "\t" x $#$n_ra
. '$prob_ra->[ '
. join( ' + ', @var_names )
. " ] +=\n"
. join( " *\n",
map "\t" x @$n_ra
. '$f_raa->[ '
. $_
. ' ]->[ '
. $var_names[ $_ ]
. ' ]', 0 .. $#$n_ra )
. "\n"
. join '', map "\t" x $_ . "}\n", reverse 0 .. $#$n_ra;

eval $nested_loop;



John
--
use Perl;
program
fulfillment
 
Reply With Quote
 
Jacob JKW
Guest
Posts: n/a
 
      03-30-2006
Ilya Zakharevich wrote:
> [A complimentary Cc of this posting was sent to
> A. Sinan Unur
> <>], who wrote in article <Xns9795CB63AB7DAasu1cornelledu@127.0.0.1>:
> > You need to work a little on explaining the problem and algorithm.
> > Neither the code snippet above nor your verbal description makes any
> > sense to me

> I'm afraid the problem is on your side. The explanation-by-code looks
> absolutely clear to me.

I was definitely a bt lacadaisical in my proofreading efforts. What I
*should* have written was:
But that's obviously messy and more imprtantly I'd like to be able to
decide at run time how many nested levels I'll need.

Possibly that's vaguely more clear.


> Looks like there is a multi-dimensional array of unknown-in-advance
> dimension. It is known that it is "rectangular"; the sizes are stored
> in another vector (one size per dimension).

You got it exactly.

[OT Description - I'm using this to create a binomial-style probability
distribution where the success probability differs between trials. For
example. If I flip n different coins, each one biased to a known
extent, m(i) times each what would the probability be of flipping x
heads?]

> One wants a CONVENIENT way to run through the elements of this array.

The way I'd put it would be that I want a way to run through the
elements of the array without having to resort to copy-and-paste.

> One hint to OP: since you do not know the dimension at compile
> time, you cannot be sure that the index of 1st,2nd,3rd etc
> dimensions is $k, $l, $m etc. So the only solution is to have the
> running index to be an array too: $I[0], $I[1], $I[3] etc.

Most definitely . I had just posted the first kludge I came up with.

> This more or less immediately suggests a possible solution...

I have to admit, I don't really see the possible solution you have in
mind here ...

> P.S. One could also use Math:ari's forvec(); might be a little bit
> heavy-weight solution, but maybe then you will find some use for
> other functions in Math:ari too.

Self-promote much?

 
Reply With Quote
 
Jacob JKW
Guest
Posts: n/a
 
      03-30-2006
David Formosa (aka ? the Platypus) wrote:
> On 29 Mar 2006 16:51:14 -0800, Jacob JKW <> wrote:
> > This is what I have:
> >
> > -------------
> > #!perl
> >
> > for (my $i = 0; $i<=$n_ra->[0]; $i++) {
> > for (my $j = 0; $j<=$n_ra->[1]; $j++) {
> > for (my $k = 0; $k<=$n_ra->[2]; $k++) {
> > $prob_ra->[$i+$j+$k] += (
> > $f_raa->[0]->[$i] *
> > $f_raa->[1]->[$j] *
> > $f_raa->[2]->[$k] *
> > );
> > }
> > }
> > -------------
> > But that's obviously messy and more imprtantly I'd like to be able to
> > decide at run time to have how nested levels to go (probably be on the
> > order of 50 or 60). I assume that there's a canonical manner in which
> > this should be handled (using closures I'd guess) but I can't
> > sufficiently summarize my issue to make it Google-able.

>
> I quickly worked out one way to do this, no guarties as to effeceny.
>
> sub closefor (&$@) {
> my $sub = shift;
> my $range = shift;
>
> return sub {
> for my $i (0..$range){
> $sub->($i,@_)
> }
> }
> }
>
> sub mulitloop (&@) {
> my $sub = shift;
> for (@_) {
> my $oldsub = $sub;
> $sub = closefor {$oldsub->(@_)} $_;
> }
> $sub->();
> }
>
> Your code becomes
>
> mulitloop { my $i = shift;
> my $j = shift;
> my $k = shift;
> $prob_ra->[$i+$j+$k] += $f_raa->[0]->[$i] *
> $f_raa->[1]->[$j] *
> $f_raa->[2]->[$k]
> } @$n_ra;
>
> To convert the algorithm into something that does arbitrarily depth
> involves a small reworking the insides so that it works with an
> arbitrary number of arguments.
>
> mulitloop {
> my $sum = 0;
> my $product = 1;
> for (my $i; $i<=@#_; $i++) {
> $sum += $_[$i];
> $product *= $f_raa->[$i]->[$_[$i]];
> }
> $prob_ra->[$sum] += $product;
> } @$n_ra;
>

I made a few synactical changes but it worked out beautifully. Thank
you very, very much for that.
(Thanks to Jim Gibson and John Krahn who both answered my post as well,
for no particularly good reason I didn't get a chance to try out either
of their code samples.)


> --
> Please excuse my spelling as I suffer from agraphia. See
> http://dformosa.zeta.org.au/~dformosa/Spelling.html to find out more.

Do you think if I became agraphic I could become as good a programmer
as you?

 
Reply With Quote
 
Ron Savage
Guest
Posts: n/a
 
      03-30-2006
On Thu, 30 Mar 2006 13:54:58 +1000, Jacob JKW wrote:

Hi Jacob

Glad to see you obtained a solution.

Just for the record, this was discussed in a book by the Australianprogrammer
Ian Oliver:

Programming Classics
Ian Oliver
Prentice Hall
1993
0-13-100413-1
Section 4.3 Page 87
Computing sub-subtotals within subtotals within totals to any depth


 
Reply With Quote
 
Jacob JKW
Guest
Posts: n/a
 
      03-30-2006

David Formosa (aka ? the Platypus) wrote:
> On 29 Mar 2006 16:51:14 -0800, Jacob JKW <> wrote:
> > This is what I have:
> >
> > -------------
> > #!perl
> >
> > for (my $i = 0; $i<=$n_ra->[0]; $i++) {
> > for (my $j = 0; $j<=$n_ra->[1]; $j++) {
> > for (my $k = 0; $k<=$n_ra->[2]; $k++) {
> > $prob_ra->[$i+$j+$k] += (
> > $f_raa->[0]->[$i] *
> > $f_raa->[1]->[$j] *
> > $f_raa->[2]->[$k] *
> > );
> > }
> > }
> > -------------
> > But that's obviously messy and more imprtantly I'd like to be able to
> > decide at run time to have how nested levels to go (probably be on the
> > order of 50 or 60). I assume that there's a canonical manner in which
> > this should be handled (using closures I'd guess) but I can't
> > sufficiently summarize my issue to make it Google-able.

>
> I quickly worked out one way to do this, no guarties as to effeceny.
>
> sub closefor (&$@) {
> my $sub = shift;
> my $range = shift;
>
> return sub {
> for my $i (0..$range){
> $sub->($i,@_)
> }
> }
> }
>
> sub mulitloop (&@) {
> my $sub = shift;
> for (@_) {
> my $oldsub = $sub;
> $sub = closefor {$oldsub->(@_)} $_;
> }
> $sub->();
> }
>
> Your code becomes
>
> mulitloop { my $i = shift;
> my $j = shift;
> my $k = shift;
> $prob_ra->[$i+$j+$k] += $f_raa->[0]->[$i] *
> $f_raa->[1]->[$j] *
> $f_raa->[2]->[$k]
> } @$n_ra;
>
> To convert the algorithm into something that does arbitrarily depth
> involves a small reworking the insides so that it works with an
> arbitrary number of arguments.
>
> mulitloop {
> my $sum = 0;
> my $product = 1;
> for (my $i; $i<=@#_; $i++) {
> $sum += $_[$i];
> $product *= $f_raa->[$i]->[$_[$i]];
> }
> $prob_ra->[$sum] += $product;
> } @$n_ra;
>
> --

You know as clever and elegant as this method is, it actually runs
significantly than my original ugly cut-and-paste style, which I
suppose shouldn't have come as any surprise as when is elegance ever
free?

Anyway, I'm going to keep this code for further use and some later
date, but I eventyually went with John Krahn eval method posted above.
Ugly but fast,

Thanks again for your help.

 
Reply With Quote
 
Jacob JKW
Guest
Posts: n/a
 
      03-30-2006

John W. Krahn wrote:
> Jacob JKW wrote:
> > This is what I have:
> >
> > -------------
> > #!perl
> >
> > for (my $i = 0; $i<=$n_ra->[0]; $i++) {
> > for (my $j = 0; $j<=$n_ra->[1]; $j++) {
> > for (my $k = 0; $k<=$n_ra->[2]; $k++) {
> > $prob_ra->[$i+$j+$k] += (
> > $f_raa->[0]->[$i] *
> > $f_raa->[1]->[$j] *
> > $f_raa->[2]->[$k] *
> > );
> > }
> > }
> > -------------
> > But that's obviously messy and more imprtantly I'd like to be able to
> > decide at run time to have how nested levels to go (probably be on the
> > order of 50 or 60). I assume that there's a canonical manner in which
> > this should be handled (using closures I'd guess) but I can't
> > sufficiently summarize my issue to make it Google-able.

>
> Easy enough to do in perl:
>
> my $index_var = 'aa';
> my @var_names = map '$' . $index_var++, 0 .. $#$n_ra;
>
> my $nested_loop = join( '',
> map "\t" x $_
> . 'for ( my '
> . $var_names[ $_ ]
> . ' = 0; '
> . $var_names[ $_ ]
> . ' <= $n_ra->[ '
> . $_
> . ' ]; '
> . $var_names[ $_ ]
> . "++ ) {\n", 0 .. $#$n_ra )
> . "\t" x $#$n_ra
> . '$prob_ra->[ '
> . join( ' + ', @var_names )
> . " ] +=\n"
> . join( " *\n",
> map "\t" x @$n_ra
> . '$f_raa->[ '
> . $_
> . ' ]->[ '
> . $var_names[ $_ ]
> . ' ]', 0 .. $#$n_ra )
> . "\n"
> . join '', map "\t" x $_ . "}\n", reverse 0 .. $#$n_ra;
>
> eval $nested_loop;

You know, I initially shied away from this method just because I've
always had a problem with the brute force ugliness of eval. But the
truth is that even if not the prettiest, this is simply the fastest and
most direct way to go.

Highly appreciate the advice and the ready to go out the box code.

 
Reply With Quote
 
Jacob JKW
Guest
Posts: n/a
 
      03-30-2006
Ron Savage wrote:
> On Thu, 30 Mar 2006 13:54:58 +1000, Jacob JKW wrote:
>
> Hi Jacob
>
> Glad to see you obtained a solution.
>
> Just for the record, this was discussed in a book by the Australian programmer
> Ian Oliver:
>
> Programming Classics
> Ian Oliver
> Prentice Hall
> 1993
> 0-13-100413-1
> Section 4.3 Page 87
> Computing sub-subtotals within subtotals within totals to any depth

Thanks. Always on the lookout for a good read. I'll check it out.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re:"The urlopen() and urlretrieve() functions can cause arbitrarily longdelays" rh Python 0 02-24-2013 10:46 PM
using exp() inside many nested for loops causing Memory overflow ertis6@googlemail.com C++ 3 08-26-2008 03:22 PM
Loops with loops using html-template Me Perl Misc 2 01-12-2006 05:07 PM
Can you use forms authentication arbitrarily? Darrel ASP .Net 2 10-23-2004 06:59 PM
Arbitrarily Complex Data Structure JR Perl Misc 10 09-05-2003 08:44 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57