【问题标题】:Avoid repeated calls to Interpolation避免重复调用 Interpolation
【发布时间】:2011-10-16 02:34:21
【问题描述】:

我想在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] 时构建插值!我该如何避免这种情况?

感谢阅读。

【问题讨论】:

    标签: wolfram-mathematica mathematica-8


    【解决方案1】:

    第一步是用a参数化approx

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

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

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

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

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

    现在,approx 将保存任何给定 a 的插值函数,避免在后续调用中使用相同的 a 进行重建。当然,这会占用内存,因此如果有大量不同的 a 值,那么内存可能会不足。可以通过将保存的值与另一个符号(在本例中为 cache)相关联来本地化 approx 使用的缓存:

    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

    【讨论】:

    • 谢谢你的回答,它激励我去学习更多的数学!
    【解决方案2】:

    尝试以下方法:

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

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

    【讨论】:

    • 这种方法似乎是提供的其他方法中最简单的方法。与其他答案中描述的显式缓存相比,该方案可能存在缺陷。但我还不够专家知道其中的区别。
    • 其他答案涉及如何在缓存符号变得太大时释放存储在缓存符号中的内存。这些的缓存思想与此答案中的相同。如果您的代码不是太占用内存,则不必真正关心释放当前会话的内存,但如果您进行大量计算,它会很有用。
    【解决方案3】:

    您可以使用我在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}]
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多