1
$\begingroup$

I am trying to compare two functions on the end points of an interval.

For instance, $f_1(t)=t^3$ and $f_2(t)=t^4$. From my code below I check whether $f_1(t)\leq f_2(t)$ when $t=50$ on $[50, 51]$ and if it is then I store values $\{\{f_1(50), f_2(50)\}\}$ and then I move to $t=51$ and store it as $\{f_1(50), f_2(50)\},\{f_1(51), f_2(51)\} \}$ and so on until I reach $t=55$. I am using Sow/Reap to build my list. Here is my code:


f1[t_] := t^3
f2[t_] := t^4

n = 0;
T = 50;
k = 1;
lst = {};
Reap[While[T + n*k <= 55,
  If[f1[T + n*k] <= f2[T + n*k], Sow[{f1[T + n*k], f2[T + n*k]}]; 
   n = n + 1, Print[T + n*k]]]
 ]
lst

My questions:

  1. Using Reap/Sow in this manner gives me some extra $\{\}$ and an output of "Null" as my first element. What would be the correct way of using them in this case? (I wasn't able to get this clarification from their documentation.)

  2. Is there a quicker way to build such a list since in application I will have large "t" of the order of $10^6$ or $10^7$ instead of $50$ (and complicated $f_1, f_2$)? So far Reap/Sow I found to be the fastest.

$\endgroup$
1
  • $\begingroup$ Join @@ Last@ Reap[While[T + n*k <= 55, If[f1[T + n*k] <= f2[T + n*k], Sow[{f1[T + n*k], f2[T + n*k]}]; n = n + 1, Print[T + n*k]]]] $\endgroup$ – OkkesDulgerci Oct 28 '19 at 18:47
2
$\begingroup$

The extra Null and {} is just Reap/Sow working as expected, there is nothing to fix. The Null is the value of the expression. The extra {} that wraps the result is there because if you use tags then the values will be grouped by those tags:

Reap[
 Sow[a, "key1"];
 Sow[b, "key1"];
 Sow[c, "key2"];
 value
 ]

{value, {{a, b}, {c}}}

So then clearly, if you only have one group, the form of the expression should be {{a, b, c}} (i.e., there should be an extra set of brackets.)

Reap/Sow is usually what we resort to when we have lists of unknown length, to avoid having to use the awfully slow Append. But for your case, there may be much faster solutions because as long as you don't run into memory problems, you shouldn't need to grow the list dynamically. Here's something that I would try:

With[
   {range = Range[10^6]},
   f1Values = f1[range];
   f2Values = f2[range];
   res = Pick[Transpose[{f1Values, f2Values}], 
     UnitStep[f2Values - f1Values], 1];
   ]; // AbsoluteTiming

{7.39647, Null}

In practice, you should probably only go for the loop solution if you run into memory problems. If your functions are not listable then that may also affect the type of solution. Perhaps the best solution will then be a "bag" data structure used in conjunction with Compile.

$\endgroup$

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.