Избегайте повторных вызовов в Интерполяцию

Я хочу, чтобы интерполировать функцию в 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:

Лучший способ построить функцию с памятью

Динамическое программирование в Mathematica: как автоматически локализовать и / или очистить определения запомненной функции

Вы можете использовать определение 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}]
]
Другие вопросы по тегам