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.
Создайте эту функцию:
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))
Создайте процедуру 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)
Создайте процедуру 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)
Создайте процедуру 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)
|
Процедура или функциональная среда |
|
Процедура или выражение |
|
Процедура или выражение |
|
При использовании этой опции процедура, возвращенная
В конце вызова функции отбрасываются все помнившие значения. Если вы вызываете функцию с теми же входными параметрами снова, вызов функции оценен с теми же затратами как прежде. Можно предотвратить рекурсию в вызове функции и одновременно использовать помнить механизм вне вызова функции при помощи этого синтаксиса: |
Измененная процедура или функциональная среда