Избегайте повторных вызовов в Интерполяцию
Я хочу, чтобы интерполировать функцию в 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 ответа
Попробуйте что-то вроде этого:
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
,
Первый шаг заключается в параметризации 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
называется. Один из способов избежать этого - переопределить 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}]])
С этой версией approx
, cache
может быть локализован с помощью Block
Например:
Block[{cache}
, Table[G[x, a], {x, 0, 5}, {a, 0, 1, 0.1}]
]
Функции интерполяции все еще временно сохраняются для каждого отдельного значения a
, но теперь эти сохраненные определения выпускаются после Block
выходы.
Для получения дополнительной информации о функциях с памятью в Mathematica см. Вопросы SO:
Вы можете использовать определение CacheIndex, которое я разместил в разделе Что находится в вашей сумке с инструментами Mathematica?, Хорошая вещь об использовании этой функции заключается в том, что вы можете кэшировать значения или части кода без необходимости определения новой функции (хотя мы делаем это в соответствии с примером).
G[x_,a_] :=
CacheIndex[a,
Pause[3];
Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]]
][x];
Я добавил Pause[3] только для того, чтобы прояснить, что определение интерполяции кэшируется для каждого 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}]
]