@c /Rules.texi/1.25/Fri Mar  2 00:44:44 2007/-ko/

@menu
* Introdução a Regras e Modelos::  
* Definições para Regras e Modelos::  
@end menu

@node Introdução a Regras e Modelos, Definições para Regras e Modelos, Regras e Modelos, Regras e Modelos
@section Introdução a Regras e Modelos

Essa secção descreve coincidências de modelos definidos pelo utilizador e
regras de simplificação.
Existem dois grupos de funções que implementam até certo ponto diferentes esquemas de coincidência de modelo.
Em um grupo estão @code{tellsimp}, @code{tellsimpafter}, @code{defmatch}, @code{defrule},
@code{apply1}, @code{applyb1}, e @code{apply2}.
Em outro grupo estão @code{let} e @code{letsimp}.
Ambos os esquemas definem modelos em termos de variáveis de modelo declaradas por @code{matchdeclare}.

Regras de coincidência de modelos definidas por @code{tellsimp} e @code{tellsimpafter} são aplicadas automaticamente
através do simplificador do Maxima.
Regras definidas através de @code{defmatch}, @code{defrule}, e @code{let} são aplicadas
através de uma chamada explícita de função.

Existe mecanismos adicionais para regras aplicadas a polinómios através de @code{tellrat},
e para álgebra comutativa e não comutativa no pacote @code{affine}. 

@c end concepts Rules and Patterns
@node Definições para Regras e Modelos,  , Introdução a Regras e Modelos, Regras e Modelos
@section Definições para Regras e Modelos

@c NEEDS CLARIFICATION AND EXAMPLES
@deffn {Função} apply1 (@var{expr}, @var{rule_1}, ..., @var{rule_n})
Repetidamente aplica @var{rule_1} a
@var{expr} até que isso falhe, então repetidamente aplica a mesma regra a todas
as subexpressões de @var{expr}, da esquerda para a direita, até que @var{rule_1} tenha falhado
sobre todas as subexpressões.  Chama o resultado da transformação de @var{expr} dessa
maneira de @var{expr_2}.  Então @var{rule_2} é aplicada no mesmo estilo
iniciando no topo de @var{expr_2}.  Quando @var{rule_n} falhar na subexpressão
final, o resultado é retornado.

@code{maxapplydepth} é a intensidade de nível mais distante de subexpressões processadas por
@code{apply1} e @code{apply2}.

Veja também @code{applyb1}, @code{apply2}, e @code{let}.

@end deffn

@c NEEDS CLARIFICATION AND EXAMPLES
@deffn {Função} apply2 (@var{expr}, @var{rule_1}, ..., @var{rule_n})
Se @var{rule_1} falhar sobre uma dada subexpressão, então @var{rule_2} é
repetidamente aplicada, etc.  Somente se todas as regras falharem sobre uma dada
subexpressão é que o conjunto completo de regras é repetidamente aplicada à próxima
subexpressão.  Se uma das regras obtém sucesso, então a mesma
subexpressão é reprocessada, iniciando com a primeira regra.

@code{maxapplydepth} é a intensidade do nível mais distante de subexpressões processadas através de
@code{apply1} e @code{apply2}.

Veja também @code{apply1} e @code{let}.

@end deffn

@c NEEDS CLARIFICATION AND EXAMPLES
@deffn {Função} applyb1 (@var{expr}, @var{rule_1}, ..., @var{rule_n})
Repetidamente aplica @var{rule_1} para a subexpressão mais distante de @var{expr} até falhar,
então repetidamente aplica a mesma regra um nível mais acima (i.e., subexpressãos mais larga),
até que @var{rule_1} tenha falhado sobre a expressão de nível mais alto.
Então @var{rule_2} é aplicada com o mesmo estilo para o resultado de @var{rule_1}.
após @var{rule_n} ter sido aplicada à expressão de nível mais elevado,
o resultado é retornado.

@code{applyb1} é similar a @code{apply1} mas trabalha da
base para cima em lugar de do topo para baixo.

@code{maxapplyheight} é o ápice que @code{applyb1} encontra
antes de interromper.

Veja também @code{apply1}, @code{apply2}, e @code{let}.

@end deffn

@defvr {Variável de opção} current_let_rule_package
Valor por omissão: @code{default_let_rule_package}

@code{current_let_rule_package} é o nome do pacote de regras que está sendo usado por
funções no pacote @code{let} (@code{letsimp}, etc.) @c NEED TO GIVE AN EXPLICIT LIST HERE (NOT "ETC")
se nenhum outro pacote de regras for especificado.
A essa variável pode ser atribuído o nome de qualquer pacote de regras definido
via comando @code{let}.

Se uma chamada tal como @code{letsimp (expr, nome_pct_regras)} for feita,
o pacote de regras @code{nome_pct_regras} é usado para aquela chamada de função somente,
e o valor de @code{current_let_rule_package} não é alterado.

@end defvr

@defvr {Variável de opção} default_let_rule_package
@c DEFAULT BINDING OF default_let_rule_package IS default_let_rule_package (BOUND TO ITSELF)
Valor por omissão: @code{default_let_rule_package}

@c THIS IS SORT OF CONFUSING. PROBABLY NEED TO GIVE MORE DETAIL HERE
@code{default_let_rule_package} é o nome do pacote de regras usado quando um
não for explicitamente escolhido pelo utilizador com @code{let} ou através de alteração do valor de
@code{current_let_rule_package}.

