Previous: Введение в правила преобразований и шаблоны, Up: Правила преобразования и шаблоны   [Contents][Index]

34.2 Функции и переменные для правил преобразования и шаблонов

Функция: apply1 (expr, rule_1, ..., rule_n)

Осуществляет повторное применение правила преобразования rule_1 к expr до тех пор пока выражение отвечает шаблону преобразования, затем, таким же образом осуществляется повторное применение этого правила ко всем подвыражениям expr, слева направо. Далее, к полученному результату тем же способом применяется правило rule_2 и так далее все последующие правила вплоть до rule_n. Конечный результат возвращается.

Переменная maxapplydepth контролирует нижнюю глубину уровня подвыражения до которого применяются правила преобразований в функциях apply1 и apply2.

См. также applyb1, apply2 и let.

Функция: apply2 (expr, rule_1, ..., rule_n)

Если правило rule_1 неприменимо на подвыражении expr, тогда применяется правило rule_2 и далее по той же схеме остальные правила. Только если каждое из правил является неприменимым на данном подвыражении expr, программа переходит на следующий уровень подвыражнния expr, и по той же схеме последовательно применяет весь набор правил, начиная с первого. Если применение одного из правил оказывается успешным, тогда весь набор правил заново применяется к этому подвыражению.

Переменная maxapplydepth контролирует нижнюю глубину уровня подвыражения до которого применяются правила преобразований в функциях apply1 и apply2.

См. также apply1 и let.

Функция: applyb1 (expr, rule_1, ..., rule_n)

В отличие от apply1 применяется по восходящей, т.е., сначала на самом глубоком уровне expr повторяется применение правила rule_1. Затем программа переходит на более высокие уровни expr и применяет данное правило по той же схеме. После того как применение правила rule_1 терпит неудачу на самом вернем уровне expr программа переходит к применению правила rule_2 по той же схеме (по восходящей) и так далее, заканчивая применением правила rule_n. После этого возвращается результат.

Функция applyb1 аналогична apply1, но работает по восходящей.

Переменная maxapplyheight контролирует высоту уровня подвыражения до которого применяются правила преобразований в функции applyb1.

См. также apply1, apply2 и let.

Управляющая переменная: current_let_rule_package

Значение по умолчанию: 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

default_let_rule_package - имя пакета правил, используемого по умолчанию, если пакет правил не был задан в явном виде при вызове let или через изменение значения переменной current_let_rule_package.

Функция: defmatch (progname, pattern, x_1, ..., x_n)
Функция: defmatch (progname, pattern)

Определяет функцию 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)]
Функция: defrule (rulename, pattern, replacement)

Определяет и именует правило преобразования для данного шаблона. Если правило c именем rulename применяется к выражению (путем apply1, applyb1 или apply2), то каждое подвыражение, удовлетворяющее шаблону, заменяется соответствующей подстановкой. После этого выражение упрощается.

Правила могут рассматриваться как функции, преобразующие выражение путем одной операции сопоставления с шаблоном и подстановки. При неудаче сопоставления, функция правила преобразования возвращает false.

Функция: disprule (rulename_1, ..., rulename_2)
Функция: disprule (all)

Выводит правила преобразований и их имена 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) -> []]
Функция: let (prod, repl, predname, arg_1, ..., arg_n)
Функция: let ([prod, repl, predname, arg_1, ..., arg_n], package_name)

Определяет правила подстановки для функции letsimp такие, что prod заменяется на repl. prod является произведением подвыражений положительной или отрицательной степени. Подвыражения могут быть следующего типа:

Члены положительной степени будут сопоставляться только членам, имеющим положительную степень. Члены отрицательной степени будут сопоставляться только членам, имеющим отрицательную степень. Для того чтобы 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
Управляющая переменная: letrat

Значение по умолчанию: 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)

Выводит правила, содержащиеся в пакете правил преобразований. letrules () выводит правила текущего пакета правил преобразований. letrules (package_name) выводит правила преобразований в пакете package_name.

Текущий пакет правил определяется значением current_let_rule_package. Если не определено иначе, то current_let_rule_package по умолчанию равен default_let_rule_package.

См. также функцию disprule, отображающую правила, определенные путем tellsimp и tellsimpafter.

Функция: letsimp (expr)
Функция: letsimp (expr, package_name)
Функция: letsimp (expr, package_name_1, ..., package_name_n)

Данная функция осуществляет повторное применение правил подстановки, определенных в 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) и так далее.

Управляющая переменная: let_rule_packages

Значение по умолчанию: [default_let_rule_package]

let_rule_packages - список определенных пользователем пакетов правил вместе с пакетом default_let_rule_package.

Функция: matchdeclare (a_1, pred_1, ..., a_n, pred_n)

Связывает предикат 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)
Функция: matchfix (ldelimiter, rdelimiter, arg_pos, pos)

Объявляет матчфиксный (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
Функция: remlet (prod, name)
Функция: remlet ()
Функция: remlet (all)
Функция: remlet (all, name)

Удаляет правило подстановки prod -> замена, определенное при самом последнем вызове функции let. При вызове с именем правила в качестве аргумента удаление производится из соответствующего пакета правил.

Вызовы remlet() и remlet(all) удаляют все правила подстановки из текущего пакета правил. При указании имени, например, remlet (all, name), пакет правил name также удаляется.

Если необходимо изменить правило подстановки одного произведения, нет необходимости вызывать remlet, можно просто переопределить подстановку данного произведения при помощи функции let, с новой заменой и/или предикатом. После этого вызов remlet (prod) восстанавливает исходное правило подстановки.

См. также функцию remrule, которая удаляет правила определенные функцией tellsimp или tellsimpafter.

Функция: remrule (op, rulename)
Функция: remrule (op, all)

Удаляет правила, определенные функциями 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)]
Функция: tellsimp (pattern, replacement)

аналогична 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)
Функция: tellsimpafter (pattern, replacement)

Определяет правило упрощения, которое встроенный в 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
Функция: clear_rules ()

Исполняет kill (rules) и обнуляет счетчик, т.е. новое правило будет иметь номер 1 вслед за встроенными правилами для операторов суммы +, умножения * и степени ^.


Previous: Введение в правила преобразований и шаблоны, Up: Правила преобразования и шаблоны   [Contents][Index]