Previous: Введение в правила преобразований и шаблоны, Up: Правила преобразования и шаблоны [Contents][Index]
Осуществляет повторное применение правила преобразования rule_1 к expr до тех пор пока выражение отвечает шаблону преобразования, затем, таким же образом осуществляется повторное применение этого правила ко всем подвыражениям expr, слева направо. Далее, к полученному результату тем же способом применяется правило rule_2 и так далее все последующие правила вплоть до rule_n. Конечный результат возвращается.
Переменная maxapplydepth
контролирует нижнюю глубину уровня подвыражения до
которого применяются правила преобразований в функциях apply1
и apply2
.
См. также applyb1, apply2
и let
.
Если правило rule_1 неприменимо на подвыражении expr, тогда применяется правило rule_2 и далее по той же схеме остальные правила. Только если каждое из правил является неприменимым на данном подвыражении expr, программа переходит на следующий уровень подвыражнния expr, и по той же схеме последовательно применяет весь набор правил, начиная с первого. Если применение одного из правил оказывается успешным, тогда весь набор правил заново применяется к этому подвыражению.
Переменная maxapplydepth
контролирует нижнюю глубину уровня подвыражения до
которого применяются правила преобразований в функциях apply1
и apply2
.
См. также apply1
и let
.
В отличие от apply1
применяется по восходящей, т.е., сначала на
самом глубоком уровне expr повторяется применение правила
rule_1. Затем программа переходит на более высокие уровни
expr и применяет данное правило по той же схеме. После того как
применение правила rule_1 терпит неудачу на самом вернем уровне
expr программа переходит к применению правила rule_2 по
той же схеме (по восходящей) и так далее, заканчивая применением
правила rule_n. После этого возвращается результат.
Функция applyb1
аналогична apply1
, но работает по восходящей.
Переменная maxapplyheight
контролирует высоту уровня подвыражения до
которого применяются правила преобразований в функции applyb1
.
См. также apply1
, apply2
и let
.
Значение по умолчанию: default_let_rule_package
current_let_rule_package
- имя пакета правил, которые, если не
определен другой пакет правил, используются функциями из программы let
(такими как,
letsimp
, и т.д.) Эта переменной может быть присвоено имя любого пакета правил
преобразований, определенного при помощи функции let
.
При вызове letsimp (expr, rule_pkg_name)
,
пакет правил rule_pkg_name
используется только во время данного
действия, при этом значение переменной current_let_rule_package
остается неизменным.
Значение по умолчанию: default_let_rule_package
default_let_rule_package
- имя пакета правил, используемого по умолчанию, если
пакет правил не был задан в явном виде при вызове let
или через
изменение значения переменной current_let_rule_package
.
Определяет функцию progname (expr, x_1, ..., x_n)
,
которая проверяет выражение expr на соответствие шаблону pattern.
Шаблон pattern - выражение, содержащее аргументы шаблона x_1, ..., x_n (если есть)
и переменные шаблона (если есть).
Аргументы шаблона задаются в явном виде, как аргументы функции
defmatch
, а переменные шаблона декларируются функцией matchdeclare
.
Всякая переменная, не декларированная как переменная шаблона при помощи mathdeclare
или как аргумент шаблона при помощи defmatch
соответствует только сама себе.
Первым аргументом создаваемой функции progname является выражение, проверяемое на соответствие шаблону, а другие аргументы это актуальные параметры, соответствующие аргументам шаблона x_1, ..., x_n.
Если проверка на соответствие шаблону оказывается успешной, то
progname возвращает список уравнений, в которых левые части
являются аргументами и переменными шаблона, а правые части - подвыражения expr,
сопоставленные данным аргументам и переменным.
Переменным шаблона, но не аргументам шаблона, присваиваются соответствующие значения.
В случае неудачи сопоставления progname возвращает false
.
Любая переменная, не объявленная в параметрах шаблона в
matchdeclare
или в переменных шаблона в defmatch
,
сопоставляется только самой себе.
Программа для буквального шаблона, т.е. шаблона не содержащего ни аргументов ни переменных,
в случае удачи сопоставления возвращает true
.
См. также matchdeclare
, defrule
, tellsimp
и tellsimpafter
.
Примеры:
Определим функцию linearp (expr, x)
, которая проверяет может ли expr
быть представлено
ввиде a*x + b
, где a
и b
не содержат x
и a
отлично от нуля.
Эта функция сопоставима с выражениями линейными по любой переменной,
поскольку аргумент шаблона x
определен в defmatch
.
(%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b, freeof(x)); (%o1) done (%i2) defmatch (linearp, a*x + b, x); (%o2) linearp (%i3) linearp (3*z + (y + 1)*z + y^2, z); 2 (%o3) [b = y , a = y + 4, x = z] (%i4) a; (%o4) y + 4 (%i5) b; 2 (%o5) y (%i6) x; (%o6) x
Определим функцию linearp(expr)
, которая проверяет может ли expr
быть представлено
ввиде a*x + b
, где a
и b
не содержат x
и a
отлично от нуля.
Эта функция сопоставима с выражениями линейными только по x
,
поскольку в defmatch
не заданы никакие аргументы шаблона.
(%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b, freeof(x)); (%o1) done (%i2) defmatch (linearp, a*x + b); (%o2) linearp (%i3) linearp (3*z + (y + 1)*z + y^2); (%o3) false (%i4) linearp (3*x + (y + 1)*x + y^2); 2 (%o4) [b = y , a = y + 4]
Определим функцию checklimits(expr)
, которая проверяет,
определяет ли expr
интеграл.
(%i1) matchdeclare ([a, f], true); (%o1) done (%i2) constinterval (l, h) := constantp (h - l); (%o2) constinterval(l, h) := constantp(h - l) (%i3) matchdeclare (b, constinterval (a)); (%o3) done (%i4) matchdeclare (x, atom); (%o4) done (%i5) simp : false; (%o5) false (%i6) defmatch (checklimits, 'integrate (f, x, a, b)); (%o6) checklimits (%i7) simp : true; (%o7) true (%i8) 'integrate (sin(t), t, %pi + x, 2*%pi + x); x + 2 %pi / [ (%o8) I sin(t) dt ] / x + %pi (%i9) checklimits (%); (%o9) [b = x + 2 %pi, a = x + %pi, x = t, f = sin(t)]
Определяет и именует правило преобразования для данного шаблона.
Если правило c именем rulename применяется к выражению
(путем apply1
, applyb1
или apply2
), то каждое
подвыражение, удовлетворяющее шаблону, заменяется соответствующей подстановкой.
После этого выражение упрощается.
Правила могут рассматриваться как функции, преобразующие выражение путем
одной операции сопоставления с шаблоном и подстановки.
При неудаче сопоставления, функция правила преобразования возвращает false
.
Выводит правила преобразований и их имена rulename_1, ..., rulename_n,
определенные в defrule
, tellsimp
или tellsimpafter
, или
шаблоны, определенные defmatch
.
Каждое правило выводится в форме промежуточного выражения, маркированного символом (%t
).
Вызов disprule (all)
выводит все определенные правила.
Функция disprule
не вычисляет свои аргументы.
Функция disprule
возвращает список меток промежуточных выражений, соответствующих выведенным правилам.
См. также функцию letrules
, которая выводит правила определенные let
.
Примеры:
(%i1) tellsimpafter (foo (x, y), bar (x) + baz (y)); (%o1) [foorule1, false] (%i2) tellsimpafter (x + y, special_add (x, y)); (%o2) [+rule1, simplus] (%i3) defmatch (quux, mumble (x)); (%o3) quux (%i4) disprule (foorule1, "+rule1", quux); (%t4) foorule1 : foo(x, y) -> baz(y) + bar(x) (%t5) +rule1 : y + x -> special_add(x, y) (%t6) quux : mumble(x) -> [] (%o6) [%t4, %t5, %t6] (%i6) ''%; (%o6) [foorule1 : foo(x, y) -> baz(y) + bar(x), +rule1 : y + x -> special_add(x, y), quux : mumble(x) -> []]
Определяет правила подстановки для функции letsimp
такие, что prod заменяется на repl.
prod является произведением подвыражений положительной или отрицательной степени.
Подвыражения могут быть следующего типа:
letsimp
ведет только по имени, если перед
вызовом letsimp
в функции matchdeclare
не был определен
предикат, связанный с этим атомом. В последнем случае letsimp
будет сопоставлять атом с любым членом произведения удовлетворяющим предикату.
sin(x)
, n!
, f(x,y)
и т.п. Как и в
предыдущем случае letsimp
ищет буквальное соответствие, если
в matchdeclare
не был определен предикат.
Члены положительной степени будут сопоставляться только членам, имеющим положительную
степень. Члены отрицательной степени будут сопоставляться только членам, имеющим отрицательную
степень.
Для того чтобы letsimp
работал с отрицательными степенями в prod
переменная letrat
должна быть установлена равной true
.
См. также letrat
.
Если в функцию let
включен предикат, с последующим списком аргументов,
то подстановки осуществляются только если predname (arg_1', ...,
arg_n')
дает true
, где arg_i’ есть значение, сопоставленное arg_i.
Переменная arg_i может быть именем атома или аргументом любого ядра, присутствующего в prod.
repl может быть любым рациональным выражением. Если любой атом или аргумент из prod присутствует в
repl, то выполняются соответствующие подстановки.
Глобальная переменная letrat
управляет упрощением дробных
выражений в letsimp
.
Если letrat
равена false
, то
letsimp
упрощает отдельно числитель и знаменатель выражения
expr, но не упрощает их частное.
В этом случае подстановки типа n!/n
на (n-1)!
не будут работать.
Если letrat
равена true
, тогда числитель, знаменатель и
их частное упрощаются в данном порядке.
Данные функции подстановок позволяют работать с несколькими пакетами
правил одновременно. Каждый пакет правил может содержать любое
количество правил преобразований let
и обозначается некоторым
заданным пользователем именем.
Вызов let ([prod, repl, predname, arg_1, ..., arg_n], package_name)
добавляет правило predname к пакету правил package_name.
Вызов letsimp (expr, package_name)
применяет правила преобразований из пакета package_name.
Процедура letsimp (expr, package_name1, package_name2, ...)
эквивалентна применению функций letsimp (expr, package_name1)
и затем функции letsimp (%, package_name2)
, ....
Переменная current_let_rule_package
содержит имя текущего пакета правил.
Данной переменной может быть присвоено имя любого пакета правил,
определенного при помощи let
.
Вызов команды let
без упоминания имени пакета приводит к
применению пакета, определенного current_let_rule_package
.
При вызове типа letsimp (expr, rule_pkg_name)
,
используются правила пакета rule_pkg_name, только для данного вызова lrtsimp
а
значение переменной current_let_rule_package
не меняется. По умолчанию current_let_rule_package
равно default_let_rule_package
.
(%i1) matchdeclare ([a, a1, a2], true)$ (%i2) oneless (x, y) := is (x = y-1)$ (%i3) let (a1*a2!, a1!, oneless, a2, a1); (%o3) a1 a2! --> a1! where oneless(a2, a1) (%i4) letrat: true$ (%i5) let (a1!/a1, (a1-1)!); a1! (%o5) --- --> (a1 - 1)! a1 (%i6) letsimp (n*m!*(n-1)!/m); (%o6) (m - 1)! n! (%i7) let (sin(a)^2, 1 - cos(a)^2); 2 2 (%o7) sin (a) --> 1 - cos (a) (%i8) letsimp (sin(x)^4); 4 2 (%o8) cos (x) - 2 cos (x) + 1
Значение по умолчанию: false
Если letrat
равна false
, то letsimp
упрощает отдельно числитель и знаменатель выражения
expr, и не упрощает их частное.
Если letrat
равна true
, то числитель, знаменатель и их частное упрощаются в данном порядке.
(%i1) matchdeclare (n, true)$ (%i2) let (n!/n, (n-1)!); n! (%o2) -- --> (n - 1)! n (%i3) letrat: false$ (%i4) letsimp (a!/a); a! (%o4) -- a (%i5) letrat: true$ (%i6) letsimp (a!/a); (%o6) (a - 1)!
Выводит правила, содержащиеся в пакете правил преобразований.
letrules ()
выводит правила текущего пакета правил
преобразований.
letrules (package_name)
выводит правила преобразований в
пакете package_name.
Текущий пакет правил определяется значением current_let_rule_package
.
Если не определено иначе, то current_let_rule_package
по умолчанию равен default_let_rule_package
.
См. также функцию disprule
, отображающую правила, определенные
путем tellsimp
и tellsimpafter
.
Данная функция осуществляет повторное применение правил подстановки,
определенных в let
, до тех пор пока выражение expr не
перестанет изменяться.
letsimp (expr)
использует правила из пакета current_let_rule_package
.
letsimp (expr, package_name)
использует правила из пакета package_name
без изменения значения переменной current_let_rule_package
.
letsimp (expr, package_name_1, ..., package_name_n)
эквивалентно применению letsimp (expr, package_name_1
,
затем letsimp (%, package_name_2)
и так далее.
Значение по умолчанию: [default_let_rule_package]
let_rule_packages
- список определенных пользователем пакетов
правил вместе с пакетом default_let_rule_package
.
Связывает предикат pred_k с переменной или списком переменных
a_k, так что a_k сопоставляется с выражениями,
для которых предикат возвращает значение отличное от false
.
Предикат это есть имя функции, или лямбда-выражение, или вызов функции
или лямбда-выражения без последнего аргумента, или true
, или all
.
Если предикат определен при помощи вызова функции или лямбда-выражения, то
тестируемое выражение добавляется к списку аргументов; аргументы вычисляются
во время вызова процедуры проверки на соответствие.
Если предикат определен в виде имени функции или лямбда-выражения,
то единственным аргументом является тестируемое выражение.
Предикат не обязан быть определенным в момент вызова
matchdeclare
, поскольку он не вычисляется до тех пор пока
не вызывается проверка на соответствие.
Предикат может возвращать логическое выражение а также true
или false
.
Логическое выражение вычисляется при помощи is
внутри построенной функции правила,
так что нет необходимости вызывать is
в предикате.
Если выражение удовлетворяет предикату, то переменной шаблона
присваивается выражение за исключением переменных шаблона которые
являются операндами сложения +
или умножения *
.
Только сложение и умножение управляется специальным образом. Другие n-арные операторы,
(как пользовательские, так и встроенные) рассматриваются как обычные функции.
В случае операторов сложения и умножения, переменной шаблона может быть присвоено простое выражение, которое соответствует предикату, а также сумма или произведение таких выражений. Такое сложное сопоставление является ресурсоемким: предикаты вычисляются в порядке в котором, ассоциированные с ними переменные, встречаются в тестируемом выражении, и член, удовлетворяющий более чем одному предикату, сопоставляется первому соответствующему предикату. Каждый предикат проверяется для всех операндов суммы или произведения и только после этого проверяется следующий предикат. Кроме того, если 0 или 1 удовлетворяют предикату, а все остальные слагаемые выражения нет, тогда 0 или 1 присваиваются переменным шаблона ассоциированным с предикатом.
Алгоритм проверки шаблонов, содержащий суммы и произведения, может давать разные результаты (например, шаблон, содержащий переменную соответствующую "всему, что угодно") в зависимости от порядка членов заданного шаблона и порядка членов тестируемого выражения. Если все операторы предикаты взаимно исключают друг друга, то результат не зависит от порядка, поскольку члены, соответствующие одному предикату, не могут соответствовать другому.
Вызов matchdeclare
с переменной a в качестве аргумента
изменяет ранее объявленные свойства matchdeclare
для a -
при определении правил преобразования, учитываются только самый последний
вызов matchdeclare
.
Все последующие изменения свойства matchdeclare
(посредством matchdeclare
или remove
)
не меняют существующих правил преобразований.
propvars (matchdeclare)
возвращает список всех переменных,
имеющих свойство matchdeclare
.
printprops (a, matchdeclare)
возвращает предикат
для переменной a
.
printprops (all, matchdeclare)
возвращает список всех предикатов
для всех переменных matchdeclare
.
remove (a, matchdeclare)
удаляет свойства
matchdeclare
для переменной a.
Функции
defmatch
, defrule
, tellsimp
, tellsimpafter
и let
строят правила, которые сопоставляют выражения с шаблонами.
Функция matchdeclare
не вычисляет свои аргументы.
Функция matchdeclare
всегда возвращает done
.
Примеры:
Предикат есть имя функции, или лямбда-выражение, или вызов функции или
лямбда-вызов без последнего аргумента,
или true
, или all
.
(%i1) matchdeclare (aa, integerp); (%o1) done (%i2) matchdeclare (bb, lambda ([x], x > 0)); (%o2) done (%i3) matchdeclare (cc, freeof (%e, %pi, %i)); (%o3) done (%i4) matchdeclare (dd, lambda ([x, y], gcd (x, y) = 1) (1728)); (%o4) done (%i5) matchdeclare (ee, true); (%o5) done (%i6) matchdeclare (ff, all); (%o6) done
Если выражение удовлетворяет предикату, то переменной шаблона присваивается выражение.
(%i1) matchdeclare (aa, integerp, bb, atom); (%o1) done (%i2) defrule (r1, bb^aa, ["integer" = aa, "atom" = bb]); aa (%o2) r1 : bb -> [integer = aa, atom = bb] (%i3) r1 (%pi^8); (%o3) [integer = 8, atom = %pi]
В случае суммы и произведения, переменной шаблона может быть присвоено простое выражение, которое удовлетворяет предикату, или также сумма или произведение таких выражений.
(%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x))); (%o1) done (%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" = bb]); bb + aa partitions `sum' (%o2) r1 : bb + aa -> [all atoms = aa, all nonatoms = bb] (%i3) r1 (8 + a*b + sin(x)); (%o3) [all atoms = 8, all nonatoms = sin(x) + a b] (%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" = bb]); bb aa partitions `product' (%o4) r2 : aa bb -> [all atoms = aa, all nonatoms = bb] (%i5) r2 (8 * (a + b) * sin(x)); (%o5) [all atoms = 8, all nonatoms = (b + a) sin(x)]
При сопоставлении аргументов +
и *
,
если все предикаты условия являются взаимоисключающими, то результат
проверки не зависит порядка, так как один предикат не соответствует
членам, соответствующим другому предикату.
(%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x))); (%o1) done (%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" = bb]); bb + aa partitions `sum' (%o2) r1 : bb + aa -> [all atoms = aa, all nonatoms = bb] (%i3) r1 (8 + a*b + %pi + sin(x) - c + 2^n); n (%o3) [all atoms = %pi + 8, all nonatoms = sin(x) + 2 - c + a b] (%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" = bb]); bb aa partitions `product' (%o4) r2 : aa bb -> [all atoms = aa, all nonatoms = bb] (%i5) r2 (8 * (a + b) * %pi * sin(x) / c * 2^n); n (b + a) 2 sin(x) (%o5) [all atoms = 8 %pi, all nonatoms = -----------------] c
Функции propvars
и printprops
возвращают информацию о
переменных шаблона.
(%i1) matchdeclare ([aa, bb, cc], atom, [dd, ee], integerp); (%o1) done (%i2) matchdeclare (ff, floatnump, gg, lambda ([x], x > 100)); (%o2) done (%i3) propvars (matchdeclare); (%o3) [aa, bb, cc, dd, ee, ff, gg] (%i4) printprops (ee, matchdeclare); (%o4) [integerp(ee)] (%i5) printprops (gg, matchdeclare); (%o5) [lambda([x], x > 100, gg)] (%i6) printprops (all, matchdeclare); (%o6) [lambda([x], x > 100, gg), floatnump(ff), integerp(ee), integerp(dd), atom(cc), atom(bb), atom(aa)]
Объявляет матчфиксный (matchfix) оператор с левым и правым ограничителями ldelimiter и rdelimiter соответственно. Ограничители являются строками.
Матчфиксный оператор является функцией любого количества аргументов
заключенных между ограничителями ldelimiter и rdelimiter.
Ограничителем может являться любая строка, если синтаксический анализатор
может различить ограничители от других выражений и операторов.
На практике, это исключает такие ограничители, как
%
, ,
, $
и ;
, и может потребовать при вводе
изолировать ограничители пробелами. Правый ограничитель может
совпадать с левым или отличаться от него.
Левый ограничитель может быть ассоциирован только с одним правым; два различных матчфиксных оператора не могут иметь одинаковых левых ограничителя.
Существующий оператор может быть переобъявлен, как матчфиксный оператор
без изменения других его свойств. Например, встроенные
операторы сложения +
могут быть объявлены матчфиксными, однако
операторные функции для встроенных операторов определены быть не могут.
Вызов matchfix (ldelimiter, rdelimiter, arg_pos, pos)
объявляет аргумент "часть речи" arg_pos и результат "часть речи" pos
вместе с ограничителями ldelimiter и rdelimiter.
Термин "чать речи" по отношению к декларации операторов означает тип выражения.
Различаются три типа выражений: expr
, clause
и any
,
что обозначает алгебраическое выражение, логическое выражение и выражение
произвольного типа соответственно. Maxima может обнаруживать некоторые
синтаксические ошибки сравнивая объявленную часть речи с реальным
выражением.
Функция для выполнения матчфиксной операции является обычной пользовательской
функцией. Операторная функция определяется стандартным образом
при помощи операторов :=
или define
.
Аргументы могут быть записаны между ограничителями или при
помощи левого ограничителя в форме строки и последующих аргументов
в скобках.
dispfun (ldelimiter)
выводит определение
функции.
Единственный встроенный матчфиксный оператор это конструктор
списка [ ]
. Скобки ( )
и двойные кавычки " "
работают как матчфиксные операторы, однако не обрабатываются
синтаксическим анализатором Maxima как таковые.
Функция matchfix
вычисляет свои аргументы.
Функция matchfix
возвращает свой первый аргумент ldelimiter.
Примеры:
(%i1) matchfix ("@@", "~"); (%o1) @@ (%i2) @@ a, b, c ~; (%o2) @@a, b, c~ (%i3) matchfix (">>", "<<"); (%o3) >> (%i4) >> a, b, c <<; (%o4) >>a, b, c<< (%i5) matchfix ("foo", "oof"); (%o5) foo (%i6) foo a, b, c oof; (%o6) fooa, b, coof (%i7) >> w + foo x, y oof + z << / @@ p, q ~; >>z + foox, yoof + w<< (%o7) ---------------------- @@p, q~
(%i1) matchfix ("!-", "-!"); (%o1) "!-" (%i2) !- x, y -! := x/y - y/x; x y (%o2) !-x, y-! := - - - y x (%i3) define (!-x, y-!, x/y - y/x); x y (%o3) !-x, y-! := - - - y x (%i4) define ("!-" (x, y), x/y - y/x); x y (%o4) !-x, y-! := - - - y x (%i5) dispfun ("!-"); x y (%t5) !-x, y-! := - - - y x (%o5) done (%i6) !-3, 5-!; 16 (%o6) - -- 15 (%i7) "!-" (3, 5); 16 (%o7) - -- 15
Удаляет правило подстановки prod -> замена,
определенное при самом последнем вызове функции let
.
При вызове с именем правила в качестве аргумента
удаление производится из соответствующего пакета правил.
Вызовы remlet()
и remlet(all)
удаляют все правила
подстановки из текущего пакета правил. При указании имени, например,
remlet (all, name)
, пакет правил name также удаляется.
Если необходимо изменить правило подстановки одного
произведения, нет необходимости вызывать remlet
, можно просто
переопределить подстановку данного произведения при помощи функции
let
, с новой заменой и/или предикатом.
После этого вызов remlet (prod)
восстанавливает исходное
правило подстановки.
См. также функцию remrule
, которая удаляет правила
определенные функцией tellsimp
или tellsimpafter
.
Удаляет правила, определенные функциями tellsimp
или tellsimpafter
.
remrule (op, rulename)
удаляет правило с именем rulename для оператора op.
Если оператор op является встроенным оператором или определен
пользователем (например, при помощи функций infix
, prefix
,
и т.п.), тогда op и rulename необходимо заключить в двойные кавычки.
remrule (op, all)
удаляет все правила для оператора op.
См. также функцию remlet
, удаляющую правила, определенные при помощи let
.
Примеры:
(%i1) tellsimp (foo (aa, bb), bb - aa); (%o1) [foorule1, false] (%i2) tellsimpafter (aa + bb, special_add (aa, bb)); (%o2) [+rule1, simplus] (%i3) infix ("@@"); (%o3) @@ (%i4) tellsimp (aa @@ bb, bb/aa); (%o4) [@@rule1, false] (%i5) tellsimpafter (quux (%pi, %e), %pi - %e); (%o5) [quuxrule1, false] (%i6) tellsimpafter (quux (%e, %pi), %pi + %e); (%o6) [quuxrule2, quuxrule1, false] (%i7) [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e), quux (%e, %pi)]; bb (%o7) [bb - aa, special_add(aa, bb), --, %pi - %e, %pi + %e] aa (%i8) remrule (foo, foorule1); (%o8) foo (%i9) remrule ("+", "+rule1"); (%o9) + (%i10) remrule ("@@", "@@rule1"); (%o10) @@ (%i11) remrule (quux, all); (%o11) quux (%i12) [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e), quux (%e, %pi)]; (%o12) [foo(aa, bb), bb + aa, aa @@ bb, quux(%pi, %e), quux(%e, %pi)]
аналогична tellsimpafter
, но добавляет
новую информацию о правилах до уже существующей. Таким образом, сначала
применяются пользовательские правила упрощения, а потом правила,
встроенные в систему.
Функция tellsimp
используется, когда важно модифицировать выражение
до того, как оно обработано упрощателем, например, встроенный механизм
упрощения "знает" что-либо о структуре выражения, но возвращает результат,
который вас не устраивает. Если встроенный механизм
упрощения "знает" что-либо о главном операторе выражения, но работает не
достаточно эффективно - можно попробовать использовать tellsimpafter
.
Шаблон не может быть суммой, произведением, одиночной переменной или числом.
rules
- список правил определенный функциями
defrule
, defmatch
, tellsimp
и tellsimpafter
.
Примеры:
(%i1) matchdeclare (x, freeof (%i)); (%o1) done (%i2) %iargs: false$ (%i3) tellsimp (sin(%i*x), %i*sinh(x)); (%o3) [sinrule1, simp-%sin] (%i4) trigexpand (sin (%i*y + x)); (%o4) sin(x) cos(%i y) + %i cos(x) sinh(y) (%i5) %iargs:true$ (%i6) errcatch(0^0); 0 0 has been generated (%o6) [] (%i7) ev (tellsimp (0^0, 1), simp: false); (%o7) [^rule1, simpexpt] (%i8) 0^0; (%o8) 1 (%i9) remrule ("^", %th(2)[1]); (%o9) ^ (%i10) tellsimp (sin(x)^2, 1 - cos(x)^2); (%o10) [^rule2, simpexpt] (%i11) (1 + sin(x))^2; 2 (%o11) (sin(x) + 1) (%i12) expand (%); 2 (%o12) 2 sin(x) - cos (x) + 2 (%i13) sin(x)^2; 2 (%o13) 1 - cos (x) (%i14) kill (rules); (%o14) done (%i15) matchdeclare (a, true); (%o15) done (%i16) tellsimp (sin(a)^2, 1 - cos(a)^2); (%o16) [^rule3, simpexpt] (%i17) sin(y)^2; 2 (%o17) 1 - cos (y)
Определяет правило упрощения, которое встроенный в Maxima механизм
упрощения применяет после встроенных правил упрощения.
pattern - выражение, включающее переменные шаблона (объявленные в matchdeclare
)
и другие атомы и операторы, которые рассматриваются как константы с точки зрения сопоставления с шаблоном.
replacement подставляется вместо первоначального выражения, удовлетворяющего шаблону pattern;
переменным шаблона из в replacement присваиваются соответствующие подвыражения из
реального выражения.
pattern может быть любым составным выражением в котором имя главного
оператор не входит в число переменных шаблона;
правило упрощения связывается с именем главного оператора.
Имена функций (за исключением приведенных ниже), списки и массивы могут присутствовать
в шаблоне pattern в качестве основного оператора только, как
литералы (не переменные шаблона);
это исключает шаблоны вида aa(x)
и bb[y]
,
если aa
и bb
являются переменными шаблона.
Имена функций, списки и массивы, которые являются переменными шаблона
могут входить в качестве не основных операторов в описание шаблона pattern.
Есть одно исключение к указанному правилу, касающееся имен функций.
Имена функций с индексом в выражениях типа aa[x](y)
могут быть переменными шаблона, поскольку в этом случае главный оператор
не aa
, а Lisp-атом mqapply
.
Это является следствием представления выражений, включающих
функции с индексом.
Правила упрощения применяются после вычисления (если вычисления не
запрещены либо экранированием выражения, либо ключом noeval
).
Правила введенные tellsimpafter
применяются в том порядке в
котором они были определены после всех встроенных правил.
Преобразования применяются "снизу-вверх", т.е.,
сначала к подвыражению, перед обработкой выражения в целом.
Иногда для того, чтобы обеспечить, что применены все правила, необходимо повторное упрощение результата
(например, при применении оператора кавычка-кавычка ''
или ключа infeval
).
Переменные шаблона рассматриваются как локальные переменные в правилах
упрощения. Как только правило определено, значение переменной шаблона
не влияет на правило, и наоборот, правило не влияет на значение переменной.
Присваивание значений переменным шаблона, происходящее в результате успешного
сопоставления шаблона, не влияет на текущие значения (или их отсутствие)
переменных шаблона. Однако, как и у всех атомов в Maxima,
свойства переменных шаблона (объявленные оператором put
и подобными функциями) являются глобальными.
Правило, построенное с помощью tellsimpafter
,
обозначаеся именем главного оператора pattern.
Правила для встроенных операторов и пользовательских функций,
определенных при помощи infix
, prefix
,
postfix
, matchfix
и nofix
,
имеют имена, являющиеся Lisp-идентификаторами.
Правила для других функций имеют имена, являющиеся идентификаторами Maxima.
Обработка вычисляемых и не вычисляемых форм немного неоднозначна. Если правило определено для невычисляемой (или вычисляемой) формы выражения, а правило для соответствующей вычисляемой (или невычисляемой) уже существует, то новое правило применяется к обеим формам выражения (вычисляемой и невычисляемой). Если правило для соответствующей вычисляемой (или невычисляемой) не существует, то новое правило применяется к невычисляемой (или вычисляемой) форме выражения.
Правило, построенное с помощью tellsimpafter
, является обычной
Lisp- функцией. Если имя правила - $foorule1
, то
конструкция :lisp (trace $foorule1)
дает трассировку ее вызовов,
а :lisp (symbol-function '$foorule1
выводит ее определение.
Функция tellsimpafter
не вычисляет свои аргументы.
Функция tellsimpafter
возвращает список правил для основного оператора
шаблона pattern, включая вновь объявленные правила.
См. также matchdeclare
, defmatch
, defrule
, tellsimp
, let
,
kill
, remrule
и clear_rules
.
Примеры:
pattern может быть любым неатомарным выражением в котором главный оператор не является переменной шаблона.
(%i1) matchdeclare (aa, atom, [ll, mm], listp, xx, true)$ (%i2) tellsimpafter (sin (ll), map (sin, ll)); (%o2) [sinrule1, simp-%sin] (%i3) sin ([1/6, 1/4, 1/3, 1/2, 1]*%pi); 1 sqrt(2) sqrt(3) (%o3) [-, -------, -------, 1, 0] 2 2 2 (%i4) tellsimpafter (ll^mm, map ("^", ll, mm)); (%o4) [^rule1, simpexpt] (%i5) [a, b, c]^[1, 2, 3]; 2 3 (%o5) [a, b , c ] (%i6) tellsimpafter (foo (aa (xx)), aa (foo (xx))); (%o6) [foorule1, false] (%i7) foo (bar (u - v)); (%o7) bar(foo(u - v))
Правила применяются в том порядке в котором они были определены. Если два правила соответствуют выражению, то первым применяется то, которое было определено раньше.
(%i1) matchdeclare (aa, integerp); (%o1) done (%i2) tellsimpafter (foo (aa), bar_1 (aa)); (%o2) [foorule1, false] (%i3) tellsimpafter (foo (aa), bar_2 (aa)); (%o3) [foorule2, foorule1, false] (%i4) foo (42); (%o4) bar_1(42)
Переменные шаблона являются локальными переменные правил упрощения.
(Сравни с функцией defmatch
, которая рассматривает переменные
шаблона, как глобальные).
(%i1) matchdeclare (aa, integerp, bb, atom); (%o1) done (%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb)); (%o2) [foorule1, false] (%i3) bb: 12345; (%o3) 12345 (%i4) foo (42, %e); (%o4) bar(aa = 42, bb = %e) (%i5) bb; (%o5) 12345
Как и у всех атомов, свойства переменных шаблона
являются глобальными даже если их значение локально.
В данном примере свойство объявляется при помощи define_variable
.
Это свойство атома bb
является глобальным.
(%i1) matchdeclare (aa, integerp, bb, atom); (%o1) done (%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb)); (%o2) [foorule1, false] (%i3) foo (42, %e); (%o3) bar(aa = 42, bb = %e) (%i4) define_variable (bb, true, boolean); (%o4) true (%i5) foo (42, %e); Error: bb was declared mode boolean, has value: %e -- an error. Quitting. To debug this try debugmode(true);
Правила именуются по имени основного оператора. Имена правил для встроенных и пользовательских операторов являются Lisp-идентификаторами, тогда как имена других функций являются идентификаторами Maxima.
(%i1) tellsimpafter (foo (%pi + %e), 3*%pi); (%o1) [foorule1, false] (%i2) tellsimpafter (foo (%pi * %e), 17*%e); (%o2) [foorule2, foorule1, false] (%i3) tellsimpafter (foo (%i ^ %e), -42*%i); (%o3) [foorule3, foorule2, foorule1, false] (%i4) tellsimpafter (foo (9) + foo (13), quux (22)); (%o4) [+rule1, simplus] (%i5) tellsimpafter (foo (9) * foo (13), blurf (22)); (%o5) [*rule1, simptimes] (%i6) tellsimpafter (foo (9) ^ foo (13), mumble (22)); (%o6) [^rule1, simpexpt] (%i7) rules; (%o7) [foorule1, foorule2, foorule3, +rule1, *rule1, ^rule1] (%i8) foorule_name: first (%o1); (%o8) foorule1 (%i9) plusrule_name: first (%o4); (%o9) +rule1 (%i10) remrule (foo, foorule1); (%o10) foo (%i11) remrule ("^", ?\^rule1); (%o11) ^ (%i12) rules; (%o12) [foorule2, foorule3, +rule1, *rule1]
Рабочий пример: антикоммутативное умножение.
(%i1) gt (i, j) := integerp(j) and i < j; (%o1) gt(i, j) := integerp(j) and i < j (%i2) matchdeclare (i, integerp, j, gt(i)); (%o2) done (%i3) tellsimpafter (s[i]^^2, 1); (%o3) [^^rule1, simpncexpt] (%i4) tellsimpafter (s[i] . s[j], -s[j] . s[i]); (%o4) [.rule1, simpnct] (%i5) s[1] . (s[1] + s[2]); (%o5) s . (s + s ) 1 2 1 (%i6) expand (%); (%o6) 1 - s . s 2 1 (%i7) factor (expand (sum (s[i], i, 0, 9)^^5)); (%o7) 100 (s + s + s + s + s + s + s + s + s + s ) 9 8 7 6 5 4 3 2 1 0
Исполняет kill (rules)
и обнуляет счетчик, т.е. новое правило
будет иметь номер 1
вслед за встроенными правилами для операторов суммы
+
, умножения *
и степени ^
.