@end defvr

@deffn {Função} defmatch (@var{prognome}, @var{modelo}, @var{x_1}, ..., @var{x_n})
@deffnx {Função} defmatch (@var{prognome}, @var{modelo})
Define uma função @code{@var{prognome}(@var{expr}, @var{x_1}, ..., @var{x_n})}
que testa @var{expr} para ver se essa expressão coincide com @var{modelo}.

@var{modelo} é uma expressão contendo os argumentos modelo @var{x_1}, ..., @var{x_n} (se existir algum)
e alguns modelos de variáveis (se existir algum).
os argumentos modelo são fornecidos explicitamente como argumentos para @code{defmatch} enquanto os modelos de variáveis
são declarados através da função @code{matchdeclare}.
Qualquer variável não declarada como modelo em @code{matchdeclare}
ou como um argumento modelo em @code{defmatch} coincide somente com si mesma.

O primeiro argumento para a função criada @var{prognome} é uma expressão
a serem comparadas contra o modelo  e os outros argumentos são os atuais argumetnos
que correspondem às variáveis respectivas @var{x_1}, ..., @var{x_n} no modelo.

Se a tentativa de coincidência obtiver sucesso, @var{prognome} retorna
uma lista de equações cujos lados esquerdos são os
argumetnos de modelo e variáveis de modelo, e cujo lado direito forem as subexpressões
cujos argumentos de modelo e as variáveis coincidem.
Os modelos de variáveis, mas não tos argumentos de modelo, são atribuídos às subexpressões que coincidirem.
Se a coincidência falhar, @var{prognome} retorna @code{false}.  

Um modelo literal
(isto é, um modelo que não contiver nem argumentos de modelo nem variáveis de modelo)
retorna @code{true} se a coincidência ocorrer.

Veja também @code{matchdeclare}, @code{defrule}, @code{tellsimp}, e @code{tellsimpafter}.

Exemplos:

Define uma função @code{linearp(expr, x)} que
testa @code{expr} para ver se essa expressão da forma @code{a*x + b}
tal que @code{a} e @code{b} não contenham @code{x} e @code{a} seja não nulo.
Essa função de coincidência coincide com expressões que sejam lineares em qualquer variável,
por que o argumento de modelo @code{x} é fornecido para @code{defmatch}.
@c HOW HARD WILL MAXIMA TRY TO COLLECT TERMS AND DO OTHER MUNGEING TO FIT THE PATTERN ??

@c ===beg===
@c matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b, freeof(x));
@c defmatch (linearp, a*x + b, x);
@c linearp (3*z + (y + 1)*z + y^2, z);
@c a;
@c b;
@c x;
@c ===end===
@example
(%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
@end example

Define uma função @code{linearp(expr)} que testa @code{expr}
para ver se essa expressão é da forma @code{a*x + b}
tal que @code{a} e @code{b} não contenham @code{x} e @code{a} seja não nulo.
Essa função de coincidência somente coincide com expressões lineares em @code{x},
não em qualquer outra variável, porque nenhum argumento de modelo é fornecido a @code{defmatch}.

@c ===beg===
@c matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b, freeof(x));
@c defmatch (linearp, a*x + b);
@c linearp (3*z + (y + 1)*z + y^2);
@c linearp (3*x + (y + 1)*x + y^2);
@c ===end===
@example
(%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]
@end example

Define uma função @code{checklimits(expr)} que testa @code{expr}
para ver se essa expressão é uma integral definida.
 
@c ===beg===
@c matchdeclare ([a, f], true);
@c constinterval (l, h) := constantp (h - l);
@c matchdeclare (b, constinterval (a));
@c matchdeclare (x, atom);
@c simp : false;
@c defmatch (checklimits, 'integrate (f, x, a, b));
@c simp : true;
@c 'integrate (sin(t), t, %pi + x, 2*%pi + x);
@c checklimits (%);
@c ===end===
@example
(%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)]
@end example

@end deffn

@c NEEDS CLARIFICATION AND EXAMPLES
@deffn {Função} defrule (@var{nomeregra}, @var{modelo}, @var{substituição})
Define e nomeia uma
regra de substituição para o modelo dado.  Se a regra nomeada @var{nomeregra} for
aplicada a uma expressão (através de @code{apply1}, @code{applyb1}, ou @code{apply2}), toda
subexpressão coincidindo com o modelo será substituída por
@code{substituição}. Todas as variáveis em @code{substituição} que tiverem sido
atribuidos valores pela coincidência com o modelo são atribuidas esses valores na
@code{substituição} que é então simplificado.

As regras por si mesmas podem ser
tratadas como funções que transforma uma expressão através de uma
operação de coincidência de modelo e substituição.
Se a coincidência falhar, a função da regra retorna @code{false}.

@end deffn

@c NEEDS EXAMPLES
@deffn {Função} disprule (@var{nomeregra_1}, ..., @var{nomeregra_2})
@deffnx {Função} disprule (all)
Mostra regras com os nomes @var{nomeregra_1}, ..., @var{nomeregra_n},
como retornado por @code{defrule}, @code{tellsimp}, ou @code{tellsimpafter},
ou um modelo definido por meio de @code{defmatch}.

