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=
- References:
- Alignment of Graphics Within Expressions
- From: "David Park" <djmpark@comcast.net>
- Alignment of Graphics Within Expressions