prog::remember

Расширенный помнят механизм за процедуры

Блокноты MuPAD® будут демонтированы в будущем релизе. Используйте live скрипты MATLAB® вместо этого.

Live скрипты MATLAB поддерживают большую часть функциональности MuPAD, хотя существуют некоторые различия. Для получения дополнительной информации смотрите, Преобразуют Notebook MuPAD в Live скрипты MATLAB.

Синтаксис

prog::remember(f, <depends>, <PreventRecursion, <predef>>)

Описание

prog::remember(f) возвращает модифицированную копию процедуры f это хранит ранее вычисленные результаты и дополнительную информацию в помнить таблице. Когда вы вызываете f с аргументами, которые вы уже использовали в предыдущих вызовах, f находит результаты в помнить таблицу и сразу возвращает их.

Если вы присваиваете f к идентификатору или доменному пазу, также необходимо присвоить копию, возвращенную prog::remember к тому же идентификатору или пазу, например, f := prog::remember(f).

f :=prog::remember(f) помнит результаты без контекстной информации, такие как свойства или значение DIGITS. В первый раз вы вызываете f с любой новой комбинацией входных параметров, помнить таблицей f хранилища `input`->`f(input)`. После этого, когда вы вызываете f теми же входными параметрами это берет результату f(input) из помнить таблицы вместо того, чтобы повторно вычислить его. Смотрите Пример 1.

f := prog::remember(f, depends) помнит результаты и дополнительную контекстную информацию. Функция зависимости depends позволяет вам задать контекстную информацию, чтобы сохранить наряду с вычисленными результатами в помнить таблице и проверить в каждом вызове функции. Смотрите Пример 2.

Как правило, полезно сохранить и проверить свойства входа и значения DIGITS и ORDER. К свойствам доступа входа используйте property::depends. Эта функция зависимости проверяет все три значения:

() -> [property::depends(args()), DIGITS, ORDER]

Другая типичная проблема состоит в том, что перегружающаяся функция не указывает, когда ее паз перегрузки изменяется в некоторой другой функции или области. Эта функция зависимости, которая использует slotAssignCounter позволяет вам избежать этой проблемы:

() -> [property::depends, slotAssignCounter("foo")]

Чтобы объединить все три задачи, используйте эту функцию зависимости:

() -> [property::depends(args()),
			DIGITS, ORDER, slotAssignCounter("foo")]

В первый раз вы вызываете f с любой новой комбинацией входных параметров, помнить таблицей f хранилища `[input, depends(input)]`->`f(input)`. После этого, когда вы вызываете f теми же входными параметрами это проверяет ли depends(input) возвращает то же значение как прежде. Если это делает, то f берет результат f(input) из помнить таблицы. В противном случае это вычисляет f(input) и добавляет новые значения `[input, depends(input)]`->`f(input)` к помнить таблице. Единственным исключением к этому правилу являются результаты, вычисленные с различными значениями MAXEFFORT. Если в предыдущих вызовах f(input) был вычислен с более низким MAXEFFORT, затем новый вызов с более высоким MAXEFFORT оценен и помнил, что результаты заменяются новыми единицами.

Если функция зависимости является постоянной или возвращает значение, которое не зависит от входа, то помнить механизм игнорирует контекстную информацию.

Можно вызвать модифицированную процедуру с Remember опция в качестве первого аргумента и одной из этих специальных опций в качестве второго аргумента:

  • Clear очищает помнить таблицу процедуры.

  • ClearPrevent очищает помнить таблицу, которая предотвращает бесконечные рекурсии в процедуре. Для получения дополнительной информации о предотвращении бесконечных рекурсий, см. описание PreventRecursion опция.

  • Print возвращает помнить таблицу процедуры.

Например, вызов f(Remember, Clear) очищает помнить таблицу f. Также смотрите Пример 3.

Примеры

Пример 1

Создайте эту функцию:

f := X -> if X > 1 then f(X - 1)*f(X - 2) - f(X - 2) else 1 end_if:

Вызывание этой функции длительно, потому что вызовы функции самой рекурсивно и оценивают каждый вызов:

f(20), time(f(20))

Используя помнить механизм устраняет эти переоценки. Чтобы включить помнить механизм, используйте prog::remember:

f := prog::remember(f):
f(200), time(f(200))

Пример 2

Создайте процедуру pos это проверяет, положителен ли его параметр:

pos := proc(x)
       begin
         is(x > 0)
       end_proc:

Включите помнить механизм для pos:

pos := prog::remember(pos):

pos возвращает UNKNOWN для переменной a:

pos(a)

Теперь используйте assume задавать ту переменную a положительно:

assume(a > 0):

Когда вы вызываете pos для переменной a, это находит значение pos(a) в помнить таблице. В этом случае помнить таблица не хранит контекстную информацию, и поэтому не проверяет на новые предположения на переменной a. Это возвращает помнивший результат, который является неправильным из-за нового предположения:

pos(a)

Вызов pos для a^3 возвращает правильный результат потому что pos(a^3) еще не находится в помнить таблице:

pos(a^3)

