Introducción a simplification
=============================

El directorio maxima/share/simplification contiene programas que implementan algunas reglas y funciones para simplificar expresiones, así como ciertas funciones no relacionadas con la simplificación.

Funciones y variables para simplification
=========================================

Paquete absimp
--------------

El paquete absimp contiene reglas para aplicar patrones que extienden el sistema de reglas nativo de Maxima para las funciones abs y signum, respetando las relaciones establecidas con la función assume o con declaraciones tales como modedeclare (m, even, n, odd) para enteros pares o impares.

En el paquete absimp se definen las funciones unitramp y unitstep en términos de abs y signum.

La instrucción load (absimp) carga este paquete y demo (absimp) desarrolla una demostración sobre el uso del mismo.

Ejemplos:

     (%i1) load (absimp)$
     (%i2) (abs (x))^2;
                                            2
     (%o2)                                 x
     (%i3) diff (abs (x), x);
                                           x
     (%o3)                               ------
                                         abs(x)
     (%i4) cosh (abs (x));
     (%o4)                               cosh(x)

Paquete facexp
--------------

El paquete facexp contiene varias funciones que le aportan al usuario la posibilidad de estructurar expresiones controlando su expansión. Esta capacidad es especialmente útil cuando la expresión contiene variables con significado físico, ya que se suele dar el caso de que la forma más sencilla para estas expresiones se obtiene cuando se expanden respecto de estas variables y luego se factoriza respecto de sus coeficientes. Si bien es cierto que este procedimiento no es difícil de llevar a cabo con las funciones estándar de Maxima, pueden ser necesarios algunos retoques adicionales que sí pueden ser más difíciles de hacer.

La función facsum y sus formas relacionadas proporcionan un método para controlar la estructura de expresiones. La función collectterms puede usarse para añadir dos o más expresiones que ya hayan sido simplificadas de la forma indicada, sin necesidad de volver a simplificar la expresión completa. Esta función puede ser útil cuando las expresiones sean largas.

La instrucción load (facexp) carga este paquete y demo (facexp) hace una demostración sobre su uso.

 -- Función: facsum (EXPR, ARG_1, ..., ARG_N)

     Devuelve una expresión equivalente a EXPR, la cual depende de los argumentos ARG_1, ..., ARG_N, y éstos pueden ser de cualquiera de las formas aceptables para ratvars, o listas de estas formas. Si los argumentos no son listas, la forma devuelta se expande completamente con respecto de los argumentos, siendo los coeficientes de tales argumentos factorizados. Estos coeficientes no contienen a ninguno de los argumentos, excepto quizás de una forma no racional.

     En caso de que cualquiera de los argumentos sea una lista, entonces todos ellos se combinan en una única lista, y en lugar de llamar a factor para los coeficientes de los argumentos, facsum se llama a sí misma utilizando esta nueva lista única como lista de argumentos.

     Es posible que se quiera utilizar facsum con respecto a expresiones más complicadas, tales como log (x + y). Estos argumentos son también admisibles. Si no se especifican variables, como en facsum (EXPR), el resultado devuelto es el mismo que el conseguido mediante ratsimp (EXPR).

     En ocasiones puede ser necesario obtener cualquiera de las formas anteriores especificadas por sus operadores principales. Por ejemplo, se puede querer aplicar facsum con respecto a todos los log; en este caso, se puede incluir entre los argumentos bien los log específicos que se quieran tratar de esta manera, bien la expresión operator (log) o 'operator (log). Si se quiere aplicar facsum a EXPR con respecto a los operadores OP_1, ..., OP_N, se debe evaluar facsum (EXPR, operator (OP_1, ..., OP_N)). La forma operator puede aparecer también dentro de las listas de argumentos.

     Además, dándole valores a las variables opcionales facsum_combine y nextlayerfactor se puede controlar el resultado de facsum.

 -- Variable global: nextlayerfactor
     Valor por defecto: false

     Si nextlayerfactor vale true, las llamadas recursivas de facsum se aplican a los factores de la forma factorizada de los coeficientes de los argumentos.

     Si vale false, facsum se aplica a cada coeficiente como un todo cada vez que se efectúen llamadas recursivas a facsum.

     La inclusión del átomo nextlayerfactor en la lista de argumentos de facsum tiene el mismo efecto que nextlayerfactor: true, pero solamente para el siguiente nivel de la expresión. Puesto que nextlayerfactor toma siempre uno de los valores true o  false, debe aparecer comentado (comilla simple) cada vez que aparezca en la lista de argumentos de facsum.

 -- Variable global: facsum_combine
     Valor por defecto: true

     La variable facsum_combine controla la forma del resultado final devuelto por facsum si su argumento es un cociente de polinomios. Si facsum_combine vale false, el resultado será una suma completamente expandida, pero si vale true, la expresión devuelta es un cociente de polinomios.

 -- Función: factorfacsum (EXPR, ARG_1, ... ARG_N)
     Devuelve una expresión equivalente a EXPR obtenida aplicando facsum a los factores de EXPR, de argumentos ARG_1, ... ARG_N. Si alguno de los factores de EXPR se eleva a una potencia, tanto el factor como el exponente se procesarán de esta manera.

 -- Función: collectterms (ARG_1, ..., ARG_N)
     Si algunas expresiones fueron ya simplificadas con facsum, factorfacsum, factenexpand,  facexpten o factorfacexpten, debiendo ser luego sumadas, puede ser conveniente combinarlas utilizando la función collecterms, la cual admite como argumentos todos aquéllos que se puedan pasar a las anteriormente citadas funciones, con la excepción de nextlayerfactor, que no tiene efecto alguno sobre collectterms. La ventaja de collectterms es que devuelve una forma similar a la de facsum, pero debido a que suma expresiones que ya han sido previamente procesadas, no necesita repetir esta operación, lo cual resulta ser especialmente útil cuando las expresiones a sumar son muy grandes.

