Message Boards Message Boards

0
|
4337 Views
|
7 Replies
|
4 Total Likes
View groups...
Share
Share this post:

Refining a function to be faster

I have two functions qMultiple1 and qMultiple2 with the same goal . The function qMultiple2 much faster than qMultiple1, the difference is that Integrate[u[t],..] in qMultiple1 is inside of the function and in qMultiple2 is outside. How can be modified qMultiple1 (including Integrate inside it) in order to be as faster as qMultiple2 (I have copied the function below and I have added the notebook with the same functions). Thank you

qMultiple1[inputdata_,  {ff_, tt_}, ts_] := 
Module[{u, uc, tau, r, rr, rt, bi, t1, ti, Ti, t2,  t3}, 
u[t2_] = ff /. tt -> t2;   uc[t3_] =  Integrate[u[tau], {tau, 0, t3}] ;           
r[t1_, Ti_] := Piecewise[{{0, t1 < 0}, {uc[t1], 0 <= t1 <= Ti}, 
{uc[t1] - uc[t1 - Ti], t1 > Ti}}];  rr[bi_, ti_, Ti_] := (bi/Ti)*r[t1 - ti, Ti]; 
rt = rr @@@ inputdata /. t1 -> ts; Total[rt]];

qMultiple2[inputdata_,  {ff_, tt_}, ts_] := 
Module[{ tau, uc, r, rr, rt, bi, t1, ti, Ti, t2,  t3},  
uc[t2_] = ff /. tt -> t2;   r[t1_, Ti_] := Piecewise[{{0, t1 < 0}, {uc[t1], 0 <= t1 <= Ti}, 
{uc[t1] - uc[t1 - Ti], t1 > Ti}}];   rr[bi_, ti_, Ti_] := (bi/Ti)*r[t1 - ti, Ti]; 
 rt = rr @@@ inputdata /. t1 -> ts; Total[rt]];

u[t_] = 1/2 E^(-0.5 t) - 1/2 E^(-2 t);
inputs = {{100, 0, 10},  {30,  15, 10}, {15, 30, 5}  };
Plot[qMultiple1[inputs, {u[t], t}, t1], {t1, 0, 50}] // AbsoluteTiming
u1[t3_] =  Integrate[u[tau], {tau, 0, t3}] ;
Plot[qMultiple2[inputs, {u1[t], t}, t1], {t1, 0,  50}] // AbsoluteTiming

Guillermo

7 Replies
Posted 3 years ago

Hans:

Thank you for the mind expanding insight.

From the documentation, I do not think I would have ever figured out that you could use Evaluate like this.

POSTED BY: Mike Besso
Posted 3 years ago

Hi Mike,

There is nothing special with Evaluate in this situation. Integrate gives a closed form solution that depends on some parameter. So, use the solution rather than redundant Integrate. Using Set rather than SetDelayed would also avoid redundant Integrate.

ClearAll@f    
f[a_] := Echo@Integrate[Sin[x], {x, 0, a}]

Plot[f[a], {a, 0, 1}, PlotPoints -> 2]

Plot[Evaluate@f[a], {a, 0, 1}]

ClearAll@f
f[a_] = Echo@Integrate[Sin[x], {x, 0, a}]

Plot[f[a], {a, 0, 1}]
POSTED BY: Rohit Namjoshi
Posted 3 years ago

Mike, the documentation does touch on this. Under the Details and Options section of Plot reference (and the related Plot3D, ParametricPlot etc).

enter image description here

The wording can be seen as a bit cryptic. An alternative phrasing could be 'Since f will be evaluated at each plot point, it may in many cases be more efficient to use Evaluate[f] before specific ..'

POSTED BY: Hans Milton
Posted 3 years ago

Guillermo, it is not qMultiple1 by itself that is slow. It is Plot that calls it for every plot point. So the integration is done about 900 times.

To reduce the effect of the repeated calls you can add Evaluate to Plot. Then the integration will be done only once.

Plot[Evaluate[qMultiple1[inputs, {u[t], t}, t1]], {t1, 0, 50}] // AbsoluteTiming
POSTED BY: Hans Milton
Posted 3 years ago

If uc[] is not constant, then I do not think that qMultiple1[] can be modified in such a way that Plot[] would be able to call it.

That said, you could define your own PlotQMultiple1[] that encapsulates the both the function and the integration.

POSTED BY: Mike Besso

Mike, I know why qMultiple2 is faster than qMultiple1, and why uc[t3_] is defined with = (much better than :=).The code works fine, I try to refine it.

The question is: How can be modified qMultiple1 (including Integrate inside it) in order to be as (almost) faster as qMultiple2 .

Thank you

Posted 3 years ago

Please note that I'm still relatively new here. So there are still things about the language that I do not fully understand. But, I learn a great deal from trying to answer questions like this. So, let me give this one a shot:

The reason that qMultiple2 is faster is that it is not recalculating the (close to the) same value (returned by the integral). This is a great optimization technique.

That said, I'm not convinced that the two functions return exactly the same thing. Just a quick look at the code and I see that uc[t3_] is defined with = and not :=.

When uc[t3] is defined in qMultiple1, = is probably what you want. But, when you pull the definition of uc[t3] outside of the qMultiple2, then I think it should be defined with :=. Otherwise, you are getting the same value for uc[] every time.

POSTED BY: Mike Besso
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract