0
$\begingroup$

The question is simple. I'm trying to improve the (time) performance of a "Do" loop that looks like the following MWE

xlist = Range[0., 1., 0.1]; ylist = Range[0., 2., 0.2]; f[x_, y_, z_] := x + 3*y - z results = {}; Do[ input = Tuples[{xlist, ylist, {step}}]; evalf = f @@ Transpose[input]; AppendTo[results, {step, Mean@evalf}] , {step, Range[-1., 1., 0.1]}] 

What is the most efficient way to speed up a thing like this?

$\endgroup$
5
  • 1
    $\begingroup$Not in a position where I can answer rn, but it strikes me that you could simply use Table instead of a Do and AppendTo here. Also an iterator of the form {step, -1, 1, 0.1} might be better, instead of computing the whole Range; not sure.$\endgroup$
    – thorimur
    CommentedMar 17, 2021 at 5:07
  • $\begingroup$Also, I don’t think you need to compute Tuples each time, since the step is constant in a given, well, step! Maybe simply compute xylist = Transpose @ Tuples[{xlist, ylist}] outside the loop, then instead of Do use results = Table[{step, Mean[f[#1, #2, step]& @@ xylist]}, {step, -1, 1, 0.1}]. Does that work as expected? (Sorry, not at a computer rn...)$\endgroup$
    – thorimur
    CommentedMar 17, 2021 at 5:15
  • 1
    $\begingroup$Of course, given that your function is linear, we could simply compute Mean[#1 + 3*#2 & @@ Transpose[Tuples[{xlist, ylist}], or analytically simply $\bar{x} + 3\bar{y} = 0.5 + 3$, and then results = Table[{step, 3.5 - step}, {step, -1, 1, 0.1}], I think, but assuming you want to use an arbitrary function in general... :P$\endgroup$
    – thorimur
    CommentedMar 17, 2021 at 5:25
  • $\begingroup$With[{ran = Range[-1., 1., 0.1]}, Transpose[{ran, Mean[xlist] + 3 Mean[ylist] - ran}] ]$\endgroup$CommentedMar 17, 2021 at 6:32
  • $\begingroup$I should have mentioned maybe that the function I'm working with is not linear...$\endgroup$
    – Pablo G
    CommentedMar 17, 2021 at 18:33

1 Answer 1

3
$\begingroup$

In MMA you seldom use loops. And when you nevertheless use a loop to create a list, do not use AppendTo, this will reallocate the list every time you add an element. Instead use Sow and Reap. Here is a solution without loops:

xlist = Range[0., 1., 0.1]; ylist = Range[0., 2., 0.2]; Clear[f, f1] f[x_, y_, z_] := x + 3*y - z f1[z_] = {z, Mean[f[xlist, ylist, z]]} results = f1 /@ Range[-1., 1., 0.1] 
$\endgroup$
2
  • $\begingroup$The key point of using Tuples in my original code was to create a grid on which you could evaluate the function. Then I want to obtain the fraction of points on this grid where the function is greater OR smaller than certain limits. For this I used Mean[UnitStep[f[args]-valmax]] + Mean[UnitStep[valmin- f[args]]]. If I'm right, with your code the function only gets evaluated at the pairs of values in the lists with the same position, and that's not what I want. Is there a workaround for Tuples or the UnitStep usage in this case?$\endgroup$
    – Pablo G
    CommentedMar 17, 2021 at 18:30
  • $\begingroup$I have difficulties understanding what you want. I think you should open an new question and explain exactly what you want. with a small test example.$\endgroup$CommentedMar 17, 2021 at 19:58

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.