Paquete functs
--------------

 -- Función: rempart (EXPR, N)
     Elimina la parte N de la expresión EXPR.

     Si N es una lista de la forma [L, M], entonces las partes desde L a M serán eliminadas.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: wronskian ([F_1, ..., F_N], X)
     Devuelve la matriz wronskiana de las funciones F_1, ..., F_N dependeientes de la variable X.

     Los argumentos F_1, ..., F_N pueden ser nombres de funciones definidas por el usuario, o expresiones de variable X.

     El determinante de la matriz wronskiana es el determinante wronskiano del conjunto de funciones. Las funciones serán linealmente dependientes si este determinante es nulo.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: tracematrix (M)
     Devuelve la traza (suma de los elementos de la diagonal) de la matriz M.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: rational (Z)
     Multiplica el numerador y denominador de Z por el complejo conjugado del denominador, racionalizando así el denominador. Devuelve la expresión canónica racional (canonical rational expression, CRE) si el argumento Z es de esta forma, en caso contrario devuelve una expresión en formato común.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: logand (X,Y)
     Devuelve el "y" lógico binario de los argumentos X e Y.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: logor (X,Y)
     Devuelve el "o" lógico binario de los argumentos X e Y.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: logxor (X,Y)
     Devuelve el "o-excusivo" lógico binario de los argumentos X e Y.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: nonzeroandfreeof (X, EXPR)
     Devuelve true si EXPR es diferente de cero y freeof (X, EXPR) devuelve true. En caso contrario devuelve false.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: linear (EXPR, X)
     Si EXPR es una expresión lineal respecto de la variable X, linear devuelve A*X + B, siendo A no nula y, junto con B, no incluye a X. En otro caso, linear devuelve EXPR.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: gcdivide (P, Q)
     Si takegcd vale true, gcdivide divide los polinomios P y Q por su máximo común divisor y devuelve el cociente de los resultados.

     Si takegcd vale false, gcdivide devuelve el cociente P/Q.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: arithmetic (A, D, N)
     Devuelve el N-ésimo término de la progresión aritmética A, A + D, A + 2*D, ..., A + (N - 1)*D.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: geometric (A, R, N)
     Devuelve el N-ésimo término de la progresión geométrica A, A*R, A*R^2, ..., A*R^(N - 1).

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: harmonic (A, B, C, N)
     Devuelve el N-ésimo término de la progresión armónica A/B, A/(B + C), A/(B + 2*C), ..., A/(B + (N - 1)*C).

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: arithsum (A, D, N)
     Devuelve la suma de la progresión aritmética desde hasta el N-ésimo término.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: geosum (A, R, N)
     Devuelve la suma de la sucesión geométrica hasta el N-ésimo término. Si N es infinito (inf) la suma será finita sólo si el valor absoluto de R es menor que 1.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: gaussprob (X)
     Devuelve la función de densidad de probabilidad, normal %e^(-X^2/2) / sqrt(2*%pi).

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: gd (X)
     Devuelve la función de Gudermann, 2 * atan(%e^X - %pi/2).

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: agd (X)
     Devuelve la inversa de la función de Gudermann, log (tan (%pi/4 + x/2))).

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: vers (X)
     Devuelve 1 - cos (x).

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: covers (X)
     Devuelve 1 - sin (X).

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: exsec (X)
     Devuelve sec (X) - 1.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: hav (X)
     Devuelve (1 - cos(x))/2.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: combination (N, R)
     Calcula el número de combinaciones de N objetos tomados de R en R.

     Para hacer uso de esta función ejecutar load(functs).

 -- Función: permutation (N, R)
     Calcula el número de permutaciones de R, seleccionados de un conjunto de N.

     Para hacer uso de esta función ejecutar load(functs).