Cada regra é mostrada com um rótulo de expressão intermédia (@code{%t}).

@code{disprule (all)} mostra todas as regras.

@code{disprule} não avalia seus argumentos.

@code{disprule} retorna a lista de rótulos de expressões intermedáirias correspondendo às regras mostradas.

Veja também @code{letrules}, que mostra regras definidas através de @code{let}.

Examples:

@c ===beg===
@c tellsimpafter (foo (x, y), bar (x) + baz (y));
@c tellsimpafter (x + y, special_add (x, y));
@c defmatch (quux, mumble (x));
@c disprule (foorule1, "+rule1", quux);
@c ''%;
@c ===end===
@example
(%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) -> []]
@end example

@end deffn

@deffn {Função} let (@var{prod}, @var{repl}, @var{prednome}, @var{arg_1}, ..., @var{arg_n})
@deffnx {Função} let ([@var{prod}, @var{repl}, @var{prednome}, @var{arg_1}, ..., @var{arg_n}], @var{nome_pacote})
Define uma regra de substituição para @code{letsimp} tal que @var{prod} é substituído por @var{repl}.
@var{prod} é um produto de expoentes positivos ou negativos dos seguintes termos:

@itemize @bullet
@item
Atomos que @code{letsimp} irá procurar literalmente a menos que previamente
chamando @code{letsimp} a função @code{matchdeclare} é usada para associar um
predicado com o átomo.  Nesse caso @code{letsimp} irá coincidir com o átomo para
qualquer termo de um produto satisfazendo o predicado.
@item
Núcleos tais como @code{sin(x)}, @code{n!}, @code{f(x,y)}, etc.  Como com átomos acima
@code{letsimp} irá olhar um literal coincidente a menos que @code{matchdeclare} seja usada para
associar um predicado com o argumento do núcleo.
@end itemize

Um termo para um expoente positivo irá somente coincidir com um termo tendo ao menos aquele
expoente.  Um termo para um expoente negativo
por outro lado irá somente coincidir com um termo com um expoente ao menos já
negativo.  o caso de expentes negativos em @var{prod} o comutador
@code{letrat} deve ser escolhido para @code{true}.
Veja também @code{letrat}.

