避免重复调用插值

mar*_*ark 8 wolfram-mathematica mathematica-8

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

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

approx = Interpolation[Table[{F[0.1 n, a], 0.1 n}, {n, -100, 100}]]
Run Code Online (Sandbox Code Playgroud)

现在我可以简单地调用一点approx[x]来评估反函数.

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

G[x_,a_] = "construct the interpolating function,
            and return the value of the function at x"
Run Code Online (Sandbox Code Playgroud)

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

谢谢阅读.

WRe*_*ach 12

第一步是参数化approxa:

approx[a_] := Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
Run Code Online (Sandbox Code Playgroud)

有了这个定义,G就可以这样定义:

G[x_, a_] := approx[a][x]
Run Code Online (Sandbox Code Playgroud)

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

m: approx[a_] := m = Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
Run Code Online (Sandbox Code Playgroud)

现在,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}]])
Run Code Online (Sandbox Code Playgroud)

有了这个版本approx,cache可以使用本地化Block,例如:

Block[{cache}
, Table[G[x, a], {x, 0, 5}, {a, 0, 1, 0.1}]
]
Run Code Online (Sandbox Code Playgroud)

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

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

构造具有内存的函数的最佳方法

Mathematica中的动态编程:如何自动定位和/或清除memoized函数的定义


Ver*_*eia 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 *)
Run Code Online (Sandbox Code Playgroud)

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

  • 其他答案涉及当缓存符号变得太大时如何释放存储在缓存符号中的内存.这些缓存的想法与此答案中的相同.如果您的代码不是太占用内存,那么可以不关心释放当前会话的内存,但是如果您进行大量计算它会很有用. (3认同)

fay*_*sou 6

您可以使用我在Mathematica工具包中的内容中发布的CacheIndex的定义.使用此函数的一个好处是,您可以缓存值或代码的一部分,而无需定义新函数(尽管我们这里做的是与示例一致).

G[x_,a_] :=
   CacheIndex[a,
      Pause[3];
      Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
   ][x];
Run Code Online (Sandbox Code Playgroud)

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

然后,您可以使用缓存删除CacheIndex中的缓存插值

DeleteCachedValues[CacheIndex] (*or*) 
DeleteCachedValues[CacheIndex,1].
Run Code Online (Sandbox Code Playgroud)

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

这是CacheSymbol的定义

SetAttributes[CacheSymbol,HoldAll];
CacheSymbol[cacheSymbol_,expr_]:=cacheSymbol[expr]/.(_cacheSymbol:>(cacheSymbol[expr]=expr));
Run Code Online (Sandbox Code Playgroud)

您可以使用以下指令测试此实现,在实例中,将在块中定义缓存.

ClearAll[cache]
SetAttributes[cache,HoldFirst] 
CacheSymbol[cache,Pause[3];2+2]
?cache
CacheSymbol[cache,Pause[3];2+2]
Run Code Online (Sandbox Code Playgroud)

这是CacheSymbolIndex的定义

SetAttributes[CacheIndexSymbol,HoldAll];
CacheIndexSymbol[cacheSymbol_,index_,expr_]:=cacheSymbol[index,expr]/.(_cacheSymbol:>(cacheSymbol[index,expr]=expr));
Run Code Online (Sandbox Code Playgroud)

您可以使用以下指令测试此实现,在实例中,将在块中定义缓存.

ClearAll[cache] 
SetAttributes[cache,HoldRest]
CacheIndexSymbol[cache,2+2,Pause[3];2+2]
?cache
CacheIndexSymbol[cache,2+2,Pause[3];2+2]
Run Code Online (Sandbox Code Playgroud)

和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}]
]
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

735 次

最近记录:

14 年 前