Paquete ineq
------------

El paquete ineq contiene reglas de simplificación para desigualdades

Una sesión de ejemplo:

     (%i1) load(ineq)$
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     Warning: Putting rules on '+' or '*' is inefficient, and may not work.
     (%i2) a>=4;  /* a sample inequality */
     (%o2)                               a >= 4
     (%i3) (b>c)+%; /* add a second, strict inequality */
     (%o3)                            b + a > c + 4
     (%i4) 7*(x<y); /* multiply by a positive number */
     (%o4)                              7 x < 7 y
     (%i5) -2*(x>=3*z); /* multiply by a negative number */
     (%o5)                           - 2 x <= - 6 z
     (%i6) (1+a^2)*(1/(1+a^2)<=1); /* Maxima knows that 1+a^2 > 0 */
                                             2
     (%o6)                             1 <= a  + 1
     (%i7) assume(x>0)$ x*(2<3); /* assuming x>0 */
     (%o7)                              2 x < 3 x
     (%i8) a>=b; /* another inequality */
     (%o8)                               a >= b
     (%i9) 3+%; /* add something */
     (%o9)                           a + 3 >= b + 3
     (%i10) %-3; /* subtract it out */
     (%o10)                              a >= b
     (%i11) a>=c-b; /* yet another inequality */
     (%o11)                            a >= c - b
     (%i12) b+%; /* add b to both sides */
     (%o12)                            b + a >= c
     (%i13) %-c; /* subtract c from both sides */
     (%o13)                         - c + b + a >= 0
     (%i14) -%;  /* multiply by -1 */
     (%o14)                          c - b - a <= 0
     (%i15) (z-1)^2>-2*z; /* determining truth of assertion */
                                           2
     (%o15)                         (z - 1)  > - 2 z
     (%i16) expand(%)+2*z; /* expand this and add 2*z to both sides */
                                        2
     (%o16)                            z  + 1 > 0
     (%i17) %,pred;
     (%o17)                               true

Debe tenerse cuidado con el uso de paréntesis que incluyan desigualdades; si se escribe (A > B) + (C = 5) el resultado es A + C > B + 5, pero A > B + C = 5 es un error sintáctico y (A > B + C) = 5 es una cosa completamente diferente.

Ejecútese disprule (all) para ver la lista completa de las reglas definidas.

Maxima preguntará al usuario cuando desconozca el signo de una cantidad que multiplica a una desigualdad.

Los fallos más comunes son:

     eq: a > b;
     2*eq;
     % - eq;

Otro problema es el producto de una desigualdad por cero. Si se escribe x*SOME_INEQUALITY y Maxima pregunta por el signo de x y se responde que vale zero (o z), el programa devuelve x*SOME_INEQUALITY sin hacer uso de la información de que x es 0. En tal caso se debería escribir ev (%, x: 0), ya que la base de datos sólo será utilizada para fines comparativos y no para evaluar x.

