Services & Resources / Wolfram Forums / MathGroup Archive
-----

MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: pure function with an NIntegrate command

  • To: mathgroup at smc.vnet.net
  • Subject: [mg99002] Re: [mg98957] pure function with an NIntegrate command
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Thu, 23 Apr 2009 06:46:27 -0400 (EDT)
  • References: <200904202312.TAA09654@smc.vnet.net>

Hi Ruth,

Can't  see the problem with NIntegrate:

In[1] =

Efun[x_, y_, z_] :=x + y + z;
fintn = NIntegrate[Efun[x, ##3], {x, #1, #2}] &;

I have redefined your function a bit so that it takes the lower limit
explicitly, but this does not matter here.

In[2] = fintn[0, #, 0.2, 0.3] & /@ Range[150] // Short // Timing

{1.171,{1.,<<148>>,11325.}}

I don't see however what do you gain by insisting on the use of pure
functions -  the speed-up is marginal:

In[3] = fintnp[list_, y_, z_] :=
 NIntegrate[Efun[x, y, z], {x, 0, #}] & /@ list;

In[4] = fintnp[Range[150], 0.2, 0.3] // Short // Timing

Out[4] ={1.182,{1.,<<148>>,11325.}}

This does not really seem to be the case where the use of pure functions
will lead to a major speed-up, since the main time is spent anyway by the
integration routine.

One suggestion would be to integrate the function analytically if possible,
and only once. Here is the code that does this, and automatically takes int=
o
account the variable number of arguments:

In[5] =

Clear[integr];
integr[f_, x_, pars___] :=
  With[{params = Table[Unique[], {Length[{pars}]}]},
   With[{patterns = Sequence @@ Map[Pattern[#, Blank[]] &, params]},
    integr[f, x1_, patterns] =
     Integrate[f[x1, Sequence @@ params], x1];
    integr[f, x, pars]]];

Clear[integratedFunction];
integratedFunction[f_, {lower_, higher_}, params___] :=
  integr[f, higher, params] - integr[f, lower, params] ;


It takes the function name as a first explicit argument. It uses a
generalized memoization (dynamic programming) with patterns, to compute the
integral upon the first call with this function and this number of
parameters, and stores the result as a formula. The function <integr> is
auxilliary and could be made local in principle.  Now:

In[6] =

Clear[Efun];
Efun[x_, y_] := x + y;
Efun[x_, y_, z_] :=x + y + z;

In[7] = integratedFunction[Efun, #, 0.2, 0.3] & /@ Table[{0, i}, {i, 150}=
]
//
  Short // Timing

Out[7] = {0.01,{1.,3.,6.,10.,<<143>>,11026.,11175.,11325.}}

In[8] = integratedFunction[Efun, #, 0.2] & /@ Table[{0, i}, {i, 150}] //
  Short // Timing

Out[8] = {2.16493*10^-15,{0.7,2.4,5.1,<<144>>,10981.6,11130.3,11280.}}


If explicit (analytical) integration is not an option, I have 2 more
suggestions. First, you may try to use Compile in defining your Efun
function for each particular set of parameters. Second, you may use the
additive nature of integration, and for every limit compute only the
integral from the previous limit to this one rather than from 0 to this one=


  • Prev by Date: Bug in Rational arithmetic?
  • Next by Date: Re: Re: Help with Speeding up a For loop
  • Previous by thread: Re: Alignment of Graphics Within Expressions
  • Next by thread: Re: Alignment of Graphics Within Expressions