Избегайте повторных вызовов Интерполяции
Я хочу интерполировать функцию в математике.
Функция зависит от параметра 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]! Как мне избежать этого?
Спасибо за чтение.
Ответы
Ответ 1
Попробуйте что-то в этом направлении:
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
Первым шагом является параметризация 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
с помощью memoization:
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:
Лучший способ построения функции с памятью
Динамическое программирование в Mathematica: как автоматически локализовать и/или очистить имена замеченных функций
Ответ 3
Вы можете использовать определение 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], чтобы дать понять, что определение 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}]
]