Примите тот a отрицательно:

assume(a < 0):

Теперь оба вызова возвращают неправильные значения, потому что результаты взяты из помнить таблиц:

pos(a), pos(a^3)

Чтобы сделать помнить механизм, знающий об изменениях в предположениях, используйте prog::remember со вторым аргументом property::depends как функция зависимости:

unassume(a):
pos := proc(x)
       begin
         is(x > 0)
       end_proc:
pos := prog::remember(pos, property::depends):
pos(a)

Теперь pos реагирует правильно на новое предположение:

assume(a > 0):
pos(a)

pos также возвращает правильный результат после того, как вы очистите предположение:

unassume(a):
pos(a)

Пример 3

Создайте процедуру pos и включите помнить механизм для него:

pos := proc(x)
       begin
         is(x > 0)
       end_proc:
pos := prog::remember(pos, getprop):

Вызовите pos для этих параметров:

pos(a):
assume(b > a, _and):
pos(b):

После того, как вы вызовете процедуру, по крайней мере, однажды, она составляет помнить таблицу. Чтобы видеть помнить таблицу процедуры, используйте специальную опцию Print. Значение 106 во втором столбце является значением MAXEFFORT используемый во время расчетов.

pos(Remember, Print)

Чтобы очистить помнить таблицу процедуры и таким образом обеспечить функцию, чтобы переоценить все результаты, используйте специальную опцию Clear:

pos(Remember, Clear):
pos(b)

Пример 4

Создайте процедуру deps это собирает все операнды свойств данного выражения, включая идентификаторы принятых свойств:

deps := proc(x)
        begin
          if domtype(x) <> DOM_IDENT then
            op(map(indets(x), deps))
          else
            x, deps(getprop(x))
          end_if
        end_proc:

Установите следующее предположение. Обратите внимание на то, что теперь deps содержит потенциально бесконечные рекурсии потому что свойство x относится к y, и свойство y вернулся к x:

assume(x > y):
deps(x)
Error: Recursive definition [See ?MAXDEPTH]

Чтобы предотвратить бесконечные рекурсии, используйте prog::remember с PreventRecursion опция:

deps := prog::remember(deps, PreventRecursion):
deps(x)

Упростить возвращаемое значение deps, перепишите функцию так, чтобы она возвратила набор всех идентификаторов:

deps := proc(x)
        begin
          if domtype(x) <> DOM_IDENT then
            _union(op(map(indets(x), deps)))
          else
            {x} union deps(getprop(x))
          end_if
        end_proc:
deps := prog::remember(deps, PreventRecursion):
deps(x)

Теперь deps ожидает, что возвращаемое значение будет набором. По умолчанию, когда рекурсия обнаруживается, процедура возвращает значение своего входа (который не является набором в этом примере). При предотвращении рекурсии в процедуре, где тип входа отличается от типа возвращаемого значения, задайте значение predef то, что процедура возвращается, когда рекурсия обнаруживается:

deps := proc(x)
        begin
          if domtype(x) <> DOM_IDENT then
            _union(op(map(indets(x), deps)))
          else
            {x} union deps(getprop(x))
          end_if
        end_proc:
deps := prog::remember(deps, PreventRecursion, () -> {args()}):

Здесь predef возвращает набор с входом как операнд:

deps(x)

Параметры

f

Процедура или функциональная среда

depends

Процедура или выражение

predef

Процедура или выражение

Опции

PreventRecursion

При использовании этой опции, процедурой, возвращенной prog::remember использование помнило информацию, чтобы предотвратить бесконечную рекурсию в процедуре.

f := prog::remember(f, PreventRecursion, predef ) хранит входные параметры только во время вызова функции. Этот подход позволяет вам постараться не переоценивать тот же вызов функции когда вызовы функции сам рекурсивно. Вместо этого это возвращает вход (по умолчанию) или результат вызова predef(input) (если вы задаете predef). Если возврат входа не является соответствующим результатом для вызова функции (например, если возвращаемое значение f и вход имеет различные типы), затем необходимо задать значение predef. Смотрите пример 4.

В конце вызова функции отбрасываются все помнившие значения. Если вы вызываете функцию теми же входными параметрами снова, вызов функции оценен с теми же затратами как прежде.

Можно предотвратить рекурсию в вызове функции и одновременно использовать помнить механизм вне вызова функции при помощи этого синтаксиса: f := prog::remember(f, depends, PreventRecursion, predef ). Если вы хотите использовать помнить механизм с контекстной информацией, задайте функцию зависимости depends как обычно. Если вы хотите использовать помнить механизм без контекстной информации и предотвратить рекурсии в процедуре, задайте depends как константа (или любая функция, возвращаемое значение которой не зависит от входа). Обратите внимание на то, что, если вы не используете depends функционируйте и только используйте синтаксис f := prog::remember(f, PreventRecursion, predef ), затем помнить механизм не работает вне вызова функции. В этом случае вы только предотвращаете рекурсии.

Возвращаемые значения

Модифицированная процедура или функциональная среда

Смотрите также

Функции MuPAD