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