2011-10-16 157 views
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]時都會構造插值!我將如何避免這種情況?

感謝您的閱讀。

回答

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您第一次爲每個特定值調用它時。

+0

這種方法似乎是其他方法提供的最簡單的方法。如其他答案中所述,也許在這個方案上隱藏了顯式緩存。但我不夠專業知道這種差異。 – mark

+3

其他答案處理如何釋放存儲在緩存符號中的內存,當它變得太大時。這些緩存的想法與這個答案中的一樣。如果你的代碼不是太內存密集型的,可以不關心釋放當前會話的內存,但是如果你做大的計算,它會很有用。 – faysou

+0

@Faysal Aberkane ......謝謝 – mark

12

的第一步是參數化approxa

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

+0

謝謝你的回答,它促使我去學習更多的數學! – mark

6

您可以使用的定義CacheIndex我發佈在What is in your Mathematica tool bag?。使用這個函數的一個好處是你可以緩存值或部分代碼,而不必定義一個新的函數(儘管我們在這裏要與示例一致)。

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

我適應我的緩存和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}] 
]