For any positive integer $n$ which is not specified a priori, I can make $n$-tuple vector $v$ by v = Array[a, 1, n]. Now, given that $n$ is a positive integer which is not specified a priori, I want to write an iteration sentence which performs over $1\leq a_1,\ldots, a_n\leq 3$. ($a_i$ are integers and hence I will get $3^n$ iterations).

For example, if $n=2$, my sentence plays the same role as the following loop:

Do[EXPERIMENT, {i, 3}, {j, 3}]

If $n=3$, my sentence plays the same role as the following:

Do[EXPERIMENT, {i, 3}, {j, 3}, {k, 3}].

I can do it for any given SPECIFIED integer $n$, but I want to write the universal looping sentence which iterates for $1\leq a_1,\ldots, a_n\leq 3$ ($a_i$ are integers.)

  • $\begingroup$ Something like this? f[n_] := Module[{i = 1}, Do[Print@i++, Evaluate[Sequence @@ Thread[List[Array[a, n], 1, 3]]]]]; f[4] $\endgroup$ May 19 '13 at 21:25
  • $\begingroup$ Also, the tagging looks inappropriate. Anyone? $\endgroup$ May 19 '13 at 21:29
  • $\begingroup$ That's what I want! $\endgroup$
    – newbie0823
    May 19 '13 at 22:06

Following belisarius' suggestion you might use something like:

SetAttributes[f, HoldFirst]

f[body_, n_Integer?Positive, m__:3] := Block[{a},
  Do[body, ##] & @@ Thread[{Array[a, n], m}]


f[Print[a[1], a[2], a[3]], 3]

f[Print[a[1], a[2]], 2, 4]

f[Print[a[1], a[2]], 2, 5, 7]

How are parameters evaluated for a Plot in Manipulate

The second parameter is your n value. The third and following parameters are the range specification for the loops.

I Blocked a to prevent a global assignment to that symbol from breaking the function.

  • $\begingroup$ Faster than me ;) +1 $\endgroup$
    – Rojo
    May 20 '13 at 4:12
  • $\begingroup$ @Rojo Well it only took me 6+ hours... :^) And I thought you were in bed? $\endgroup$
    – Mr.Wizard
    May 20 '13 at 4:13
  • $\begingroup$ Haha, I just came back home, was about to go to bed, saw the other question, commented, and when I was about to lie down, it was stronger than me to come and answer. Then I saw this one, started to type Do[ and your answer appeared $\endgroup$
    – Rojo
    May 20 '13 at 4:22
  • 5
    $\begingroup$ @rojo I'd love that sort of auto-completion - start typing, and Mr Wizard fills the rest in for me...! $\endgroup$
    – cormullion
    May 20 '13 at 6:32

Say for $n=1$, you have defined f[{i1}] as your first experiment. For $n=2$, your experiments are defined by f[{i1,i2}], for $n=3$ the experiments are defined by f[{i1,i2,i3}] and etc, with the idea that you wish to allow $n$ such experiments. If you structure your experiments this way, then you can create a list of all experiments by

m = 3; n = 3; c = Tuples[Range[m], n]

Here $m$ is the number of values each variable is to take on, and $n$ is how many variables you have. Now you can run all your experiments at once using

Map[f, c]

or use the shortcut

f /@ c

For $m=n=3$, this gives

{f[{1, 1, 1}], f[{1, 1, 2}], f[{1, 1, 3}], f[{1, 2, 1}], f[{1, 2, 2}],
 f[{1, 2, 3}], f[{1, 3, 1}], f[{1, 3, 2}], f[{1, 3, 3}], 
 f[{2, 1, 1}], f[{2, 1, 2}], f[{2, 1, 3}], f[{2, 2, 1}], f[{2, 2, 2}],
 f[{2, 2, 3}], f[{2, 3, 1}], f[{2, 3, 2}], f[{2, 3, 3}], 
 f[{3, 1, 1}], f[{3, 1, 2}], f[{3, 1, 3}], f[{3, 2, 1}], f[{3, 2, 2}],
 f[{3, 2, 3}], f[{3, 3, 1}], f[{3, 3, 2}], f[{3, 3, 3}]}

so you can see all 3^3 experiments will run. In general you will have $n^m$ experiments. As Mr. Wizard suggests, an alternative to Map would be to use Scan:

Scan[Print[f[#]] &, c]

This might be preferred if your experiment function f has "side effects", such as making assignments, or generating output, since Scan will suppress these.

  • $\begingroup$ I thought about posting something like this but held off because I thought Do might be specified because of memory restrictions. Nevertheless the packed array from Tuples is compact, and this should be practical for a large range of applications. I would however mention Scan as that is more analogous to Do. +1 $\endgroup$
    – Mr.Wizard
    May 20 '13 at 5:25
  • $\begingroup$ Mr. Wizard -- Yes, I agree I was taking some liberties with the question: but this is one of the things with functional programming - if you plan ahead and build your "experiments" correctly, then later steps (like this one) become almost trivial. In fact, I would say planning ahead is important in any kind of programming. $\endgroup$
    – bill s
    May 20 '13 at 5:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.