El usuario puede apreciar que las respuestas son más lentas al cargarse este paquete, ya que el simplificador deberá examinar más reglas que cuando no se hace uso del paquete, por lo que puede ser conveniente borrar estas reglas cuando ya no se haga uso de ellas. Ejecútese kill (rules) para eliminar todas las reglas (incluidas las definidas por el usuario); también es posible eliminar parte de ellas o utilizar remrule sobre una reglas específica.

Nótese que si se carga este paquete después de haber definido otras reglas de igual nombre,se borrarán las antiguas. Las reglas de este paquete son: *rule1, ..., *rule8, +rule1, ..., +rule18, debiéndose encerrar entre comillas el nombre de la reglas para referenciarse a ellas, como en remrule ("+", "+rule1") para eliminar la primera regla sobre "+", o disprule ("*rule2") para mostrar la definición de la segunda regla multiplicativa.

Paquete rducon
--------------

 -- Función: reduce_consts (EXPR)
     Sustituye subexpresiones constantes de EXPR por átomos, guardando la definición de todos ellos en la lista de ecuaciones const_eqns y devolviendo el expresión EXPR ya modificada. Se consideran partes constantes de EXPR aquellas que devuelven true cuando se les aplica la función constantp, por lo que antes de llamar a reduce_consts se debe ejecutar

          declare ([OBJETOS A LOS QUE SE QUIERA DAR LA PROPIEDAD DE SER CONSTANTES], constant)$

     para crear la base de datos de las cantidades constantes presentes en la expresión.

     Si se pretende generar código Fortran después de estos cálculos simbólicos, una de las primeras secciones del código debe ser el cálculo de las constantes. Para generar este segmento de código hacer

          map ('fortran, const_eqns)$

     Junto a const_eqns, otras variables que afectan a reduce_consts son:

     const_prefix (Valor por defecto: xx) es la cadena de caracteres utilizada como prefijo para todos los símbolos generados por reduce_consts para representar subexpresiones constantes.

     const_counter (Valor por defecto: 1) es el índice entero utilizado para generar los símbolos que representen a las subexpresiones constantes encontradas por reduce_consts.

     La instrucción load (rducon) carga esta función y demo (rducon) hace una demostración sobre su uso.

Paquete scifac
--------------

 -- Función: gcfac (EXPR)
     Es una función de factorización que intenta aplicar la misma heurística que los humanos cuando tratan de hacer las expresiones más simples, limitándose a la factorización de monomios. En caso de sumas, gcfac hace lo siguiente:

      1. Factoriza los enteros.

      2. Factoriza las potencias mayores de los términos que aparecen como coeficientes, independientemente de su complejidad.

      3. Utiliza (1) y (2) en la factorización de pares de términos adyacentes.

      4. Aplica estas técnicas repetida y recursivamente hasta que la expresión deje de sufrir cambios.

     En general, el apartado (3) no hace una factorización óptima debido a la naturaleza combinatoria y compleja de encontrar cuál de todas las ordenaciones posibles de los pares da lugar a la expresión más compacta.

     La instrucción load (scifac) carga esta función y demo (scifac) hace una demostración sobre su uso.

Paquete sqdnst
--------------

 -- Función: sqrtdenest (EXPR)
     Reduce expresiones en las que se encuentren raíces cuadradas anidadas, siempre que sea posible

     Ejemplo:

          (%i1) load (sqdnst)$
          (%i2) sqrt(sqrt(3)/2+1)/sqrt(11*sqrt(2)-12);
                                              sqrt(3)
                                         sqrt(------- + 1)
                                                 2
          (%o2)                        ---------------------
                                       sqrt(11 sqrt(2) - 12)
          (%i3) sqrtdenest(%);
                                            sqrt(3)   1
                                            ------- + -
                                               2      2
          (%o3)                            -------------
                                              1/4    3/4
                                           3 2    - 2

     A veces conviene aplicar sqrtdenest más de una vez, como en el caso (19601-13860 sqrt(2))^(7/4).

     La sentencia load (sqdnst) carga esta función.