避免重复调用插值

时间:2011-10-16 02:34:22

标签: wolfram-mathematica mathematica-8

我想在mathematica中插入一个函数。

函数取决于参数a,实际上它是函数F的倒数,它也取决于a,所以我建立我的近似值,如下所示,

approx = Interpolation[Table[{F[0.1 n, a], 0.1 n}, {n, -100, 100}]]

现在我可以简单地调用approx[x]来评估某个点的反函数。

相反,我想做这样的事情:定义一个带参数的函数,

G[x_,a_] = "construct the interpolating function,
            and return the value of the function at x"

然后写G [x,a]来评估函数。否则我将不得不为我感兴趣的所有参数重复插值并且有很多变量。我已经尝试将Interpolation []调用放在一个模块中,但每次调用G [x,a]时都只构造插值!我怎么能避免这个?

感谢阅读。

3 个答案:

答案 0 :(得分:12)

第一步是使用approx参数化a

approx[a_] := Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]

通过这个定义,可以定义G

G[x_, a_] := approx[a][x]

但是,正如在问题中所观察到的,每次调用G时,这最终都会重建插值。避免这种情况的一种方法是使用memoization重新定义approx

m: approx[a_] := m = Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]

现在,approx将为任何给定的a保存插值函数,避免在后续调用中使用相同的a重建。当然,这会消耗内存,所以如果有大量不同的a值,那么内存可能会短缺。通过将保存的值与另一个符号(在这种情况下为approx)相关联,可以本地化cache使用的缓存:

approx[a_] := cache[a] /.
  _cache :> (cache[a] = Interpolation[Table[{F[0.1` n,a],0.1` n},{n,-100,100}]])

使用此版本的approxcache可以使用Block进行本地化,例如:

Block[{cache}
, Table[G[x, a], {x, 0, 5}, {a, 0, 1, 0.1}]
]

插值函数仍然为a的每个不同值临时存储,但现在这些已保存的定义将在Block退出后释放。

有关Mathematica中带内存函数的更多信息,请参阅SO问题:

The best way to construct a function with memory

Dynamic Programming in Mathematica: how to automatically localize and / or clear memoized function's definitions

答案 1 :(得分:6)

尝试以下几点:

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 *)

您只会在第一次为G的每个特定值调用时评估a

答案 2 :(得分:6)

您可以使用我在What is in your Mathematica tool bag?中发布的 CacheIndex 的定义。使用此函数的一个好处是,您可以缓存值或代码的一部分,而无需定义新函数(尽管我们在此处与示例一致)。

G[x_,a_] :=
   CacheIndex[a,
      Pause[3];
      Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
   ][x];

我添加了Pause [3]只是为了清楚地表明Interpolation的定义是在计算一次后为每个a缓存的。

然后,您可以使用

删除CacheIndex中的缓存插值
DeleteCachedValues[CacheIndex] (*or*) 
DeleteCachedValues[CacheIndex,1].

我调整了我的Cache和CacheIndex函数,使它们与WReach使用块中定义的单独符号的想法兼容。这里不实用的一件事是你必须为用作缓存的符号定义Hold属性,但这个想法仍然很有趣。

以下是 CacheSymbol

的定义
SetAttributes[CacheSymbol,HoldAll];
CacheSymbol[cacheSymbol_,expr_]:=cacheSymbol[expr]/.(_cacheSymbol:>(cacheSymbol[expr]=expr));

您可以使用以下说明测试此实现,在实例中,缓存将在块中定义。

ClearAll[cache]
SetAttributes[cache,HoldFirst] 
CacheSymbol[cache,Pause[3];2+2]
?cache
CacheSymbol[cache,Pause[3];2+2]

以下是 CacheSymbolIndex

的定义
SetAttributes[CacheIndexSymbol,HoldAll];
CacheIndexSymbol[cacheSymbol_,index_,expr_]:=cacheSymbol[index,expr]/.(_cacheSymbol:>(cacheSymbol[index,expr]=expr));

您可以使用以下说明测试此实现,在实例中,缓存将在块中定义。

ClearAll[cache] 
SetAttributes[cache,HoldRest]
CacheIndexSymbol[cache,2+2,Pause[3];2+2]
?cache
CacheIndexSymbol[cache,2+2,Pause[3];2+2]

与WReach的例子类似,我们会有

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}]
]