问题
I want to interpolate a function in mathematica.
The function depends on a parameter a
, in fact it is the inverse of a function F
which also depends on a
, so I build my approximation as follows,
approx = Interpolation[Table[{F[0.1 n, a], 0.1 n}, {n, -100, 100}]]
now I can simply call approx[x]
to evaluate the inverse function at a point.
Instead I would like to do something like this: Define a function which takes a parameter,
G[x_,a_] = "construct the interpolating function,
and return the value of the function at x"
Then write G[x,a] to evaluate the function. Otherwise I would have to repeat the interpolation for all the parameters I am interested in and have lots of variables lying around. I have tried putting the Interpolation[] call inside a module but that just constructs the interpolation every time I call G[x,a]! How would I avoid this?
Thanks for reading.
回答1:
Try something along these lines:
G[a_]:=G[a]=Interpolation[Table[{F[0.1 n, a], 0.1 n}, {n, -100, 100}]]
G[0.2] (* particular value of G[a] *)
G[0.2][0.3] (* the value you want *)
You will only evaluate G
the first time you call it for each particular value of a
.
回答2:
The first step is to parameterize approx
with a
:
approx[a_] := Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
With this definition, G
can then be defined thus:
G[x_, a_] := approx[a][x]
But, as observed in the question, this ends up reconstructing the interpolation every time G
is called. One way to avoid this is to redefine approx
using memoization:
m: approx[a_] := m = Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
Now, approx
will save the interpolation function for any given a
, avoiding reconstruction in subsequent calls with the same a
. Of course, this uses up memory so if there are a large number of distinct values of a
then memory could run short. It is possible to localize the cache used by approx
by associating the saved values with another symbol (cache
in this case):
approx[a_] := cache[a] /.
_cache :> (cache[a] = Interpolation[Table[{F[0.1` n,a],0.1` n},{n,-100,100}]])
With this version of approx
, cache
can be localized using Block
, e.g.:
Block[{cache}
, Table[G[x, a], {x, 0, 5}, {a, 0, 1, 0.1}]
]
The interpolation functions are still temporarily stored for each distinct value of a
, but now those saved definitions are released after the Block
exits.
For more information about functions with memory in Mathematica, see the SO questions:
The best way to construct a function with memory
Dynamic Programming in Mathematica: how to automatically localize and / or clear memoized function's definitions
回答3:
You could use the definition of CacheIndex I posted in What is in your Mathematica tool bag?. One good thing about using this function is that you can cache values or portions of code without having to define a new function (although we do here to be in line with the example).
G[x_,a_] :=
CacheIndex[a,
Pause[3];
Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
][x];
I added Pause[3] just to make it clear that the definition of Interpolation is cached for each a after it has been computed once.
You could then delete the cached Interpolation values in CacheIndex using
DeleteCachedValues[CacheIndex] (*or*)
DeleteCachedValues[CacheIndex,1].
I adapted my Cache and CacheIndex functions to make them compatible with the idea of WReach of using a separate symbol defined in a Block. One thing not practical here is that you have to define Hold attributes to the symbol used as cache, but the idea is still interesting.
Here is the definition of CacheSymbol
SetAttributes[CacheSymbol,HoldAll];
CacheSymbol[cacheSymbol_,expr_]:=cacheSymbol[expr]/.(_cacheSymbol:>(cacheSymbol[expr]=expr));
You can test this implementation using the following instructions, in a real example cache would be defined in a Block.
ClearAll[cache]
SetAttributes[cache,HoldFirst]
CacheSymbol[cache,Pause[3];2+2]
?cache
CacheSymbol[cache,Pause[3];2+2]
Here is the definition of CacheSymbolIndex
SetAttributes[CacheIndexSymbol,HoldAll];
CacheIndexSymbol[cacheSymbol_,index_,expr_]:=cacheSymbol[index,expr]/.(_cacheSymbol:>(cacheSymbol[index,expr]=expr));
You can test this implementation using the following instructions, in a real example cache would be defined in a Block.
ClearAll[cache]
SetAttributes[cache,HoldRest]
CacheIndexSymbol[cache,2+2,Pause[3];2+2]
?cache
CacheIndexSymbol[cache,2+2,Pause[3];2+2]
and similarly to the example of WReach we would have
G[x_,a_] :=
CacheIndexSymbol[cache,a,
Print["Caching"];
Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
][x]
Block[{cache},
SetAttributes[cache,HoldRest];
Table[G[x, a], {x, 0, 5}, {a, 0, 1, 0.1}]
]
来源:https://stackoverflow.com/questions/7781981/avoid-repeated-calls-to-interpolation