Se um predicado for incluído na função @code{let} seguido por uma lista de
argumentos, uma tentativa de coincidência (i.e. uma que pode ser aceita se o
predicado fosse omitido) é aceita somente se
@code{prednome (arg_1', ..., arg_n')} avaliar para @code{true} onde @var{arg_i'} é o valor
coincidente com @var{arg_i}.  O @var{arg_i} pode ser o nome de qualquer átomo ou o argumento
de qualquer núcleo aparecendo em @var{prod}.
@var{repl} pode ser qualquer expressão racional. @c ONLY RATIONAL -- REALLY ??
Se quaisquer dos átomos ou argumentos de @var{prod} aparecer em @var{repl} a
substituição é feita. @c SPELL OUT "APPROPRIATE" IN THIS CONTEXT

O sinalizador global @code{letrat} controla a simplificação dos quocientes através de @code{letsimp}.
Quando @code{letrat} for @code{false},
@code{letsimp} simplifica o numerador e o
denominador de @var{expr} separadamente, e não simplifica o quociente.
Substituições tais como @code{n!/n} vão para @code{(n-1)!} então falham quando @code{letrat} for @code{false}.
Quando @code{letrat} for @code{true}, então o numerador,
o denominador, e o quociente são simplificados nessa ordem.

Essas funções de substituição
permitem-lhe trabalhar com muitos pacotes de regras.  Cada pacote de
regras pode conter qualquer número de regras @code{let} e é
referenciado através de um nome definido pelo utilizador.  @code{let
([@var{prod}, @var{repl}, @var{prednome}, @var{arg_1}, ...,
@var{arg_n}], @var{nome_pacote})} adiciona a regra @var{prednome} ao
pacote de regras @var{nome_pacote}.  @code{letsimp (@var{expr},
@var{nome_pacote})} aplica as regras em @var{nome_pacote}.
@code{letsimp (@var{expr}, @var{nome_pacote1}, @var{nome_pacote2}, ...)}
é equivalente a @code{letsimp (@var{expr}, @var{nome_pacote1})}
seguido por @code{letsimp (%, @var{nome_pacote2})}, ....

@code{current_let_rule_package} é o nome do pacote de regras que está
actualmente sendo usando.
Essa variável pode receber o nome de
qualquer pacote de regras definidos via o comando @code{let}.
Quando qualquer das funções compreendidas no pacote @code{let} são chamadas sem o nome do pacote,
o pacote nomeado por @code{current_let_rule_package} é usado.
Se uma chamada tal como @code{letsimp (@var{expr}, @var{nome_pct_regras})} é feita,
o pacote de regras @var{nome_pct_regras} é usado somente para aquele comando @code{letsimp},
e @code{current_let_rule_package} não é alterada.
Se não especificado de outra forma,
@code{current_let_rule_package} avalia de forma padronizada para @code{default_let_rule_package}.

@example
(%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
@end example

@c NEEDS ADDITIONAL EXAMPLES
@end deffn

@defvr {Variável de opção} letrat
Valor por omissão: @code{false}

Quando @code{letrat} for @code{false}, @code{letsimp} simplifica o
numerador e o denominador de uma razão separadamente,
e não simplifica o quociente.

Quando @code{letrat} for @code{true},
o numerador, o denominador, e seu quocienten são simplificados nessa ordem.

@example
(%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)!
@end example

@end defvr

@c NEEDS EXAMPLES
@deffn {Função} letrules ()
@deffnx {Função} letrules (@var{nome_pacote})
Mostra as regras em um pacote de regras.
@code{letrules ()} mostra as regras no pacote de regras corrente.
@code{letrules (@var{nome_pacote})} mostra as regras em @code{nome_pacote}.

O pacote de regras corrente é nomeado por @code{current_let_rule_package}.
Se não especificado de outra forma, @code{current_let_rule_package}
avalia de forma padrão para @code{default_let_rule_package}.

Veja também @code{disprule}, que mostra regras defindas por @code{tellsimp} e @code{tellsimpafter}.
@c WHAT ABOUT defmatch AND defrule ??

@end deffn

@deffn {Função} letsimp (@var{expr})
@deffnx {Função} letsimp (@var{expr}, @var{nome_pacote})
@deffnx {Função} letsimp (@var{expr}, @var{nome_pacote_1}, ..., @var{nome_pacote_n})
Repetidamente aplica a substituição definida por @code{let}
até que nenhuma mudança adicional seja feita para @var{expr}.

@code{letsimp (@var{expr})} usa as regras de @code{current_let_rule_package}.

@code{letsimp (@var{expr}, @var{nome_pacote})} usa as regras de @var{nome_pacote}
sem alterar @code{current_let_rule_package}.

@code{letsimp (@var{expr}, @var{nome_pacote_1}, ..., @var{nome_pacote_n})}
é equivalente a @code{letsimp (@var{expr}, @var{nome_pacote_1}},
seguido por @code{letsimp (%, @var{nome_pacote_2})}, e assim sucessivamente.

@c NEEDS EXAMPLES
@end deffn

@defvr {Variável de opção} let_rule_packages
Valor por omissão: @code{[default_let_rule_package]}

@code{let_rule_packages} é uma lista de todos os pacotes de regras @code{let} definidos pelo utilizador
mais o pacote padrão @code{default_let_rule_package}.

@end defvr

@deffn {Função} matchdeclare (@var{a_1}, @var{pred_1}, ..., @var{a_n}, @var{pred_n})
Associa um predicado @var{pred_k} 
com uma variável ou lista de variáveis @var{a_k}
de forma que @var{a_k} coincida com expressões
para as quais o predicado retorne qualquer coisa que não @code{false}.

Umpredicado é o nome de uma função,
ou de uma expressão lambda,
ou uma chamada de função ou chamada de função lambda iomitindo o úlltimo argumento,
ou @code{true} ou @code{all}.
Qualquer expressão coincide com @code{true} ou @code{all}.
Se o predicado for especificado como uma chamada de função ou chamada de função lambda,
a expressão a ser testada é anexada ao final da lista de argumentos;
os argumentos são avaliados ao mesmo tempo que a coincidência é avaliada.
De outra forma, o predicado é especificado como um nome de função ou expressão lambda,
e a expressão a ser testada é o argumento sozinho.
Uma função predicado não precisa ser definida quando @code{matchdeclare} for chamada;
o predicado não é avaliado até que uma coincidência seja tentada.

Um predicado pode retornar uma expressão Booleana além de @code{true} ou @code{false}.
Expressões Booleanas são avaliadas por @code{is} dentro da função da regra construída,
de forma que não é necessário chamar @code{is} dentro do predicado.

Se uma expressão satisfaz uma coincidência de predicado,
a variável de coincidência é atribuída à expressão,
excepto para variáveis de coincidência que são operandos de adição @code{+} ou multiplicação @code{*}.
Somente adição e multiplicação são manuseadas de forma especial;
outros operadores enários (ambos os definidos internamente e os definidos pelo utilizador) são tratados como funções comuns.
@c WOULD BE GREAT TO EXTEND PART+/PART* PROCESSING TO ALL N-ARY OPERATORS

No caso de adição e multiplicação,
a variável de coincidência pode ser atribuida a uma expressão simples que satisfaz o predicado de coincidência,
ou uma adição ou um produto (respectivamente) de tais expressões.
Tal coincidência de termo multiplo é gulosa:
predicados são avaliados na ordem em que suas variáveis associadas
aparecem no modelo de coincidência,
e o termo que satisfizer mais que um predicado é tomado pelo primeiro
predicado que satisfizer.
Cada predicado é testado contra todos os operandos de adição ou produto antes que o próximo predicado seja avaliado.
Adicionalmente,
se 0 ou 1 (respectivamente) satisfazem um predicado de coincidência,
e não existe outros termos que satisfaçam o predicado,
0 ou 1 é atribuído para a variável de coincidência associada com o predicado.

O algoritmo para processar modelos contendo adição e multiplicação faz alguns resultados de coincidência
(por exemplo, um modelo no qual uma variável "coincida com qualquer coisa" aparecer)
dependerem da ordem dos termos no modelo de coincidência e na expressão a ser testada a coincidência.
Todavia,
se todos os predicados de coincidência são mutuamente exclusivos,
o resultado de coincidência é insensível a ordenação,
como um predicado de coincidência não pode aceitar termos de coincidência de outro.

Chamado @code{matchdeclare} com uma variável @var{a} como um argumento
muda a propriedade @code{matchdeclare} para @var{a}, se a variável @var{a} tiver sido declarada anteriormente;
somente o @code{matchdeclare} mais recente está em efeito quando uma regra é definida,
mudanças posteriores para a propriedade @code{matchdeclare}
(via @code{matchdeclare} ou @code{remove})
não afectam regras existentes.

@code{propvars (matchdeclare)} retorna a lista de todas as variáveis
para as quais exista uma propriedade @code{matchdeclare}.
@code{printprops (@var{a}, matchdeclare)} retorna o predicado para a variável @code{a}.
@code{printprops (all, matchdeclare)} retorna a lista de predicados para todas as variáveis @code{matchdeclare}.
@code{remove (@var{a}, matchdeclare)} remove a propriedade @code{matchdeclare} da variável @var{a}.

As funções
@code{defmatch}, @code{defrule}, @code{tellsimp}, @code{tellsimpafter}, e @code{let}
constroem regras que testam expressões contra modelos.

@code{matchdeclare} coloca apóstrofo em seus argumentos.
@code{matchdeclare} sempre retorna @code{done}.

Exemplos:

Um predicado é o nome de uma função,
ou uma expressão lambda,
ou uma chamada de função ou chamada a função lambda omitindo o último argumento,
or @code{true} or @code{all}.

@c ===beg===
@c matchdeclare (aa, integerp);
@c matchdeclare (bb, lambda ([x], x > 0));
@c matchdeclare (cc, freeof (%e, %pi, %i));
@c matchdeclare (dd, lambda ([x, y], gcd (x, y) = 1) (1728));
@c matchdeclare (ee, true);
@c matchdeclare (ff, all);
@c ===end===
@example
(%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
@end example

Se uma expressão satisfaz um predicado de coincidência,
a variável de coincidência é atribuída à expressão.

@c ===beg===
@c matchdeclare (aa, integerp, bb, atom);
@c defrule (r1, bb^aa, ["integer" = aa, "atom" = bb]);
@c r1 (%pi^8);
@c ===end===
@example
(%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]
@end example

No caso de adição e multiplicação,
à variável de coincidência pode ser atribuída uma expressão simples que satisfaz o predicado de coincidência,
ou um somatório ou produtório (respectivamente) de tais expressões.

@c ===beg===
@c matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
@c defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" = bb]);
@c r1 (8 + a*b + sin(x));
@c defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" = bb]);
@c r2 (8 * (a + b) * sin(x));
@c ===end===
@example
(%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)]
@end example

Quando coincidindo argumentos de @code{+} e @code{*},
se todos os predicados de coincidência forem mutuamente exclusivos,
o resultado da coincidência é insensíve à ordenação,
como um predicado de coincidência não pode aceitar termos que coincidiram com outro.

@c ===beg===
@c matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
@c defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" = bb]);
@c r1 (8 + a*b + %pi + sin(x) - c + 2^n);
@c defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" = bb]);
@c r2 (8 * (a + b) * %pi * sin(x) / c * 2^n);
@c ===end===
@example
(%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
@end example

As funções @code{propvars} e @code{printprops} retornam informações sobre variávels de coincidência.

@c ===beg===
@c matchdeclare ([aa, bb, cc], atom, [dd, ee], integerp);
@c matchdeclare (ff, floatnump, gg, lambda ([x], x > 100));
@c propvars (matchdeclare);
@c printprops (ee, matchdeclare);
@c printprops (gg, matchdeclare);
@c printprops (all, matchdeclare);
@c ===end===
@example
(%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)]
@end example

@end deffn

@deffn {Função} matchfix (@var{delimitador_e}, @var{delimitador_d})
@deffnx {Função} matchfix (@var{delimitador_e}, @var{delimitador_d}, @var{arg_pos}, @var{pos})
Declara um operador @code{matchfix} com delimitadores esquerdo e direito @var{delimitador_e} e @var{delimitador_d}.
Os delimitadores são especificados como sequêcias de caracteres.

Um operador "matchfix" é uma função que aceita qualquer número de argumentos,
tal que os argumentos ocorram entre os delimitadores correspondentes esquerdo e direito.
Os delimitadores podem ser quaisquer sequêcias de caracteres, contanto que o analisador de expressões do Maxima possa
distinguir os delimitadores dos operandos 
e de outras expressões e operadores.
Na prática essas regras excluem delimitadores não analisáveis tais como
@code{%}, @code{,}, @code{$} e @code{;}, 
e pode ser necessário isolar os delimitadores com espaços em branco.
O delimitador da direita pode ser o mesmo ou diferente do delimitador da esquerda.

Um delimitador esquerdo pode ser associado com somente um delimitador direito;
dois diferentes operadores @code{matchfix} não podem ter o mesmo delimitador esquerdo.

Um operador existente pode ser redeclarado com um operador @code{matchfix}
sem alterar suas outras propriedades.
Particularmente, operadores internos tais como adição @code{+} podem
ser declarados @code{matchfix},
mas funções operadores não podem ser definidas para operadores internos.

@code{matchfix (@var{delimitador_e}, @var{delimitador_d}, @var{arg_pos}, @var{pos})} 
declara o argumento @var{arg_pos} como sendo um entre: expressão lógica,
expressão comum do Maxima mas que não seja do tipo anterior, e qualquer outro
tipo de expressão que não esteja incluída nos dois primeiros tipos.
Essa declaração resulta em @var{pos} sendo um entre: expressão lógica,
expressão comum do Maxima mas que não seja do tipo anterior, e qualquer outro
tipo de expressão que não esteja incluída nos dois primeiros tipos 
e os delimitadores @var{delimitador_e} e @var{delimitador_d}.

@c DUNNO IF WE REALLY NEED TO MENTION BINDING POWER HERE -- AS NOTED IT'S IRRELEVANT
@c An operator declared by @code{matchfix} is assigned a low binding power.
@c Since a matchfix operator must be evaluated before any expression
@c which contains it,
@c binding power is effectively irrelevant
@c to the declaration of a matchfix operator.

A função para realizar uma operação @code{matchfix} é uma função
comum definida pelo utilizador.
A função operador é definida
da forma usual
com o operador de definição de função @code{:=} ou @code{define}.
Os argumentos podem ser escritos entre os delimitadores,
ou com o delimitador esquerdo com uma sequência de caracteres com apóstrofo e os argumentos
seguindo entre parêntesis.
@code{dispfun (@var{delimitador_e})} mostra a definição da função operador.

O único operador interno @code{matchfix} é o construtor de listas @code{[ ]}.
Parêntesis @code{( )} e aspas duplas @code{" "} 
atuam como operadores @code{matchfix},
mas não são tratados como tal pelo analisador do Maxima.

@code{matchfix} avalia seus argumentos.
@code{matchfix} retorna seu primeiro argumento, @var{delimitador_e}.
@c HOW TO TAKE AWAY THE MATCHFIX PROPERTY ??

Exemplos:

@itemize @bullet
@item
Delimitadores podem ser quase quaisquer sequência de caracteres.
@end itemize
@c ===beg===
@c matchfix ("@@", "~");
@c @@ a, b, c ~;
@c matchfix (">>", "<<");
@c >> a, b, c <<;
@c matchfix ("foo", "oof");
@c foo a, b, c oof;
@c >> w + foo x, y oof + z << / @@ p, q ~;
@c ===end===
@example
(%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~
@end example

@itemize @bullet
@item
Operadores @code{matchfix} são funções comuns definidas pelo utilizador.
@end itemize
@example
(%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
@end example

@end deffn

@c NEEDS CLARIFICATION AND EXAMPLES
@deffn {Função} remlet (@var{prod}, @var{nome})
@deffnx {Função} remlet ()
@deffnx {Função} remlet (all)
@deffnx {Função} remlet (all, @var{nome})
Apaga a regra de substituiçao, prod --> repl, mais
recentemente definida através dea função @code{let}.  Se @code{nome} for fornecido a regra é
apagada do pacote de regras chamado @code{nome}.

@code{remlet()} e @code{remlet(all)} apagam todas as regras de substituição do pacote de regras corrente.
Se o nome de um pacote de regras for fornecido,
e.g. @code{remlet (all, @var{nome})}, o pacote de regras @var{nome} é também apagado.

Se uma substituição é para ser mudada usando o mesmo
produto, @code{remlet} não precisa ser chamada, apenas redefina a substituição
usando o mesmo produto (literalmente) com a função @code{let} e a nova
substituição e/ou nome de predicado.  Pode agora @code{remlet (@var{prod})} ser
chamada e a regra de substituição original é ressuscitada.

Veja também @code{remrule}, que remove uma regra definida através de @code{tellsimp} ou de @code{tellsimpafter}.

@end deffn

@deffn {Função} remrule (@var{op}, @var{nomeregra})
@deffnx {Função} remrule (@var{op}, all)
Remove regras definidas por @code{tellsimp}, ou @code{tellsimpafter}.

@code{remrule (@var{op}, @var{nomeregra})}
remove a regra com o nome @code{nomeregra} do operador @var{op}.
Quando @var{op} for um operador interno ou um operador definido pelo utilizador
(como definido por @code{infix}, @code{prefix}, etc.),
@var{op} e @var{rulename} devem ser colocados entre aspas duplas.

@code{remrule (@var{op}, all)} remove todas as regras para o operador @var{op}.

Veja também @code{remlet}, que remove uma regra definida através de @code{let}.

Examples:

@c ===beg===
@c tellsimp (foo (aa, bb), bb - aa);
@c tellsimpafter (aa + bb, special_add (aa, bb));
@c infix ("@@");
@c tellsimp (aa @@ bb, bb/aa);
@c tellsimpafter (quux (%pi, %e), %pi - %e);
@c tellsimpafter (quux (%e, %pi), %pi + %e);
@c [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e), 
@c        quux (%e, %pi)];
@c remrule (foo, foorule1);
@c remrule ("+", "+rule1");
@c remrule ("@@", "@@rule1");
@c remrule (quux, all);
@c [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e), 
@c         quux (%e, %pi)];
@c ===end===
@example
(%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)]
@end example

@end deffn

@c NEEDS EXPANSION OR MAYBE JUST APPROPRIATE REFS TO tellsimpafter
@deffn {Função} tellsimp (@var{pattern}, @var{replacement})
é similar a @code{tellsimpafter} mas coloca
nova informação antes da antiga de forma que essa nova regra seja aplicada antes das regras
de simplificação internas.

@code{tellsimp} é usada quando for importante modificar a expressão
antes que o simplificador trabalhe sobre ela, por exemplo se o
simplificador "sabe" alguma coisa sobre a expressão, mas o que ele
retorna não é para sua apreciação.  Se o
simplificador "sabe" alguma coisa sobre o principal operador da
expressão, mas está simplesmente a escondê-lo, provavelmente
querrá usar @code{tellsimpafter}.

O modelo pode não ser uma
adição, um produto, variável simples, ou número.

@code{rules} é a lista de regras definidas por
@code{defrule}, @code{defmatch}, @code{tellsimp}, e @code{tellsimpafter}.

Exemplos:

@example
(%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)
@end example

@end deffn

@deffn {Função} tellsimpafter (@var{modelo}, @var{substituição})
Define a uma regra de simplificação que o simplificador do Maxima
aplica após as regras de simplificação internas.
@var{modelo} é uma expressão, compreendendo variáveis de modelo (declaradas através de @code{matchdeclare})
e outros átomos e operações, considerados literais para o propósito de coincidência de modelos.
@var{substituição} é substituída para uma expressão actual que coincide com @var{modelo};
variáveis de modelo em @var{substituição} são atribuidas a valores coincidentes na expressão actual.

@var{modelo} pode ser qualquer expressão não at@^omica
na qual o principal operador não é uma variável de modelo;
a regra de simplificação está associada com o operador principal.
Os nomes de funções (com uma excessão, descrita abaixo), listas, e arrays
podem aparecer em @var{modelo} como o principal operador somente como literais (não variáveis de modelo);
essas regras fornecem expressões tais como @code{aa(x)} e @code{bb[y]} como modelos,
se @code{aa} e @code{bb} forem variáveis de modelo.
Nomes de funções, listas, e arrays que são variáveis de modelo podem aparecer como operadores
outros que não o operador principal em @var{modelo}.

Existe uma excessão para o que foi dito acima com relação a regras e nomes de funções.
O nome de uma função subscrita em uma expressão tal como @code{aa[x](y)}
pode ser uma variável de modelo,
porque o operador principal não é @code{aa} mas ao contrário o átomo Lisp @code{mqapply}.
Isso é uma consequência da representação de expressões envolvendo funções subscritas.

@c LET'S NOT GO INTO DETAILS ABOUT MAIN OPERATORS HERE; BUT PRESERVE THIS FOR REFERENCE
@c The main operator of an expression @code{expr} is @code{caar $expr}.
@c For most kinds of expressions,
@c the main operator is the operator returned by @code{op (@var{pattern})};
@c the sole exception is the operator @code{mqapply},
@c which appears in indexed function expressions (e.g., @code{foo[i](x)}).

@c NEED TO REVIEW THIS PARAGRAPH FOR ACCURACY
Regras de simplificação são aplicadas após avaliação 
(se não suprimida através de colocação de apóstrofo ou do sinalizador @code{noeval}).
Regras estabelecidas por @code{tellsimpafter} são aplicadas na ordem em que forem definidas,
e após quaisquer regras internas.
Regras são aplicadas de baixo para cima, isto é,
aplicadas primeiro a subexpressões antes de ser aplicada à expressão completa.
@c NO IT IS MORE COMPLICATED THAN THIS, ALTHOUGH IN SOME CIRCUMSTANCE IT APPEARS TO BE THE CASE:
@c For a given expression, at most one rule per operator is applied.
Isso pode ser necessário para repetidamente simplificar um resultado
(por exemplo, via o operador apóstrofo-apóstrofo @code{'@w{}'} ou o sinalizador @code{infeval})
para garantir que todas as regras são aplicadas.

Variáveis de modelo são tratadas como variáveis locais em regras de simplificação.
Assim que uma regra é definida, o valor de uma variável de modelo
não afecta a regra, e não é afectado pela regra.
Uma atribuição para uma variável de modelo que resulta em uma coincidência de regra com sucesso
não afecta a atribuição corrente (ou necessita disso) da variável de modelo.
Todavia,
como com todos os átomos no Maxima,
as propriedades de variáveis de modelo (como declarado por @code{put} e funções relacionadas) são globais.

A regra construída por @code{tellsimpafter} é nomeada após o operador principal de @code{modelo}.
Regras para operadores internos, 
e operadores definidos pelo utilizador 
definidos por meio de @code{infix}, @code{prefix}, @code{postfix}, @code{matchfix}, e @code{nofix},
possuem nomes que são sequências de caracteres do Maxima.
@c SLIGHTLY TOO MUCH DETAIL
@c (that is, the name begins with ampersand @code{&}).
Regras para outras funções possuem nomes que são identificadores comuns do Maxima.
@c SLIGHTLY TOO MUCH DETAIL
@c (that is, the name begins with dollar sign @code{$}).

O tratamento de substantivos e formas verbais é desprezívelmente confuso. @c THIS IS A BUG.
Se uma regra é definida para uma forma substantiva (ou verbal)
e uma regra para o verbo correspondente (ou substantivo) já existe, 
então a nova regra definida aplica-se a ambas as formas (substantiva e verbal).
Se uma regra para a correspondente forma verbal (ou substantiva) não existe,
a nova regra definida aplicar-se-á somente para a forma substantiva (ou verbal).

A regra construída através de @code{tellsimpafter} é uma função Lisp comum.
Se o nome da regra for @code{$foorule1},
a construção @code{:lisp (trace $foorule1)} rastreia a função,
e @code{:lisp (symbol-function '$foorule1} mostra sua definição.

@code{tellsimpafter} não avalia seus argumentos.
@code{tellsimpafter} retorna a lista de regras para o operador principal de @var{modelo},
incluindo a mais recente regra estabelecia.
@c WHAT IS simpfoo THAT SOMETIMES APPEARS, AND WHY DOES false SOMETIMES APPEAR IN RETURN VALUE ??

Veja também @code{matchdeclare}, @code{defmatch}, @code{defrule}, @code{tellsimp}, @code{let},
@code{kill}, @code{remrule}, e @code{clear_rules}.

Exemplos:

@var{modelo} pode ser qualquer expressão não at@^omica na qual o 
principal operador não é uma variável de modelo.

@c ===beg===
@c matchdeclare (aa, atom, [ll, mm], listp, xx, true)$
@c tellsimpafter (sin (ll), map (sin, ll));
@c sin ([1/6, 1/4, 1/3, 1/2, 1]*%pi);
@c tellsimpafter (ll^mm, map ("^", ll, mm));
@c [a, b, c]^[1, 2, 3];
@c tellsimpafter (foo (aa (xx)), aa (foo (xx)));
@c foo (bar (u - v));
@c ===end===
@example
(%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))
@end example

Regras são aplicadas na ordem em que forem definidas.
Se duas regras podem coincidir com uma expressão,
a regra que foi primeiro definida é a que será aplicada.

@c ===beg===
@c matchdeclare (aa, integerp);
@c tellsimpafter (foo (aa), bar_1 (aa));
@c tellsimpafter (foo (aa), bar_2 (aa));
@c foo (42);
@c ===end===
@example
(%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)
@end example

variáveis de modelo são tratadas como variáveis locais em regras de simplificação.
(Compare a @code{defmatch}, que trata variáveis de modelo como variáveis globais.)

@c ===beg===
@c matchdeclare (aa, integerp, bb, atom);
@c tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
@c bb: 12345;
@c foo (42, %e);
@c bb;
@c ===end===
@example
(%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
@end example

Como com todos os átomos, propriedades de variáveis de modelo são globais embora valores sejam locais.
Nesse exemplo, uma propriedade de atribuição é declarada via @code{define_variable}.
Essa é a propriedade do átomo @code{bb} através de todo o Maxima.

@c ===beg===
@c matchdeclare (aa, integerp, bb, atom);
@c tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
@c foo (42, %e);
@c define_variable (bb, true, boolean);
@c foo (42, %e);
@c ===end===
@example
(%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);
@end example

Regras são nomeadas após operadores principais.
Nomes de regras para operadores internos e operadores definidos pelo utilizador são sequências de caracteres,
enquanto nomes para outras funções são identificadores comuns.

@c ===beg===
@c tellsimpafter (foo (%pi + %e), 3*%pi);
@c tellsimpafter (foo (%pi * %e), 17*%e);
@c tellsimpafter (foo (%i ^ %e), -42*%i);
@c tellsimpafter (foo (9) + foo (13), quux (22));
@c tellsimpafter (foo (9) * foo (13), blurf (22));
@c tellsimpafter (foo (9) ^ foo (13), mumble (22));
@c rules;
@c foorule_name: first (%o1);
@c plusrule_name: first (%o4);
@c [?mstringp (foorule_name), symbolp (foorule_name)];
@c [?mstringp (plusrule_name), symbolp (plusrule_name)];
@c remrule (foo, foorule1);
@c remrule ("^", "^rule1");
@c ===end===
@example
(%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) [trigrule0, trigrule1, trigrule2, trigrule3, trigrule4, 
htrigrule1, htrigrule2, htrigrule3, htrigrule4, foorule1, 
foorule2, foorule3, +rule1, *rule1, ^rule1]
(%i8) foorule_name: first (%o1);
(%o8)                       foorule1
(%i9) plusrule_name: first (%o4);
(%o9)                        +rule1
(%i10) [?mstringp (foorule_name), symbolp (foorule_name)];
(%o10)                    [false, true]
(%i11) [?mstringp (plusrule_name), symbolp (plusrule_name)];
(%o11)                    [true, true]
(%i12) remrule (foo, foorule1);
(%o12)                         foo
(%i13) remrule ("^", "^rule1");
(%o13)                          ^
@end example

Um exemplo trabalhado: multiplicação anticomutativa.

@c ===beg===
@c gt (i, j) := integerp(j) and i < j;
@c matchdeclare (i, integerp, j, gt(i));
@c tellsimpafter (s[i]^^2, 1);
@c tellsimpafter (s[i] . s[j], -s[j] . s[i]);
@c s[1] . (s[1] + s[2]);
@c expand (%);
@c factor (expand (sum (s[i], i, 0, 9)^^5));
@c ===end===
@example
(%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
@end example

@end deffn

@deffn {Função} clear_rules ()
Executa @code{kill (rules)} e então re-escolhe o próximo número de regra para 1
para adição @code{+}, multiplicação @code{*}, e exponenciação @code{^}.

@end deffn


