This is maxima.info, produced by makeinfo version 5.1 from maxima.texi.


File: maxima.info,  Node: Funciones y variables para itensor,  Prev: Introducción a itensor,  Up: itensor

25.2 Funciones y variables para itensor
=======================================

25.2.1 Trabajando con objetos indexados
---------------------------------------

 -- Función: dispcon (<tensor_1>, <tensor_2>, ...)
 -- Función: dispcon (all)

     Muestra las propiedades contractivas de sus argumentos tal como
     fueron asignadas por 'defcon'.  La llamada 'dispcon (all)' muestra
     todas propiedades contractivas que fueron definidas.

 -- Función: entertensor (<nombre>)

     Permite crear un objeto indexado llamado <nombre>, con cualquier
     número de índices tensoriales y de derivadas.  Se admiten desde un
     único índice hasta una lista de índices.  Véase el ejemplo en la
     descripción de 'covdiff'.

 -- Función: changename (<anterior>, <nuevo>, <expr>)

     Cambia el nombre de todos los objetos indexados llamados <anterior>
     a <new> en <expr>.  El argumento <anterior> puede ser un símbolo o
     una lista de la forma '[<nombre>, <m>, <n>]', en cuyo caso sólo los
     objetos indexados de llamados <nombre> con <m> índices covariantes
     y <n> contravariantes se renombrarán como <nuevo>.

 -- Función: listoftens

     Hace un listado de todos los tensores y sus índices en una
     expresión tensorial.  Por ejemplo,


          (%i6) ishow(a([i,j],[k])*b([u],[],v)+c([x,y],[])*d([],[])*e)$
                                                   k
          (%t6)                        d e c    + a    b
                                            x y    i j  u,v
          (%i7) ishow(listoftens(%))$
                                         k
          (%t7)                        [a   , b   , c   , d]
                                         i j   u,v   x y

 -- Función: ishow (<expr>)

     Muestra <expr> con todos los objetos indexados que contiene, junto
     con los correspondientes índices covariantes (como subíndices) y
     contravariantes (como superíndices).  Los índices de derivadas se
     muestran como subíndices, separados de los covariantes por una
     coma; véanse los múltiples ejemplos de este documento.

 -- Función: indices (<expr>)

     Devuelve una lista con dos elementos.  El primer elemento es una
     lista con los índices libres, aquellos que aparecen una sola vez.
     El segundo elemento es una lista con los índices mudos en <expr>,
     aquellos que aparecen exactamente dos veces.  Por ejemplo,


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i,j],[k,l],m,n)*b([k,o],[j,m,p],q,r))$
                                          k l      j m p
          (%t2)                          a        b
                                          i j,m n  k o,q r
          (%i3) indices(%);
          (%o3)                 [[l, p, i, n, o, q, r], [k, j, m]]

     Un producto tensorial que contenga el mismo índice más de dos veces
     es sintácticamente incorrecto.  La función 'indices' intenta tratar
     estas expresiones de una forma razonable; sin embargo, cuando se la
     obliga a manipular una expresión incorrecta puede tener un
     comportamiento imprevisto.

 -- Función: rename (<expr>)
 -- Función: rename (<expr>, <count>)

     Devuelve una expresión equivalente a <expr> pero con los índices
     mudos de cada término elegidos del conjunto '[%1, %2,...]' si el
     segundo argumento opcional se omite.  En otro caso, los índices
     mudos son indexados empezando con el valor <count>.  Cada índice
     mudo en un producto será diferente.  En el caso de las sumas, la
     función 'rename' operará sobre cada término de la suma
     reinicializando el contador con cada término.  De esta manera
     'rename' puede servir como simplificador tensorial.  Además, los
     índices se ordenarán alfanuméricamente, si la variable 'allsym'
     vale 'true', respecto de los índices covariantes y contravariantes
     dependiendo del valor de 'flipflag'.  Si 'flipflag' vale 'false',
     entonces los índices se renombrarán de acuerdo con el orden de los
     índices contravariantes.  Si 'flipflag' vale 'true', entonces los
     índices se renombrarán de acuerdo con el orden de los índices
     covariantes.  Suele acontecer que el efecto combinado de los dos
     cambios de nombre reduzcan la expresión más de lo que que pueda
     reducir cualquiera de ellas por separado.


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) allsym:true;
          (%o2)                                true
          (%i3) g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%4],[%3])*
          ichr2([%2,%3],[u])*ichr2([%5,%6],[%1])*ichr2([%7,r],[%2])-
          g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%2],[u])*
          ichr2([%3,%5],[%1])*ichr2([%4,%6],[%3])*ichr2([%7,r],[%2]),noeval$
          (%i4) expr:ishow(%)$

                 %4 %5  %6 %7      %3         u          %1         %2
          (%t4) g      g      ichr2      ichr2      ichr2      ichr2
                                   %1 %4      %2 %3      %5 %6      %7 r

                  %4 %5  %6 %7      u          %1         %3         %2
               - g      g      ichr2      ichr2      ichr2      ichr2
                                    %1 %2      %3 %5      %4 %6      %7 r
          (%i5) flipflag:true;
          (%o5)                                true
          (%i6) ishow(rename(expr))$
                 %2 %5  %6 %7      %4         u          %1         %3
          (%t6) g      g      ichr2      ichr2      ichr2      ichr2
                                   %1 %2      %3 %4      %5 %6      %7 r

                  %4 %5  %6 %7      u          %1         %3         %2
               - g      g      ichr2      ichr2      ichr2      ichr2
                                    %1 %2      %3 %4      %5 %6      %7 r
          (%i7) flipflag:false;
          (%o7)                                false
          (%i8) rename(%th(2));
          (%o8)                                  0
          (%i9) ishow(rename(expr))$
                 %1 %2  %3 %4      %5         %6         %7        u
          (%t9) g      g      ichr2      ichr2      ichr2     ichr2
                                   %1 %6      %2 %3      %4 r      %5 %7

                  %1 %2  %3 %4      %6         %5         %7        u
               - g      g      ichr2      ichr2      ichr2     ichr2
                                    %1 %3      %2 %6      %4 r      %5 %7

 -- Función: show (<expr>)
     Muestra 'expr' con sus objetos indexados que tengan índices
     covariantes como subíndices y los contravariantes como
     superíndices.  Los índices derivados se muestran como subíndices,
     separados por una coma de los covariantes.

 -- Variable opcional: flipflag
     Valor por defecto: 'false'

     Si vale 'false' los índices se renombrarán de acuerdo con el orden
     de los índices covariantes, si 'true' se renombrarán de acuerdo con
     el orden de los índices covariantes.

     Si 'flipflag' vale 'false', entonces 'rename' construye una lista
     con los índices contravariantes según van apareciendo de izquierda
     a derecha; si vale 'true', entonces va formando la lista con los
     covariantes.  Al primer índice mudo se le da el nombre '%1', al
     siguiente '%2', etc.  Finalmente se hace la ordenación.  Véase el
     ejemplo en la descripción de la función 'rename'.

 -- Función: defcon (<tensor_1>)
 -- Función: defcon (<tensor_1>, <tensor_2>, <tensor_3>)

     Le asigna a gives <tensor_1> la propiedad de que la contracción de
     un producto de <tensor_1> por <tensor_2> da como resultado un
     <tensor_3> con los índices apropiados.  Si sólo se aporta un
     argumento, <tensor_1>, entonces la contracción del producto de
     <tensor_1> por cualquier otro objeto indexado que tenga los índices
     apropiados, por ejemplo 'my_tensor', dará como resultado un objeto
     indexado con ese nombre, 'my_tensor', y con un nuevo conjunto de
     índices que reflejen las contracciones realizadas.  Por ejemplo, si
     'imetric:g', entonces 'defcon(g)' implementará el aumento o
     disminución de los índices a través de la contracción con el tensor
     métrico.  Se puede dar más de un 'defcon' para el mismo objeto
     indexado, aplicándose el último.  La variable 'contractions' es una
     lista con aquellos objetos indexados a los que se le han dado
     propiedades de contracción con 'defcon'.

 -- Función: remcon (<tensor_1>, ..., <tensor_n>)
 -- Función: remcon (all)

     Borra todas las propiedades de contracción de <tensor_1>, ...,
     <tensor_n>).  La llamada 'remcon(all)' borra todas las propiedades
     de contracción de todos los objetos indexados.

 -- Función: contract (<expr>)

     Lleva a cabo las contracciones tensoriales en <expr>, la cual puede
     ser cualquier combinación de sumas y productos.  Esta función
     utiliza la información dada a la función 'defcon'.  Para obtener
     mejores resultados, 'expr' debería estar completamente expandida.
     La función 'ratexpand' es la forma más rápida de expandir productos
     y potencias de sumas si no hay variables en los denominadores de
     los términos.

 -- Función: indexed_tensor (<tensor>)

     Debe ejecutarse antes de asignarle componentes a un <tensor> para
     el que ya existe un valor, como 'ichr1', 'ichr2' o 'icurvature'.
     Véase el ejemplo de la descripción de 'icurvature'.

 -- Función: components (<tensor>, <expr>)

     Permite asignar un valor indexado a la expresión <expr> dando los
     valores de las componentes de <tensor>.  El tensor debe ser de la
     forma 't([...],[...])', donde cualquiera de las listas puede estar
     vacía.  La expresión <expr> puede ser cualquier objeto indexado que
     tenga otros objetos con los mismos índices libres que <tensor>.
     Cuando se utiliza para asignar valores al tensor métrico en el que
     las componentes contengan índices mudos, se debe tener cuidado en
     no generar índices mudos múltiples.  Se pueden borrar estas
     asignaciones con la función 'remcomps'.

     Es importante tener en cuenta que 'components' controla la valencia
     del tensor, no el orden de los índices.  Así, asignando componentes
     de la forma 'x([i,-j],[])', 'x([-j,i],[])' o 'x([i],[j])' todos
     ellos producen el mismo resultado, la asignación de componentes a
     un tensor de nombre 'x' con valencia '(1,1)'.

     Las componentes se pueden asignar a una expresión indexada de
     cuatro maneras, dos de las cuales implican el uso de la instrucción
     'components':

     1) Como una expresión indexada.  Por ejemplo:


          (%i2) components(g([],[i,j]),e([],[i])*p([],[j]))$
          (%i3) ishow(g([],[i,j]))$
                                                i  j
          (%t3)                                e  p

     2) Como una matriz:

          (%i5) lg:-ident(4)$lg[1,1]:1$lg;
                                      [ 1   0    0    0  ]
                                      [                  ]
                                      [ 0  - 1   0    0  ]
          (%o5)                       [                  ]
                                      [ 0   0   - 1   0  ]
                                      [                  ]
                                      [ 0   0    0   - 1 ]

          (%i6) components(g([i,j],[]),lg);
          (%o6)                                done
          (%i7) ishow(g([i,j],[]))$
          (%t7)                                g
                                                i j
          (%i8) g([1,1],[]);
          (%o8)                                  1
          (%i9) g([4,4],[]);
          (%o9)                                 - 1

     3) Como una función.  Se puede utilizar una función de Maxima para
     especificar las componentes de un tensor en base a sus índices.
     Por ejemplo, el código siguiente asigna 'kdelta' a 'h' si 'h' tiene
     el mismo número de índices covariantes y contravariantes y no tiene
     índices de derivadas, asignándole 'g' en otro caso:


          (%i4) h(l1,l2,[l3]):=if length(l1)=length(l2) and length(l3)=0
            then kdelta(l1,l2) else apply(g,append([l1,l2], l3))$
          (%i5) ishow(h([i],[j]))$
                                                    j
          (%t5)                               kdelta
                                                    i
          (%i6) ishow(h([i,j],[k],l))$
                                               k
          (%t6)                               g
                                               i j,l

     4) Utilizando los patrones de Maxima, en particular las funciones
     'defrule' y 'applyb1':


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) matchdeclare(l1,listp);
          (%o2)                                done
          (%i3) defrule(r1,m(l1,[]),(i1:idummy(),
                g([l1[1],l1[2]],[])*q([i1],[])*e([],[i1])))$

          (%i4) defrule(r2,m([],l1),(i1:idummy(),
                w([],[l1[1],l1[2]])*e([i1],[])*q([],[i1])))$

          (%i5) ishow(m([i,n],[])*m([],[i,m]))$
                                              i m
          (%t5)                              m    m
                                                   i n
          (%i6) ishow(rename(applyb1(%,r1,r2)))$
                                     %1  %2  %3 m
          (%t6)                     e   q   w     q   e   g
                                                   %1  %2  %3 n


 -- Función: remcomps (<tensor>)

     Borra todos los valores de <tensor> que han sido asignados con la
     función 'components'.

 -- Función: showcomps (<tensor>)

     Muestra las componentes de un tensor definidas con la instrucción
     'components'.  Por ejemplo:


          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) load(itensor);
          (%o2)      /share/tensor/itensor.lisp
          (%i3) lg:matrix([sqrt(r/(r-2*m)),0,0,0],[0,r,0,0],
                          [0,0,sin(theta)*r,0],[0,0,0,sqrt((r-2*m)/r)]);
                         [         r                                     ]
                         [ sqrt(-------)  0       0              0       ]
                         [      r - 2 m                                  ]
                         [                                               ]
                         [       0        r       0              0       ]
          (%o3)          [                                               ]
                         [       0        0  r sin(theta)        0       ]
                         [                                               ]
                         [                                      r - 2 m  ]
                         [       0        0       0        sqrt(-------) ]
                         [                                         r     ]
          (%i4) components(g([i,j],[]),lg);
          (%o4)                                done
          (%i5) showcomps(g([i,j],[]));
                            [         r                                     ]
                            [ sqrt(-------)  0       0              0       ]
                            [      r - 2 m                                  ]
                            [                                               ]
                            [       0        r       0              0       ]
          (%t5)      g    = [                                               ]
                      i j   [       0        0  r sin(theta)        0       ]
                            [                                               ]
                            [                                      r - 2 m  ]
                            [       0        0       0        sqrt(-------) ]
                            [                                         r     ]
          (%o5)                                false

     La función 'showcomps' también puede mostrar las componentes de
     tensores de rango mayor de 2.

 -- Función: idummy ()

     Incrementa 'icounter' y devuelve un índice de la forma '%n' siendo
     'n' un entero positivo.  Esto garantiza que índices mudos que sean
     necesarios para formar expresiones no entren en conflico con
     índices que ya están en uso.  Véase el ejemplo de la descripción de
     'indices'.

 -- Variable opcional: idummyx
     Valor por defecto: '%'

     Es el prefijo de los índices mudos.  Véase 'indices'.

 -- Variable opcional: icounter
     Valor por defecto: '1'

     Determina el sufijo numérico a ser utilizado en la generación del
     siguiente índice mudo.  El prefijo se determina con la opción
     'idummy' (por defecto: %).

 -- Función: kdelta (<L1>, <L2>)

     Es la función delta generalizada de Kronecker definida en el
     paquete 'itensor' siendo <L1> la lista de índices covariantes y
     <L2> la lista de índices contravariantes.  La función
     'kdelta([i],[j])' devuelve el valor de la delta ordinaria de
     Kronecker.  La instrucción 'ev(<expr>,kdelta)' provoca la
     evaluación de una expresión que contenga 'kdelta([],[])'.

     En un abuso de la notación, 'itensor' también permite a 'kdelta'
     tener 2 índices covariantes y ninguno contravariante, o 2
     contravariantes y ninguno covariante.  Esto es una funcionalidad
     del paquete, loque no implica que 'kdelta([i,j],[])' sea un objeto
     tensorial de pleno derecho.

 -- Función: kdels (<L1>, <L2>)

     Función delta de Kronecker simetrizada, utilizada en algunos
     cálculos.  Por ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) kdelta([1,2],[2,1]);
          (%o2)                                 - 1
          (%i3) kdels([1,2],[2,1]);
          (%o3)                                  1
          (%i4) ishow(kdelta([a,b],[c,d]))$
                                       c       d         d       c
          (%t4)                  kdelta  kdelta  - kdelta  kdelta
                                       a       b         a       b
          (%i4) ishow(kdels([a,b],[c,d]))$
                                       c       d         d       c
          (%t4)                  kdelta  kdelta  + kdelta  kdelta
                                       a       b         a       b

 -- Función: levi_civita (<L>)

     Es el tensor de permutación de Levi-Civita, el cual devuelve 1 si
     la lista <L> con una permutación par de enteros, -1 si es en una
     permutación impar y 0 si algunos de los índices de <L> están
     repetidos.

 -- Función: lc2kdt (<expr>)

     Simplifica expresiones que contengan el símbolo de Levi-Civita,
     convirtiéndolas en expresiones con la delta de Kronecker siempre
     que sea posible.  La diferencia principal entre esta función y la
     simple evaluación del símbolo de Levi-Civita consiste en que de
     esta última forma se obtienen expresiones de Kronecker con índices
     numéricos, lo que impide simplificaciones ulteriores.  La función
     'lc2kdt' evita este problema, dando resultados con son más fáciles
     de simplificar con 'rename' o 'contract'.


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) expr:ishow('levi_civita([],[i,j])
                           *'levi_civita([k,l],[])*a([j],[k]))$
                                            i j  k
          (%t2)                  levi_civita    a  levi_civita
                                                 j            k l
          (%i3) ishow(ev(expr,levi_civita))$
                                            i j  k       1 2
          (%t3)                       kdelta    a  kdelta
                                            1 2  j       k l
          (%i4) ishow(ev(%,kdelta))$
                       i       j         j       i   k
          (%t4) (kdelta  kdelta  - kdelta  kdelta ) a
                       1       2         1       2   j

                                         1       2         2       1
                                  (kdelta  kdelta  - kdelta  kdelta )
                                         k       l         k       l
          (%i5) ishow(lc2kdt(expr))$
                               k       i       j    k       j       i
          (%t5)               a  kdelta  kdelta  - a  kdelta  kdelta
                               j       k       l    j       k       l
          (%i6) ishow(contract(expand(%)))$
                                           i           i
          (%t6)                           a  - a kdelta
                                           l           l

     La función 'lc2kdt' en ocasiones hace uso del tensor métrico.  Si
     el tensor métrico no fue previamente definido con 'imetric', se
     obtiene un mensaje de error.


          (%i7) expr:ishow('levi_civita([],[i,j])
                           *'levi_civita([],[k,l])*a([j,k],[]))$
                                           i j            k l
          (%t7)                 levi_civita    levi_civita    a
                                                               j k
          (%i8) ishow(lc2kdt(expr))$
          Maxima encountered a Lisp error:

           Error in $IMETRIC [or a callee]:
           $IMETRIC [or a callee] requires less than two arguments.

          Automatically continuing.
          To reenable the Lisp debugger set *debugger-hook* to nil.
          (%i9) imetric(g);
          (%o9)                                done
          (%i10) ishow(lc2kdt(expr))$
                   %3 i       k   %4 j       l     %3 i       l   %4 j
          (%t10) (g     kdelta   g     kdelta   - g     kdelta   g
                              %3             %4               %3
                        k
                  kdelta  ) a
                        %4   j k
          (%i11) ishow(contract(expand(%)))$
                                            l i    l i  j
          (%t11)                           a    - g    a
                                                        j

 -- Función: lc_l

     Regla de simplificación utilizada en expresiones que contienen el
     símbolo de 'levi_civita' sin evaluar.  Junto con 'lc_u', puede
     utilizarse para simplificar muchas expresiones de forma más
     eficiente que la evaluación de 'levi_civita'.  Por ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2)  el1:ishow('levi_civita([i,j,k],[])*a([],[i])*a([],[j]))$
                                       i  j
          (%t2)                       a  a  levi_civita
                                                       i j k
          (%i3) el2:ishow('levi_civita([],[i,j,k])*a([i])*a([j]))$
                                                 i j k
          (%t3)                       levi_civita      a  a
                                                        i  j
          (%i4) canform(contract(expand(applyb1(el1,lc_l,lc_u))));
          (%t4)                                  0
          (%i5) canform(contract(expand(applyb1(el2,lc_l,lc_u))));
          (%t5)                                  0

 -- Función: lc_u

     Regla de simplificación utilizada en expresiones que contienen el
     símbolo de 'levi_civita' sin evaluar.  Junto con 'lc_l', puede
     utilizarse para simplificar muchas expresiones de forma más
     eficiente que la evaluación de 'levi_civita'.  Véase 'lc_l'.

 -- Función: canten (<expr>)

     Simplifica <expr> renombrando (véase 'rename') y permutando índices
     mudos.  La función 'rename' se restringe a sumas de productos de
     tensores en los cuales no hay derivadas, por lo que está limitada y
     sólo debería utilizarse si 'canform' no es capaz de de llevar a
     cabo la simplificación requerida.

     La función 'canten' devuelve un resultado matemáticamente correcto
     sólo si su argumento es una expresión completamente simétrica
     respecto de sus índices.  Por esta razón, 'canten' devuelve un
     error si 'allsym' no vale 'true'.

 -- Función: concan (<expr>)

     Similar a 'canten' pero también realiza la contracción de los
     índices.

25.2.2 Simetrías de tensores
----------------------------

 -- Variable opcional: allsym
     Valor por defecto: 'false'

     Si vale 'true' entonces todos los objetos indexados se consideran
     simétricos respecto de todos sus índices covariantes y
     contravariantes.  Si vale 'false' entonces no se tienen en cuenta
     ningún tipo de simetría para estos índices.  Los índices de
     derivadas se consideran siempre simétricos, a menos que la variable
     'iframe_flag' valga 'true'.

 -- Función: decsym (<tensor>, <m>, <n>, [<cov_1>, <cov_2>, ...],
          [<contr_1>, <contr_2>, ...])

     Declara propiedades de simetría para el <tensor> de <m> índices
     covariantes y <n> contravariantes.  Los <cov_i> y <contr_i> son
     seudofunciones que expresan relaciones de simetría entre los
     índices covariantes y contravariantes, respectivamente.  Éstos son
     de la forma 'symoper(<index_1>, <index_2>,...)' donde 'symoper' es
     uno de 'sym', 'anti' o 'cyc' y los <index_i> son enteros que
     indican la posición del índice en el <tensor>.  Esto declarará a
     <tensor> simétrico, antisimétrico o cíclico respecto de <index_i>.
     La llamada 'symoper(all)' indica que todos los índices cumplen la
     condición de simetría.  Por ejemplo, dado un objeto 'b' con 5
     índices covariantes,
     'decsym(b,5,3,[sym(1,2),anti(3,4)],[cyc(all)])' declara 'b'
     simétrico en el primer y segundo índices covariantes, antisimétrico
     en su tercer y cuarto índices también covariantes y cíclico en
     todos sus índices contravariantes.  Cualquiera de las listas de
     declaración de simetrías puede ser nula.  La función que realiza
     las simplificaciones es 'canform', como se ilustra en el siguiente
     ejemplo,


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) expr:contract(expand(a([i1,j1,k1],[])
                      *kdels([i,j,k],[i1,j1,k1])))$
          (%i3) ishow(expr)$
          (%t3)         a      + a      + a      + a      + a      + a
                         k j i    k i j    j k i    j i k    i k j    i j k
          (%i4) decsym(a,3,0,[sym(all)],[]);
          (%o4)                                done
          (%i5) ishow(canform(expr))$
          (%t5)                              6 a
                                                i j k
          (%i6) remsym(a,3,0);
          (%o6)                                done
          (%i7) decsym(a,3,0,[anti(all)],[]);
          (%o7)                                done
          (%i8) ishow(canform(expr))$
          (%t8)                                  0
          (%i9) remsym(a,3,0);
          (%o9)                                done
          (%i10) decsym(a,3,0,[cyc(all)],[]);
          (%o10)                               done
          (%i11) ishow(canform(expr))$
          (%t11)                        3 a      + 3 a
                                           i k j      i j k
          (%i12) dispsym(a,3,0);
          (%o12)                     [[cyc, [[1, 2, 3]], []]]

 -- Función: remsym (<tensor>, <m>, <n>)

     Borra todas las propiedades de simetría del <tensor> que tiene <m>
     índices covariantes y <n> contravariantes.

 -- Función: canform (<expr>)
 -- Función: canform (<expr>, <rename>)

     Simplifica <expr> renombrando índices mudos y reordenando todos los
     índices según las condiciones de simetría que se le hayan impuesto.
     Si 'allsym' vale 'true' entonces todos los índices se consideran
     simétricos, en otro caso se utilizará la información sobre
     simetrías suministrada por 'decsym'.  Los índices mudos se
     renombran de la misma manera que en la función 'rename'.  Cuando
     'canform' se aplica a una expresión grande el cálculo puede llevar
     mucho tiempo.  Este tiempo se puede acortar llamando primero a
     'rename'.  Véase también el ejemplo de la descripción de 'decsym'.
     La función 'canform' puede que no reduzca completamente una
     expresión a su forma más sencilla, pero en todo caso devolverá un
     resultado matemáticamente correcto.

     Si al parámetro opcional <rename> se le asigna el valor 'false', no
     se renombrarán los índices mudos.

25.2.3 Cálculo tensorial indexado
---------------------------------

 -- Función: diff (<expr>, <v_1>, [<n_1>, [<v_2>, <n_2>] ...])

     Se trata de la función de Maxima para la diferenciación, ampliada
     para las necesidades del paquete 'itensor'.  Calcula la derivada de
     <expr> respecto de <v_1> <n_1> veces, respecto de <v_2> <n_2>
     veces, etc.  Para el paquete de tensores,la función ha sido
     modificada de manera que <v_i> puedan ser enteros desde 1 hasta el
     valor que tome la variable 'dim'.  Esto permite que la derivación
     se pueda realizar con respecto del <v_i>-ésimo miembro de la lista
     'vect_coords'.  Si 'vect_coords' guarda una variable atómica,
     entonces esa variable será la que se utilice en la derivación.  Con
     esto se hace posible la utilización de una lista con nombres de
     coordenadas subindicadas, como 'x[1]', 'x[2]', ...

     El paquete sobre tensores amplía las capacidades de 'diff' con el
     fin de poder calcular derivadas respecto de variables indexadas.
     En particular, es posible derivar expresiones que contengan
     combinaciones del tensor métrico y sus derivadas respecto del
     tensor métrico y su primera y segunda derivadas.  Estos métodos son
     particularmente útiles cuando se consideran los formalismos
     lagrangianos de la teoría gravitatoria, permitiendo obtener el
     tensor de Einstein y las ecuaciones de campo a partir del principio
     de acción.

 -- Función: idiff (<expr>, <v_1>, [<n_1>, [<v_2>, <n_2>] ...])
     Diferenciación inicial.  Al contrario que 'diff', que deriva
     respecto de una variable independiente, 'idiff' puede usarse para
     derivar respecto de una coordenada.

     La función 'idiff' también puede derivar el determinante del tensor
     métrico.  Así, si 'imetric' toma el valor 'G' entonces
     'idiff(determinant(g),k)' devolverá
     '2*determinant(g)*ichr2([%i,k],[%i])' donde la índice mudo '%i' se
     escoge de forma apropiada.

 -- Función: liediff (<v>, <ten>)

     Calcula la derivada de Lie de la expresión tensorial <ten> respecto
     de campo vectorial <v>.  La expresión <ten> debe ser cualquier
     tensor indexado; <v> debe ser el nombre (sin índices) de un campo
     vectorial.  Por ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(liediff(v,a([i,j],[])*b([],[k],l)))$
                 k    %2            %2          %2
          (%t2) b   (v   a       + v   a     + v   a    )
                 ,l       i j,%2    ,j  i %2    ,i  %2 j

                                    %1  k        %1  k      %1  k
                                + (v   b      - b   v    + v   b   ) a
                                        ,%1 l    ,l  ,%1    ,l  ,%1   i j

 -- Función: rediff (<ten>)

     Calcula todas las instrucciones 'idiff' que aparezcan en la
     expresión tensorial <ten>.

 -- Función: undiff (<expr>)

     Devuelve una expresión equivalente a <expr> pero con todas las
     derivadas de los objetos indexados reemplazadas por la forma
     nominal de la función 'idiff'.

 -- Función: evundiff (<expr>)

     Equivale a 'undiff' seguido de 'ev' y 'rediff'.

     La razón de esta operación es evaluar de forma sencilla expresiones
     que no pueden ser directamente evaluadas en su forma derivada.  Por
     ejemplo, lo siguiente provoca un error:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) icurvature([i,j,k],[l],m);
          Maxima encountered a Lisp error:

           Error in $ICURVATURE [or a callee]:
           $ICURVATURE [or a callee] requires less than three arguments.

          Automatically continuing.
          To reenable the Lisp debugger set *debugger-hook* to nil.

     Sin embargo, si 'icurvature' se da en forma nominal, puede ser
     evaluada utilizando 'evundiff':

          (%i3) ishow('icurvature([i,j,k],[l],m))$
                                                   l
          (%t3)                          icurvature
                                                   i j k,m
          (%i4) ishow(evundiff(%))$
                       l              l         %1           l           %1
          (%t4) - ichr2        - ichr2     ichr2      - ichr2       ichr2
                       i k,j m        %1 j      i k,m        %1 j,m      i k

                       l              l         %1           l           %1
                + ichr2        + ichr2     ichr2      + ichr2       ichr2
                       i j,k m        %1 k      i j,m        %1 k,m      i j

     Nota: en versiones antiguas de Maxima, las formas derivadas de los
     símbolos de Christoffel no se podían evaluar.  Este fallo ha sido
     subsanado, de manera que 'evundiff' ya no se necesita en
     expresiones como esta:

          (%i5) imetric(g);
          (%o5)                                done
          (%i6) ishow(ichr2([i,j],[k],l))$
                 k %3
                g     (g         - g         + g        )
                        j %3,i l    i j,%3 l    i %3,j l
          (%t6) -----------------------------------------
                                    2

                                   k %3
                                  g     (g       - g       + g      )
                                   ,l     j %3,i    i j,%3    i %3,j
                                + -----------------------------------
                                                   2

 -- Función: flush (<expr>, <tensor_1>, <tensor_2>, ...)

     Iguala a cero en la expresión <expr> todas las apariciones de
     <tensor_i> que no tengan índices de derivadas.

 -- Función: flushd (<expr>, <tensor_1>, <tensor_2>, ...)

     Iguala a cero en la expresión <expr> todas las apariciones de
     <tensor_i> que tengan índices de derivadas

 -- Función: flushnd (<expr>, <tensor>, <n>)

     Iguala a cero en <expr> todas las apariciones del objeto
     diferenciado <tensor> que tenga <n> o más índices de derivadas,
     como demuestra el siguiente ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i],[J,r],k,r)+a([i],[j,r,s],k,r,s))$
                                          J r      j r s
          (%t2)                          a      + a
                                          i,k r    i,k r s
          (%i3) ishow(flushnd(%,a,3))$
                                               J r
          (%t3)                               a
                                               i,k r

 -- Función: coord (<tensor_1>, <tensor_2>, ...)

     Le da a <tensor_i> la propiedad de diferenciación coordenada, que
     la derivada del vector contravariante cuyo nombre es uno de los
     <tensor_i> es igual a la delta de Kronecker.  Por ejemplo, si se ha
     hecho 'coord(x)' entonces 'idiff(x([],[i]),j)' da
     'kdelta([i],[j])'.  La llamada 'coord' devuelve una lista de todos
     los objetos indexados con esta propiedad.

 -- Función: remcoord (<tensor_1>, <tensor_2>, ...)
 -- Función: remcoord (all)

     Borra todas las propiedades de diferenciación coordenada de
     'tensor_i' que hayan sido establecidas por la función 'coord'.  La
     llamada 'remcoord(all)' borra esta propiedad de todos los objetos
     indexados.

 -- Función: makebox (<expr>)
     Muestra <expr> de la misma manera que lo hace 'show'; sin embargo,
     cualquier tensor de d'Alembert que aparezca en <expr> estará
     indicado por '[]'.  Por ejemplo, '[]p([m],[n])' representa
     'g([],[i,j])*p([m],[n],i,j)'.

 -- Función: conmetderiv (<expr>, <tensor>)

     Simplifica expresiones que contengan derivadas ordinarias tanto de
     las formas covariantes como contravariantes del tensor métrico.
     Por ejemplo, 'conmetderiv' puede relacionar la derivada del tensor
     métrico contravariante con los símbolos de Christoffel, como se ve
     en el ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(g([],[a,b],c))$
                                                a b
          (%t2)                                g
                                                ,c
          (%i3) ishow(conmetderiv(%,g))$
                                   %1 b      a       %1 a      b
          (%t3)                 - g     ichr2     - g     ichr2
                                             %1 c              %1 c

 -- Función: simpmetderiv (<expr>)
 -- Función: simpmetderiv (<expr>[, <stop>])

     Simplifica expresiones que contienen productos de las derivadas del
     tensor métrico.  La función 'simpmetderiv' reconoce dos
     identidades:


             ab        ab           ab                 a
            g   g   + g   g     = (g   g  )   = (kdelta )   = 0
             ,d  bc        bc,d         bc ,d          c ,d

     de donde


             ab          ab
            g   g   = - g   g
             ,d  bc          bc,d

     y


            ab          ab
           g   g     = g   g
            ,j  ab,i    ,i  ab,j

     que se deduce de las simetrías de los símbolos de Christoffel.

     La función 'simpmetderiv' tiene un argumento opcional, el cual
     detiene la función después de la primera sustitución exitosa en un
     expresión producto.  La función 'simpmetderiv' también hace uso de
     la variable global <flipflag> que determina cómo aplicar una
     ordenación "canónica" a los índices de los productos.

     Todo esto se puede utilizar para conseguir buenas simplificaciones
     que serían difíciles o imposibles de conseguir, lo que se demuestra
     en el siguiente ejemplo, que utiliza explícitamente las
     simplificaciones parciales de 'simpmetderiv':


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric(g);
          (%o2)                                done
          (%i3) ishow(g([],[a,b])*g([],[b,c])*g([a,b],[],d)*g([b,c],[],e))$
                                       a b  b c
          (%t3)                       g    g    g      g
                                                 a b,d  b c,e
          (%i4) ishow(canform(%))$

          errexp1 has improper indices
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i5) ishow(simpmetderiv(%))$
                                       a b  b c
          (%t5)                       g    g    g      g
                                                 a b,d  b c,e
          (%i6) flipflag:not flipflag;
          (%o6)                                true
          (%i7) ishow(simpmetderiv(%th(2)))$
                                         a b  b c
          (%t7)                         g    g    g    g
                                         ,d   ,e   a b  b c
          (%i8) flipflag:not flipflag;
          (%o8)                                false
          (%i9) ishow(simpmetderiv(%th(2),stop))$
                                         a b  b c
          (%t9)                       - g    g    g      g
                                              ,e   a b,d  b c
          (%i10) ishow(contract(%))$
                                              b c
          (%t10)                           - g    g
                                              ,e   c b,d

     Véase también 'weyl.dem' para un ejemplo que utiliza 'simpmetderiv'
     y 'conmetderiv' para simplificar contracciones del tensor de Weyl.

 -- Función: flush1deriv (<expr>, <tensor>)

     Iguala a cero en 'expr' todas las apariciones de 'tensor' que
     tengan exactamente un índice derivado.

25.2.4 Tensores en espacios curvos
----------------------------------

 -- Función: imetric (<g>)
 -- Variable de sistema: imetric
     Especifica la métrica haciendo la asignación de la variable
     'imetric:<g>', además las propiedades de contracción de la métrica
     <g> se fijan ejecutando las instrucciones 'defcon(<g>),
     defcon(<g>,<g>,kdelta)'.  La variable 'imetric', a la que no se le
     asigna ningún valor por defecto, tiene el valor de la métrica que
     se le haya asignado con la instrucción 'imetric(<g>)'.

 -- Función: idim (<n>)
     Establece las dimensiones de la métrica.  También inicializa las
     propiedades de antisimetría de los símbolos de Levi-Civita para la
     dimensión dada.

 -- Función: ichr1 ([<i>, <j>, <k>])
     Devuelve el símbolo de Christoffel de primera especie dado por la
     definición
                 (g      + g      - g     )/2 .
                   ik,j     jk,i     ij,k

     Para evaluar los símbolos de Christoffel de una métrica
     determinada, a la variable 'imetric' hay que asignarle un nombre
     como en el ejemplo de la descripción de 'chr2'.

 -- Función: ichr2 ([<i>, <j>], [<k>])
     Devuelve el símbolo de Christoffel de segunda especie dado por la
     definición
                                 ks
             ichr2([i,j],[k]) = g    (g      + g      - g     )/2
                                       is,j     js,i     ij,s

 -- Función: icurvature ([<i>, <j>, <k>], [<h>])
     Devuelve el tensor de curvatura de Riemann en términos de los
     símbolos de Christoffel de segunda especie ('ichr2').  Se utiliza
     la siguiente notación:
                         h             h            h         %1         h
               icurvature     = - ichr2      - ichr2     ichr2    + ichr2
                         i j k         i k,j        %1 j      i k        i j,k
                                         h          %1
                                  + ichr2      ichr2
                                         %1 k       i j

 -- Función: covdiff (<expr>, <v_1>, <v_2>, ...)
     Devuelve la derivada covariante de <expr> respecto de las variables
     <v_i> en términos de los símbolos de Christoffel de segunda especie
     ('ichr2').  Para evaluarlos debe hacerse 'ev(<expr>,ichr2)'.


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) entertensor()$
          Enter tensor name: a;
          Enter a list of the covariant indices: [i,j];
          Enter a list of the contravariant indices: [k];
          Enter a list of the derivative indices: [];
                                                k
          (%t2)                                a
                                                i j
          (%i3) ishow(covdiff(%,s))$
                       k         %1     k         %1     k
          (%t3)     - a     ichr2    - a     ichr2    + a
                       i %1      j s    %1 j      i s    i j,s

                       k     %1
                + ichr2     a
                       %1 s  i j
          (%i4) imetric:g;
          (%o4)                                  g
          (%i5) ishow(ev(%th(2),ichr2))$
                   %1 %4  k
                  g      a     (g       - g       + g      )
                          i %1   s %4,j    j s,%4    j %4,s
          (%t5) - ------------------------------------------
                                      2
              %1 %3  k
             g      a     (g       - g       + g      )
                     %1 j   s %3,i    i s,%3    i %3,s
           - ------------------------------------------
                                 2
              k %2  %1
             g     a    (g        - g        + g       )
                    i j   s %2,%1    %1 s,%2    %1 %2,s     k
           + ------------------------------------------- + a
                                  2                         i j,s

 -- Función: lorentz_gauge (<expr>)
     Impone la condición de Lorentz sustituyendo por 0 todos los objetos
     indexados de <expr> que tengan un índice derivado idéntico a un
     índice contravariante.

 -- Función: igeodesic_coords (<expr>, <nombre>)

     Elimina los símbolos no diferenciados de Christoffel y las primeras
     derivadas del tensor métrico de <expr>.  El argumento <nombre> de
     la función 'igeodesic_coords' se refiere a la métrica <nombre> si
     aparece en <expr>, mientras que los coeficientes de conexión deben
     tener los nombres 'ichr1' y/o 'ichr2'.  El siguiente ejemplo hace
     la verificación de la identidad cíclica satisfecha por el tensor de
     curvatura de Riemann haciendo uso de la función 'igeodesic_coords'.


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(icurvature([r,s,t],[u]))$
                       u            u         %1         u
          (%t2) - ichr2      - ichr2     ichr2    + ichr2
                       r t,s        %1 s      r t        r s,t

                                                        u         %1
                                                 + ichr2     ichr2
                                                        %1 t      r s
          (%i3) ishow(igeodesic_coords(%,ichr2))$
                                           u            u
          (%t3)                       ichr2      - ichr2
                                           r s,t        r t,s
          (%i4) ishow(igeodesic_coords(icurvature([r,s,t],[u]),ichr2)+
                      igeodesic_coords(icurvature([s,t,r],[u]),ichr2)+
                      igeodesic_coords(icurvature([t,r,s],[u]),ichr2))$
                       u            u            u            u
          (%t4) - ichr2      + ichr2      + ichr2      - ichr2
                       t s,r        t r,s        s t,r        s r,t

                                                       u            u
                                                - ichr2      + ichr2
                                                       r t,s        r s,t
          (%i5) canform(%);
          (%o5)                                  0

25.2.5 Sistemas de referencia móviles
-------------------------------------

Maxima puede hacer cálculos utilizando sistemas de referencia móviles,
los cuales pueden ser ortonormales o cualesquiera otros.

Para utilizar sistemas de referencia, primero se debe asignar a la
variable 'iframe_flag' el valor 'true'.  Con esto se hace que los
símbolos de Christoffel, 'ichr1' y 'ichr2', sean reemplazados por los
coeficientes 'icc1' y 'icc2' en los cálculos, cambiando así el
comportamiento de 'covdiff' y 'icurvature'.

El sistema de referencia se define con dos tensores: el campo del
sistema de referencia inverso ('ifri', la base dual tetrad) y la métrica
del sistema de referencia 'ifg'.  La métrica del sistema de referencia
es la matriz identidad en los sistemas de referencia ortonormales, o la
métrica de Lorentz en sistemas de referencia ortonormales en el
espacio-tiempo de Minkowski.  El campo del sistema de referencia inverso
define la base del sistema de referencia con vectores unitarios.  Las
propiedades contractivas se definen para el campo y la métrica del
sistema de referencia.

Si 'iframe_flag' vale 'true', muchas expresiones de 'itensor' utilizan
la métrica 'ifg' en lugar de la métrica definida por 'imetric' para
incrementar y reducir índices.

IMPORTANTE: Asignando a la variable 'iframe_flag' el valor 'true' NO
deshace las propiedades contractivas de una métrica establecidas con una
llamada a 'defcon' o a 'imetric'.  Si se utiliza el campo del sistema de
referencia, es mejor definir la métrica asignando su nombre a la
variable 'imetric' y NO hacer una llamada a la función 'imetric'.

Maxima utiliza estos dos tensores para definir los coeficientes del
sistema de referencia: 'ifc1' y and 'ifc2', los cuales forman parte de
los coeficientes de conexión 'icc1' y 'icc2', tal como demuestra el
siguiente ejemplo:


     (%i1) load(itensor);
     (%o1)      /share/tensor/itensor.lisp
     (%i2) iframe_flag:true;
     (%o2)                                true
     (%i3) ishow(covdiff(v([],[i]),j))$
                                    i        i     %1
     (%t3)                         v   + icc2     v
                                    ,j       %1 j
     (%i4) ishow(ev(%,icc2))$
                                    %1     i       i
     (%t4)                         v   ifc2     + v
                                           %1 j    ,j
     (%i5) ishow(ev(%,ifc2))$
                               %1    i %2                i
     (%t5)                    v   ifg     ifc1        + v
                                              %1 j %2    ,j
     (%i6) ishow(ev(%,ifc1))$
                 %1    i %2
                v   ifg     (ifb        - ifb        + ifb       )
                                j %2 %1      %2 %1 j      %1 j %2     i
     (%t6)      -------------------------------------------------- + v
                                        2                             ,j
     (%i7) ishow(ifb([a,b,c]))$
                                                        %3    %4
     (%t7)               (ifri        - ifri       ) ifr   ifr
                              a %3,%4       a %4,%3     b     c

Se utiliza un método alternativo para calcular el sistema de referencia
'ifb' si la variable 'iframe_bracket_form' vale 'false':


     (%i8) block([iframe_bracket_form:false],ishow(ifb([a,b,c])))$
                                     %6    %5        %5      %6
     (%t8)              ifri     (ifr   ifr     - ifr     ifr  )
                            a %5     b     c,%6      b,%6    c

 -- Variable: ifb

     Es el sistema de referencia soporte.  La contribución de la métrica
     del campo a los coeficientes de conexión se expresa utilizando:


                    - ifb      + ifb      + ifb
                         c a b      b c a      a b c
          ifc1    = --------------------------------
              abc                  2

     El sistema de referencia soporte se define en términos del campo y
     la métrica del sistema de referencia.  Se utilizan dos métodos
     alternativos dependiendo del valor de 'frame_bracket_form'.  Si
     vale 'true' (que es el valor por defecto) o si 'itorsion_flag' vale
     'true':


                    d      e                                      f
          ifb =  ifr    ifr   (ifri      - ifri      - ifri    itr   )
             abc    b      c       a d,e       a e,d       a f    d e


     En otro caso:


                       e      d        d      e
          ifb    = (ifr    ifr    - ifr    ifr   ) ifri
             abc       b      c,e      b,e    c        a d

 -- Variable: icc1

     Coeficientes de conexión de primera especie.  Se definen en
     'itensor' como


          icc1    = ichr1    - ikt1    - inmc1
              abc        abc       abc        abc

     En esta expresión, si 'iframe_flag' vale 'true', el símbolo de
     Christoffel 'ichr1' se reemplaza por el coeficiente de conexión del
     sistema de referencia 'ifc1'.  Si 'itorsion_flag' vale 'false',
     'ikt1' será omitido.  También se omite si se utiliza una base, ya
     que la torsión ya está calculada como parte del sistema de
     referencia.

 -- Variable: icc2

     Coeficientes de conexión de segunda especie.  Se definen en
     'itensor' como


              c         c        c         c
          icc2   = ichr2   - ikt2   - inmc2
              ab        ab       ab        ab

     En esta expresión, si la variable 'iframe_flag' vale 'true', el
     símbolo de Christoffel 'ichr2' se reemplaza por el coeficiente de
     conexión del sistema de referencia 'ifc2'.  Si 'itorsion_flag' vale
     'false', 'ikt2' se omite.  También se omite si se utiliza una base
     de referncia.  Por último, si 'inonmet_flag' vale 'false', se omite
     'inmc2'.

 -- Variable: ifc1

     Coeficiente del sistema de referencia de primera especie, también
     conocido como coeficientes de rotación de Ricci.  Este tensor
     represnta la contribución de la métrica del sistema de referencia
     al coeficiente de conexión de primera especie, definido como


                    - ifb      + ifb      + ifb
                         c a b      b c a      a b c
          ifc1    = --------------------------------
              abc                   2


 -- Variable: ifc2

     Coeficiente del sistema de referencia de segunda especie.  Este
     tensor representa la contribución de la métrica del sistema de
     referencia al coeficiente de conexión de segunda especie, definido
     como


              c       cd
          ifc2   = ifg   ifc1
              ab             abd

 -- Variable: ifr

     El campo del sistema de referencia.  Se contrae con el campo
     inverso 'ifri' para formar la métrica del sistema de referencia,
     'ifg'.

 -- Variable: ifri

     Campo inverso del sistema de referencia.  Especifica la base del
     sistema de referencia (vectores de la base dual).

 -- Variable: ifg

     La métrica del sistema de referencia.  Su valor por defecto es
     'kdelta', pero puede cambiarse utilizando 'components'.

 -- Variable: ifgi

     La métrica inversa del sistema de referencia.  Se contrae con la
     métrica 'ifg' para dar 'kdelta'.

 -- Variable opcional: iframe_bracket_form
     Valor por defecto: 'true'

     Especifica cómo se calcula 'ifb'.

25.2.6 Torsión y no metricidad
------------------------------

Maxima trabaja con conceptos como la torsión y la no metricidad.  Cuando
la variable 'itorsion_flag' vale 'true', la contribución de la torsión
se añade a los coeficientes de conexión.  También se añaden las
componentes de no metricidad cuando 'inonmet_flag' vale 'true'.

 -- Variable: inm

     Vector de no metricidad.  La no metricidad conforme se define a
     partir de la derivada covariante del tensor métrico.  La derivada
     covariante del tensor métrico, que normalmente es nula, se calcula,
     cuando 'inonmet_flag' vale 'true', como

          g     =- g  inm
           ij;k     ij   k

 -- Variable: inmc1

     Permutación covariante de las componentes del vector de no
     metricidad.  Se define como


                     g   inm  - inm  g   - g   inm
                      ab    c      a  bc    ac    b
          inmc1    = ------------------------------
               abc                 2

     (Sustitúyase 'g' por 'ifg' si se utiliza una métrica para el
     sistema de referencia.)

 -- Variable: inmc2

     Permutación contravariante de las componentes del vector de no
     metricidad.  Se utiliza en los coeficientes de conexión si
     'inonmet_flag' vale 'true'.  Se define como


                                c         c         cd
                    -inm  kdelta  - kdelta  inm  + g   inm  g
               c        a       b         a    b          d  ab
          inmc2   = -------------------------------------------
               ab                        2

     (Sustitúyase 'g' por 'ifg' si se utiliza una métrica para el
     sistema de referencia.)

 -- Variable: ikt1

     Permutación covariante del tensor de permutación, también conocido
     como contorsión.  Se define como


                            d           d       d
                    -g   itr  - g    itr   - itr   g
                      ad    cb    bd    ca      ab  cd
          ikt1    = ----------------------------------
              abc                   2

     (Sustitúyase 'g' por 'ifg' si se utiliza una métrica para el
     sistema de referencia.)

 -- Variable: ikt2

     Permutación contravariante del tensor de permutación, también
     conocido como contorsión.  Se define como


              c     cd
          ikt2   = g   ikt1
              ab           abd

     (Sustitúyase 'g' por 'ifg' si se utiliza una métrica para el
     sistema de referencia.)

 -- Variable: itr

     Tensor de torsión.  Para una métrica con torsión, la diferenciación
     covariante iterada de una función escalar no conmuta, tal como
     demuestra el siguiente ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric:g;
          (%o2)                                  g
          (%i3) covdiff(covdiff(f([],[]),i),j)
                   -covdiff(covdiff(f([],[]),j),i)$
          (%i4) ishow(%)$
                                             %4              %2
          (%t4)                    f    ichr2    - f    ichr2
                                    ,%4      j i    ,%2      i j
          (%i5) canform(%);
          (%o5)                                  0
          (%i6) itorsion_flag:true;
          (%o6)                                true
          (%i7) covdiff(covdiff(f([],[]),i),j)
                  -covdiff(covdiff(f([],[]),j),i)$
          (%i8) ishow(%)$
                                     %8             %6
          (%t8)             f    icc2    - f    icc2    - f     + f
                             ,%8     j i    ,%6     i j    ,j i    ,i j
          (%i9) ishow(canform(%))$
                                             %1             %1
          (%t9)                     f    icc2    - f    icc2
                                     ,%1     j i    ,%1     i j
          (%i10) ishow(canform(ev(%,icc2)))$
                                             %1             %1
          (%t10)                    f    ikt2    - f    ikt2
                                     ,%1     i j    ,%1     j i
          (%i11) ishow(canform(ev(%,ikt2)))$
                                %2 %1                    %2 %1
          (%t11)          f    g      ikt1       - f    g      ikt1
                           ,%2            i j %1    ,%2            j i %1
          (%i12) ishow(factor(canform(rename(expand(ev(%,ikt1))))))$
                                     %3 %2            %1       %1
                               f    g      g      (itr    - itr   )
                                ,%3         %2 %1     j i      i j
          (%t12)               ------------------------------------
                                                2
          (%i13) decsym(itr,2,1,[anti(all)],[]);
          (%o13)                               done
          (%i14) defcon(g,g,kdelta);
          (%o14)                               done
          (%i15) subst(g,nounify(g),%th(3))$
          (%i16) ishow(canform(contract(%)))$
                                                     %1
          (%t16)                           - f    itr
                                              ,%1    i j

25.2.7 Álgebra exterior
-----------------------

Con el paquete 'itensor' se pueden realizar operaciones en campos
tensoriales covariantes antisimétricos.  Un campo tensorial totalmente
antisimétrrico de rango (0,L) se corresponde con una L-forma
diferencial.  Sobre estos objetos se define una operación que se llama
producto exterior.

Desafortunadamente no hay consenso entre los autores a la hora de
definir el producto exterior.  Algunos autores prefieren una definición
que se corresponde con la noción de antisimetrización, con lo que el
producto externo de dos campos vectoriales se definiría como

                 a a  - a a
                  i j    j i
      a  /\ a  = -----------
       i     j        2

De forma más general, el producto de una p-forma por una q-forma se
definiría como

                            1     k1..kp l1..lq
     A       /\ B       = ------ D              A       B
      i1..ip     j1..jq   (p+q)!  i1..ip j1..jq  k1..kp  l1..lq

donde 'D' es la delta de Kronecker.

Otros autores, sin embargo, prefieren una definición "geométrica" que se
corresponde con la noción del elemento de volumen,

     a  /\ a  = a a  - a a
      i     j    i j    j i

y, en el caso general,

                            1    k1..kp l1..lq
     A       /\ B       = ----- D              A       B
      i1..ip     j1..jq   p! q!  i1..ip j1..jq  k1..kp  l1..lq

Puesto que 'itensor' un paquete de álgebra tensorial, la primera de
estas dos definiciones parece la más natural.  Sin embargo, muchas
aplicaciones hacen uso de la segunda definición.  Para resolver el
dilema, se define una variable que controla el comportamiento del
producto exteriort: si 'igeowedge_flag' vale 'false' (el valor por
defecto), se utiliza la primera definición, si vale 'true', la segunda.

 -- Operador: ~

     El operador del producto exterior se representa por el símbolo '~'.
     Este es un operador binario.  Sus argumentos deben ser expresiones
     que tengan escalares, tensores covariantes de rango uno o tensores
     covariantes de rango 'l' que hayan sido declarados antisimétricos
     en todos los índices covariantes.

     El comportamiento del operador del producto exterior se controla
     con la variable 'igeowedge_flag', como en el ejemplo siguiente:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i])~b([j]))$
                                           a  b  - b  a
                                            i  j    i  j
          (%t2)                            -------------
                                                 2
          (%i3) decsym(a,2,0,[anti(all)],[]);
          (%o3)                                done
          (%i4) ishow(a([i,j])~b([k]))$
                                    a    b  + b  a    - a    b
                                     i j  k    i  j k    i k  j
          (%t4)                     ---------------------------
                                                 3
          (%i5) igeowedge_flag:true;
          (%o5)                                true
          (%i6) ishow(a([i])~b([j]))$
          (%t6)                            a  b  - b  a
                                            i  j    i  j
          (%i7) ishow(a([i,j])~b([k]))$
          (%t7)                     a    b  + b  a    - a    b
                                     i j  k    i  j k    i k  j

 -- Operador: |

     La barra vertical '|' representa la operación "contracción con un
     vector".  Cuando un tensor covariante totalmente antisimétrico se
     contrae con un vector contravariante, el resultado no depende del
     índice utilizado para la contracción.  Así, es posible definir la
     operación de contracción de forma que no se haga referencia al
     índice.

     En el paquete 'itensor' la contracción con un vector se realiza
     siempre respecto del primer índice de la ordenación literal.
     Ejemplo:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) decsym(a,2,0,[anti(all)],[]);
          (%o2)                                done
          (%i3) ishow(a([i,j],[])|v)$
                                              %1
          (%t3)                              v   a
                                                  %1 j
          (%i4) ishow(a([j,i],[])|v)$
                                               %1
          (%t4)                             - v   a
                                                   %1 j

     Nótese que es primordial que los tensores utilizados junto con el
     operador '|' se declaren totalmente antisimétricos en sus índices
     covariantes.  De no ser así, se pueden obtener resultados
     incorrectos.

 -- Función: extdiff (<expr>, <i>)

     Calcula la derivada exterior de <expr> con respecto del índice <i>.
     La derivada exterior se define formalmente como el producto
     exterior del operador de la derivada parcial y una forma
     diferencial.  Por lo tanto, esta operación también se ve afectada
     por el valor que tome la variable 'igeowedge_flag'.  Ejemplo:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(extdiff(v([i]),j))$
                                            v    - v
                                             j,i    i,j
          (%t2)                             -----------
                                                 2
          (%i3) decsym(a,2,0,[anti(all)],[]);
          (%o3)                                done
          (%i4) ishow(extdiff(a([i,j]),k))$
                                     a      - a      + a
                                      j k,i    i k,j    i j,k
          (%t4)                      ------------------------
                                                3
          (%i5) igeowedge_flag:true;
          (%o5)                                true
          (%i6) ishow(extdiff(v([i]),j))$
          (%t6)                             v    - v
                                             j,i    i,j
          (%i7) ishow(extdiff(a([i,j]),k))$
          (%t7)                    - (a      - a      + a     )
                                       k j,i    k i,j    j i,k

 -- Función: hodge (<expr>)

     Calcula el dual de Hodge <expr>.  Por ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric(g);
          (%o2)                            done
          (%i3) idim(4);
          (%o3)                            done
          (%i4) icounter:100;
          (%o4)                             100
          (%i5) decsym(A,3,0,[anti(all)],[])$

          (%i6) ishow(A([i,j,k],[]))$
          (%t6)                           A
                                           i j k
          (%i7) ishow(canform(hodge(%)))$
                                    %1 %2 %3 %4
                         levi_civita            g        A
                                                 %1 %102  %2 %3 %4
          (%t7)          -----------------------------------------
                                             6
          (%i8) ishow(canform(hodge(%)))$
                           %1 %2 %3 %8            %4 %5 %6 %7
          (%t8) levi_civita            levi_civita            g
                                                               %1 %106
                                       g        g        g      A         /6
                                        %2 %107  %3 %108  %4 %8  %5 %6 %7
          (%i9) lc2kdt(%)$

          (%i10) %,kdelta$

          (%i11) ishow(canform(contract(expand(%))))$
          (%t11)                     - A
                                        %106 %107 %108

 -- Variable opcional: igeowedge_flag
     Valor por defecto: 'false'

     Controla el comportamiento del producto exterior y de la derivada
     exterior.  Cuando vale 'false', la noción de formas diferenciales
     se corresponde con el de campo tensorial covariante totalmente
     antisimétrico.  Cuando vale 'true', las formas diferenciales se
     corresponden con la idea de elemento de volumen.

25.2.8 Exportando expresiones en TeX
------------------------------------

El paquete 'itensor' dispone de soporte limitado para exportar
expresiones con tensores a TeX. Puesto que las expresiones de 'itensor'
son llamadas a funciones, puede que la instrucción habitual en Maxima,
'tex', no devuleva los resultados esperados.  Se puede utlizar el
comando 'tentex', que tratará de traducir expresiones tensoriales a
objetos de TeX correctamente indexados.

 -- Función: tentex (<expr>)

     Para utilizar la función 'tentex', primero se debe cargar 'tentex',
     tal como muestra el siguiente ejemplo:


          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) load(tentex);
          (%o2)       /share/tensor/tentex.lisp
          (%i3) idummyx:m;
          (%o3)                                  m
          (%i4) ishow(icurvature([j,k,l],[i]))$
                      m1       i           m1       i           i
          (%t4)  ichr2    ichr2     - ichr2    ichr2     - ichr2
                      j k      m1 l        j l      m1 k        j l,k

                                                                i
                                                         + ichr2
                                                                j k,l
          (%i5) tentex(%)$
          $$\Gamma_{j\,k}^{m_1}\,\Gamma_{l\,m_1}^{i}-\Gamma_{j\,l}^{m_1}\,
           \Gamma_{k\,m_1}^{i}-\Gamma_{j\,l,k}^{i}+\Gamma_{j\,k,l}^{i}$$

     Nótese la asignación de la variable 'idummyx' para evitar la
     aparición del símbolo del porcentaje en la expresión en TeX, que
     puede dar errores de compilación.

     Téngase en cuenta que esta versión de la función 'tentex' es
     experimental.

25.2.9 Interactuando con ctensor
--------------------------------

El paquete 'itensor' genera código Maxima que luego puede ser ejecutado
en el contexto del paquete 'ctensor'.  La función que se encarga de esta
tarea es 'ic_convert'.

 -- Function: ic_convert (<eqn>)

     Convierte la ecuación <eqn> del entorno 'itensor' a una sentencia
     de asignación de 'ctensor'.  Sumas implícitas sobre índices mudos
     se hacen explícitas mientras que objetos indexados se transforman
     en arreglos (los subíndices de los arreglos se ordenan poniendo
     primero los covariantes seguidos de los contravariantes.  La
     derivada de un objeto indexado se reemplazará por por la forma
     nominal de 'diff' tomada con respecto a 'ct_coords' con el
     subíndice correspondiente al índice derivado.  Los símbolos de
     Christoffel 'ichr1' 'ichr2' se traducen a 'lcs' y 'mcs',
     respectivamente.  Además, se añaden bucles 'do' para la sumación de
     todos los índices libres, de manera que la sentencia traducida
     pueda ser evaluada haciendo simplemente 'ev'.  Los siguientes
     ejemplos muestran las funcionalidades de esta función.

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) eqn:ishow(t([i,j],[k])=f([],[])*g([l,m],[])*a([],[m],j)
                *b([i],[l,k]))$
                                       k        m   l k
          (%t2)                       t    = f a   b    g
                                       i j      ,j  i    l m
          (%i3) ic_convert(eqn);
          (%o3) for i thru dim do (for j thru dim do (
                 for k thru dim do
                  t        : f sum(sum(diff(a , ct_coords ) b
                   i, j, k                   m           j   i, l, k

           g    , l, 1, dim), m, 1, dim)))
            l, m
          (%i4) imetric(g);
          (%o4)                                done
          (%i5) metricconvert:true;
          (%o5)                                true
          (%i6) ic_convert(eqn);
          (%o6) for i thru dim do (for j thru dim do (
                 for k thru dim do
                  t        : f sum(sum(diff(a , ct_coords ) b
                   i, j, k                   m           j   i, l, k

           lg    , l, 1, dim), m, 1, dim)))
             l, m

25.2.10 Palabras reservadas
---------------------------

Las siguientes palabras son utilizadas por el paquete 'itensor'
internamente, por lo que no deberían ser modificadas por el usuario:

       Palabra    Comentarios
       ------------------------------------------
       indices2() Versión interna de indices()
       conti      Lista los índices contravariantes
       covi       Lista los índices covariantes
       deri       Lista los índices de derivadas
       name       Devuelve el nombre de un objeto indexado
       concan
       irpmon
       lc0
       _lc2kdt0
       _lcprod
       _extlc


File: maxima.info,  Node: ctensor,  Next: atensor,  Prev: itensor,  Up: Top

26 ctensor
**********

* Menu:

* Introducción a ctensor::     
* Funciones y variables para ctensor::     


File: maxima.info,  Node: Introducción a ctensor,  Next: Funciones y variables para ctensor,  Prev: ctensor,  Up: ctensor

26.1 Introducción a ctensor
===========================

El paquete 'ctensor' dispone de herramientas para manipular componentes
de tensores.  Para poder hacer uso de 'ctensor' es necesario cargarlo
previamente en memoria ejecutando 'load(ctensor)'.  Para comenzar una
sesión interactiva con 'ctensor', ejecutar la función 'csetup()'.
Primero se le pregunta al usuario la dimensión de la variedad.  Si la
dimensión es 2, 3 o 4, entonces la lista de coordenadas será por defecto
'[x,y]', '[x,y,z]' o '[x,y,z,t]', respectivamente.  Estos nombres pueden
cambiarse asignando una nueva lista de coordenadas a la variable
'ct_coords' (que se describe más abajo), siendo el usuario advertido
sobre este particular.  Se debe tener cuidado en evitar que los nombres
de las coordenadas entren en conflicto con los nombres de otros objetos
en Maxima.

A continuación, el usuario introduce la métrica, bien directamente, o
desde un fichero especificando su posición ordinal.  La métrica se
almacena en la matriz 'lg'.  Por último, la métrica inversa se obtiene y
almacena en la matriz 'ug'.  También se dispone de la opción de efectuar
todos los cálculos en serie de potencias.

Se desarrolla a continuación un ejemplo para la métrica estática,
esférica y simétrica, en coordenadas estándar, que se aplicará
posteriormente al problema de derivar las ecuaciones de vacío de
Einstein (de las que se obtiene la solución de Schwarzschild).  Muchas
de las funciones de 'ctensor' se mostrarán en los ejemplos para la
métrica estándar.

     (%i1) load(ctensor);
     (%o1)      /share/tensor/ctensor.mac
     (%i2) csetup();
     Enter the dimension of the coordinate system:
     4;
     Do you wish to change the coordinate names?
     n;
     Do you want to
     1. Enter a new metric?

     2. Enter a metric from a file?

     3. Approximate a metric with a Taylor series?
     1;

     Is the matrix  1. Diagonal  2. Symmetric  3. Antisymmetric  4. General
     Answer 1, 2, 3 or 4
     1;
     Row 1 Column 1:
     a;
     Row 2 Column 2:
     x^2;
     Row 3 Column 3:
     x^2*sin(y)^2;
     Row 4 Column 4:
     -d;

     Matrix entered.
     Enter functional dependencies with the DEPENDS function or 'N' if none
     depends([a,d],x);
     Do you wish to see the metric?
     y;
                               [ a  0       0        0  ]
                               [                        ]
                               [     2                  ]
                               [ 0  x       0        0  ]
                               [                        ]
                               [         2    2         ]
                               [ 0  0   x  sin (y)   0  ]
                               [                        ]
                               [ 0  0       0       - d ]
     (%o2)                                done
     (%i3) christof(mcs);
                                                 a
                                                  x
     (%t3)                          mcs        = ---
                                       1, 1, 1   2 a

                                                  1
     (%t4)                           mcs        = -
                                        1, 2, 2   x

                                                  1
     (%t5)                           mcs        = -
                                        1, 3, 3   x

                                                 d
                                                  x
     (%t6)                          mcs        = ---
                                       1, 4, 4   2 d

                                                   x
     (%t7)                          mcs        = - -
                                       2, 2, 1     a

                                                cos(y)
     (%t8)                         mcs        = ------
                                      2, 3, 3   sin(y)

                                                    2
                                               x sin (y)
     (%t9)                      mcs        = - ---------
                                   3, 3, 1         a

     (%t10)                   mcs        = - cos(y) sin(y)
                                 3, 3, 2

                                                 d
                                                  x
     (%t11)                         mcs        = ---
                                       4, 4, 1   2 a
     (%o11)                               done


File: maxima.info,  Node: Funciones y variables para ctensor,  Prev: Introducción a ctensor,  Up: ctensor

26.2 Funciones y variables para ctensor
=======================================

26.2.1 Inicialización y preparación
-----------------------------------

 -- Función: csetup ()
     Es la función del paquete 'ctensor' que inicializa el paquete y
     permite al usuario introducir una métrica de forma interactiva.
     Véase 'ctensor' para más detalles.

 -- Función: cmetric (<dis>)
 -- Función: cmetric ()
     Es la función del paquete 'ctensor' que calcula la métrica inversa
     y prepara el paquete para cálculos ulteriores.

     Si 'cframe_flag' vale 'false', la función calcula la métrica
     inversa 'ug' a partir de la matriz 'lg' definida por el usuario.
     Se calcula también la métrica determinante y se almacena en la
     variable 'gdet'.  Además, el paquete determina si la métrica es
     diagonal y ajusta el valor de 'diagmetric' de la forma apropiada.
     Si el argumento opcional <dis> está presente y no es igual a
     'false', el usuario podrá ver la métrica inversa.

     Si 'cframe_flag' vale 'true', la función espera que los valores de
     'fri' (la matriz del sistema de referencia inverso) y 'lfg' (la
     matriz del sistema de referencia) estén definidos.  A partir de
     ellos, se calculan la matriz del sistema de referencia 'fr' y su
     métrica 'ufg'.

 -- Función: ct_coordsys (<sistema_coordenadas>, <extra_arg>)
 -- Función: ct_coordsys (<sistema_coordenadas>)

     Prepara un sistema de coordenadas predefinido y una métrica.  El
     argumento <sistema_coordenadas> puede ser cualquiera de los
     siguientes símbolos:


            Símbolo              Dim Coordenadas       Descripción/comentarios
            --------------------------------------------------------------------------------
            cartesian2d           2  [x,y]             Sistema de coordenadas cartesianas en 2D
            polar                 2  [r,phi]           Sistema de coordenadas polares
            elliptic              2  [u,v]             Sistema de coordenadas elípticas
            confocalelliptic      2  [u,v]             Coordenadas elípticas confocales
            bipolar               2  [u,v]             Sistema de coordenas bipolares
            parabolic             2  [u,v]             Sistema de coordenadas parabólicas
            cartesian3d           3  [x,y,z]           Sistema de coordenadas cartesianas en 3D
            polarcylindrical      3  [r,theta,z]       Polares en 2D con cilíndrica z
            ellipticcylindrical   3  [u,v,z]           Elípticas en 2D con cilíndrica z
            confocalellipsoidal   3  [u,v,w]           Elipsoidales confocales
            bipolarcylindrical    3  [u,v,z]           Bipolares en 2D con cilíndrica z
            paraboliccylindrical  3  [u,v,z]           Parabólicas en 2D con cilíndrica z
            paraboloidal          3  [u,v,phi]         Coordenadas paraboloidales
            conical               3  [u,v,w]           Coordenadas cónicas
            toroidal              3  [u,v,phi]         Coordenadas toroidales
            spherical             3  [r,theta,phi]     Sistema de coordenadas esféricas
            oblatespheroidal      3  [u,v,phi]         Coordenadas esferoidales obleadas
            oblatespheroidalsqrt  3  [u,v,phi]
            prolatespheroidal     3  [u,v,phi]         Coordenadas esferoidales prolatas
            prolatespheroidalsqrt 3  [u,v,phi]
            ellipsoidal           3  [r,theta,phi]     Coordenadas elipsoidales
            cartesian4d           4  [x,y,z,t]         Sistema de coordenadas cartesianas en 4D
            spherical4d           4  [r,theta,eta,phi] Sistema de coordenadas esféricas en 4D
            exteriorschwarzschild 4  [t,r,theta,phi]   Métrica de Schwarzschild
            interiorschwarzschild 4  [t,z,u,v]         Métrica interior de Schwarzschild
            kerr_newman           4  [t,r,theta,phi]   Métrica simétrica con carga axial

     El argumento 'sistema_coordenadas' puede ser también una lista de
     funciones de transformación, seguida de una lista que contenga los
     nombres de las coordenadas.  Por ejemplo, se puede especificar una
     métrica esférica como se indica a continuación:


          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ct_coordsys([r*cos(theta)*cos(phi),r*cos(theta)*sin(phi),
                r*sin(theta),[r,theta,phi]]);
          (%o2)                                done
          (%i3) lg:trigsimp(lg);
                                     [ 1  0         0        ]
                                     [                       ]
                                     [     2                 ]
          (%o3)                      [ 0  r         0        ]
                                     [                       ]
                                     [         2    2        ]
                                     [ 0  0   r  cos (theta) ]
          (%i4) ct_coords;
          (%o4)                           [r, theta, phi]
          (%i5) dim;
          (%o5)                                  3

     Las funciones de transformación se pueden utilizar también si
     'cframe_flag' vale 'true':


          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) cframe_flag:true;
          (%o2)                                true
          (%i3) ct_coordsys([r*cos(theta)*cos(phi),r*cos(theta)*sin(phi),
                r*sin(theta),[r,theta,phi]]);
          (%o3)                                done
          (%i4) fri;
                [ cos(phi) cos(theta)  - cos(phi) r sin(theta)  - sin(phi) r cos(theta) ]
                [                                                                       ]
          (%o4) [ sin(phi) cos(theta)  - sin(phi) r sin(theta)   cos(phi) r cos(theta)  ]
                [                                                                       ]
                [     sin(theta)            r cos(theta)                   0            ]
          (%i5) cmetric();
          (%o5)                                false
          (%i6) lg:trigsimp(lg);
                                     [ 1  0         0        ]
                                     [                       ]
                                     [     2                 ]
          (%o6)                      [ 0  r         0        ]
                                     [                       ]
                                     [         2    2        ]
                                     [ 0  0   r  cos (theta) ]

     El argumento opcional <extra_arg> puede ser cualquiera de los
     siguientes:

     'cylindrical' indica a 'ct_coordsys' que añada una coordenada
     cilíndrica más.

     'minkowski' indica a 'ct_coordsys' que añada una coordenada más con
     signatura métrica negativa.

     'all' indica a 'ct_coordsys' que llame a 'cmetric' y a
     'christof(false)' tras activar la métrica.

     Si la variable global 'verbose' vale 'true', 'ct_coordsys' muestra
     los valores de 'dim', 'ct_coords', junto con 'lg' o 'lfg' y 'fri',
     dependiendo del valor de 'cframe_flag'.

 -- Función: init_ctensor ()
     Inicializa el paquete 'ctensor'.

     La función 'init_ctensor' reinicializa el paquete 'ctensor'.  Borra
     todos los arreglos ("arrays") y matrices utilizados por 'ctensor' y
     reinicializa todas las variables, asignando a 'dim' el valor 4 y la
     métrica del sistema de referencia a la de Lorentz.

26.2.2 Los tensores del espacio curvo
-------------------------------------

El propósito principal del paquete 'ctensor' es calcular los tensores
del espacio (-tiempo) curvo, en especial los tensores utilizados en
relatividad general.

Cuando se utiliza una métrica, 'ctensor' puede calcular los siguientes
tensores:


      lg  -- ug
        \      \
         lcs -- mcs -- ric -- uric
                   \      \       \
                    \      tracer - ein -- lein
                     \
                      riem -- lriem -- weyl
                          \
                           uriem


El paquete 'ctensor' también puede trabajar con sistemas de referencia
móviles.  Si 'cframe_flag' vale 'true', se pueden calcular los
siguientes tensores:


      lfg -- ufg
          \
      fri -- fr -- lcs -- mcs -- lriem -- ric -- uric
           \                       |  \      \       \
            lg -- ug               |   weyl   tracer - ein -- lein
                                   |\
                                   | riem
                                   |
                                   \uriem

 -- Función: christof (<dis>)
     Es una función del paquete 'ctensor'.  Calcula los símbolos de
     Christoffel de ambos tipos.  El argumento <dis> determina qué
     resultados se mostrarán de forma inmediata.  Los símbolos de
     Christoffel de primer y segundo tipo se almacenan en los arreglos
     'lcs[i,j,k]' y 'mcs[i,j,k]', respectivamente, y se definen
     simétricos en sus dos primeros índices.  Si el argumento de
     'christof' es 'lcs' o 'mcs' entonces serán mostrados únicamente los
     valores no nulos de 'lcs[i,j,k]' o 'mcs[i,j,k]', respectivamente.
     Si el argumento es 'all' entonces se mostrarán los valores no nulos
     de 'lcs[i,j,k]' y 'mcs[i,j,k]'.  Si el argumento vale 'false'
     entonces no se mostrarán los elementos.  El arreglo 'mcs[i,j,k]'
     está definido de tal modo que el último índice es contravariante.

 -- Función: ricci (<dis>)
     Es una función del paquete 'ctensor'.  La función 'ricci' calcula
     las componentes covariantes (simétricas) 'ric[i,j]' del tensor de
     Ricci.  Si el argumento <dis> vale 'true', entonces se muestran las
     componentes no nulas.

 -- Función: uricci (<dis>)
     Esta función calcula en primer lugar las componentes covariantes
     'ric[i,j]' del tensor de Ricci.  Después se calcula el tensor de
     Ricci utilizando la métrica contravariante.  Si el valor del
     argumento <dis> vale 'true', entonces se mostrarán directamente las
     componentes 'uric[i,j]' (el índice <i> es covariante y el <j>
     contravariante).  En otro caso, 'ricci(false)' simplemente
     calculará las entradas del arreglo 'uric[i,j]' sin mostrar los
     resultados.

 -- Función: scurvature ()

     Devuelve la curvatura escalar (obtenida por contracción del tensor
     de Ricci) de la variedad de Riemannian con la métrica dada.

 -- Función: einstein (<dis>)
     Es una función del paquete 'ctensor'.  La función 'einstein'
     calcula el tensor de Einstein después de que los símbolos de
     Christoffel y el tensor de Ricci hayan sido calculados (con las
     funciones 'christof' y 'ricci').  Si el argumento <dis> vale
     'true', entonces se mostrarán los valores no nulos del tensor de
     Einstein 'ein[i,j]', donde 'j' es el índice contravariante.  La
     variable 'rateinstein' causará la simplificación racional de estas
     componentes.  Si 'ratfac' vale 'true' entonces las componentes
     también se factorizarán.

 -- Función: leinstein (<dis>)
     Es el tensor covariante de Einstein.  La función 'leinstein'
     almacena los valores del tensor covariante de Einstein en el
     arreglo 'lein'.  El tensor covariante de Einstein se calcula a
     partir del tensor de Einstein 'ein' multiplicándolo por el tensor
     métrico.  Si el argumento <dis> vale 'true', entonces se mostrarán
     los valores no nulos del tensor covariante de Einstein.

 -- Función: riemann (<dis>)
     Es una función del paquete 'ctensor'.  La función 'riemann' calcula
     el tensor de curvatura de Riemann a partir de la métrica dada y de
     los símbolos de Christoffel correspondientes.  Se utiliza el
     siguiente convenio sobre los índices:

                          l      _l       _l       _l   _m    _l   _m
           R[i,j,k,l] =  R    = |      - |      + |    |   - |    |
                          ijk     ij,k     ik,j     mk   ij    mj   ik

     Esta notación es consistente con la notación utilizada por el
     paquete 'itensor' y su función 'icurvature'.  Si el argumento
     opcional <dis> vale 'true', se muestran las componentes no nulas
     únicas de 'riem[i,j,k,l]'.  Como en el caso del tensor de Einstein,
     ciertas variables permiten controlar al usuario la simplificación
     de las componentes del tensor de Riemann.  Si 'ratriemann' vale
     'true', entonces se hará la simplificación racional.  Si 'ratfac'
     vale 'true', entonces se factorizarán todas las componentes.

     Si la variable 'cframe_flag' vale 'false', el tensor de Riemann se
     calcula directamente a partir de los símbolos de Christoffel.  Si
     'cframe_flag' vale 'true', el tensor covariante de Riemann se
     calcula a partir de los coeficientes del campo.

 -- Función: lriemann (<dis>)
     Es el tensor covariante de Riemann ('lriem[]').

     Calcula el tensor covariante de Riemann como un arreglo 'lriem'.
     Si el argumento <dis> vale 'true', sólo se muestran los valores no
     nulos.

     Si la variable 'cframe_flag' vale 'true', el tensor covariante de
     Riemann se calcula directamente de los coeficientes del campo.  En
     otro caso, el tensor de Riemann (3,1) se calcula en primer lugar.

     Para más información sobre la ordenación de los índices, véase
     'riemann'.

 -- Función: uriemann (<dis>)
     Calcula las componentes contravariantes del tensor de curvatura de
     Riemann como un arreglo 'uriem[i,j,k,l]'.  Éstos se muestran si
     <dis> vale 'true'.

 -- Función: rinvariant ()
     Calcula la invariante de Kretchmann ('kinvariant') obtenida por
     contracción de los tensores.

          lriem[i,j,k,l]*uriem[i,j,k,l].

     Este objeto no se simplifica automáticamente al ser en ocasiones
     muy grande.

 -- Función: weyl (<dis>)
     Calcula el tensor conforme de Weyl.  Si el argumento <dis> vale
     'true', se le mostrarán al usuario las componentes no nulas
     'weyl[i,j,k,l]'.  En otro caso, estas componentes serán únicamente
     calculadas y almacenadas.  Si la variable 'ratweyl' vale 'true',
     entonces las componentes se simplifican racionalmente; si 'ratfac'
     vale 'true' los resultados también se simplificarán.

26.2.3 Desarrollo de Taylor
---------------------------

El paquete 'ctensor' puede truncar resultados e interpretarlos como
aproximaciones de Taylor.  Este comportamiento se controla con
lavariable 'ctayswitch'; cuando vale 'true', 'ctensor' utiliza
internamente la función 'ctaylor' cuando simplifica resultados.

La función 'ctaylor' es llamada desde las siguientes funciones del
paquete 'ctensor':


         Función      Comentarios
         ---------------------------------
         christof()   Sólo para mcs
         ricci()
         uricci()
         einstein()
         riemann()
         weyl()
         checkdiv()

 -- Función: ctaylor ()

     La función 'ctaylor' trunca su argumento convirtiéndolo en un
     desarrollo de Taylor por medio de la función 'taylor' e invocando
     después a 'ratdisrep'.  Esto tiene el efecto de eliminar términos
     de orden alto en la variable de expansión 'ctayvar'.  El orden de
     los términos que deben ser eliminados se define 'ctaypov'; el punto
     alrededor del cual se desarrolla la serie se especifica en
     'ctaypt'.

     Como ejemplo, considérese una sencilla métrica que es una
     perturbación de la de Minkowski.  Sin añadir restricciones, incluso
     una métrica diagonal produce expansiones del tensor de Einstein que
     pueden llegar a ser muy complejas:


          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ratfac:true;
          (%o2)                                true
          (%i3) derivabbrev:true;
          (%o3)                                true
          (%i4) ct_coords:[t,r,theta,phi];
          (%o4)                         [t, r, theta, phi]
          (%i5) lg:matrix([-1,0,0,0],[0,1,0,0],[0,0,r^2,0],[0,0,0,r^2*sin(theta)^2]);
                                  [ - 1  0  0         0        ]
                                  [                            ]
                                  [  0   1  0         0        ]
                                  [                            ]
          (%o5)                   [          2                 ]
                                  [  0   0  r         0        ]
                                  [                            ]
                                  [              2    2        ]
                                  [  0   0  0   r  sin (theta) ]
          (%i6) h:matrix([h11,0,0,0],[0,h22,0,0],[0,0,h33,0],[0,0,0,h44]);
                                      [ h11   0    0    0  ]
                                      [                    ]
                                      [  0   h22   0    0  ]
          (%o6)                       [                    ]
                                      [  0    0   h33   0  ]
                                      [                    ]
                                      [  0    0    0   h44 ]
          (%i7) depends(l,r);
          (%o7)                               [l(r)]
          (%i8) lg:lg+l*h;
                   [ h11 l - 1      0          0                 0            ]
                   [                                                          ]
                   [     0      h22 l + 1      0                 0            ]
                   [                                                          ]
          (%o8)    [                        2                                 ]
                   [     0          0      r  + h33 l            0            ]
                   [                                                          ]
                   [                                    2    2                ]
                   [     0          0          0       r  sin (theta) + h44 l ]
          (%i9) cmetric(false);
          (%o9)                                done
          (%i10) einstein(false);
          (%o10)                               done
          (%i11) ntermst(ein);
          [[1, 1], 62]
          [[1, 2], 0]
          [[1, 3], 0]
          [[1, 4], 0]
          [[2, 1], 0]
          [[2, 2], 24]
          [[2, 3], 0]
          [[2, 4], 0]
          [[3, 1], 0]
          [[3, 2], 0]
          [[3, 3], 46]
          [[3, 4], 0]
          [[4, 1], 0]
          [[4, 2], 0]
          [[4, 3], 0]
          [[4, 4], 46]
          (%o12)                               done

     Sin embargo, si se recalcula este ejemplo como una aproximación
     lineal en la variable 'l', se obtienen expresiones más sencillas:


          (%i14) ctayswitch:true;
          (%o14)                               true
          (%i15) ctayvar:l;
          (%o15)                                 l
          (%i16) ctaypov:1;
          (%o16)                                 1
          (%i17) ctaypt:0;
          (%o17)                                 0
          (%i18) christof(false);
          (%o18)                               done
          (%i19) ricci(false);
          (%o19)                               done
          (%i20) einstein(false);
          (%o20)                               done
          (%i21) ntermst(ein);
          [[1, 1], 6]
          [[1, 2], 0]
          [[1, 3], 0]
          [[1, 4], 0]
          [[2, 1], 0]
          [[2, 2], 13]
          [[2, 3], 2]
          [[2, 4], 0]
          [[3, 1], 0]
          [[3, 2], 2]
          [[3, 3], 9]
          [[3, 4], 0]
          [[4, 1], 0]
          [[4, 2], 0]
          [[4, 3], 0]
          [[4, 4], 9]
          (%o21)                               done
          (%i22) ratsimp(ein[1,1]);
                                   2      2  4               2     2
          (%o22) - (((h11 h22 - h11 ) (l )  r  - 2 h33 l    r ) sin (theta)
                                        r               r r

                                          2               2      4    2
                            - 2 h44 l    r  - h33 h44 (l ) )/(4 r  sin (theta))
                                     r r                r



     Esta capacidad del paquete 'ctensor' puede ser muy útil; por
     ejemplo, cuando se trabaja en zonas del campo gravitatorio alejadas
     del origen de éste.

26.2.4 Campos del sistema de referencia
---------------------------------------

Cuando la variable 'cframe_flag' vale 'true', el paquete 'ctensor'
realiza sus cálculos utilizando un sistema de referencia móvil.

 -- Función: frame_bracket (<fr>, <fri>, <diagframe>)
     Es el sistema de referencia soporte ('fb[]').

     Calcula el soporte del sistema de referencia de acuerdo con la
     siguiente definición:

             c          c         c        d     e
          ifb   = ( ifri    - ifri    ) ifr   ifr
             ab         d,e       e,d      a     b

26.2.5 Clasificación algebraica
-------------------------------

Una nueva funcionalidad (Noviembre de 2004) de 'ctensor' es su capacidad
de obtener la clasificación de Petrov de una métrica espaciotemporal de
dimensión 4.  Para una demostración de esto véase el fichero
'share/tensor/petrov.dem'.

 -- Función: nptetrad ()
     Calcula la cuaterna nula de Newman-Penrose ('np').  Véase 'petrov'
     para un ejemplo.

     La cuaterna nula se construye bajo la suposición de que se está
     utilizando una métrica tetradimensional ortonormal con signatura
     métrica (-,+,+,+).  Los componentes de la cuaterna nula se
     relacionan con la inversa de la matriz del sistema de referencia de
     la siguiente manera:


          np  = (fri  + fri ) / sqrt(2)
            1       1      2

          np  = (fri  - fri ) / sqrt(2)
            2       1      2

          np  = (fri  + %i fri ) / sqrt(2)
            3       3         4

          np  = (fri  - %i fri ) / sqrt(2)
            4       3         4

 -- Función: psi (<dis>)
     Calcula los cinco coeficientes de Newman-Penrose
     'psi[0]'...'psi[4]'.  Si 'dis' vale 'true', se muestran estos
     coeficientes.  Véase 'petrov' para un ejemplo.

     Estos coeficientes se calculan a partir del tensor de Weyl.

 -- Función: petrov ()
     Calcula la clasificación de Petrov de la métrica caracterizada por
     'psi[0]'...'psi[4]'.

     Por ejemplo, lo que sigue demuestra cómo obtener la clasificación
     de Petrov para la métrica de Kerr:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) (cframe_flag:true,gcd:spmod,ctrgsimp:true,ratfac:true);
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) ug:invert(lg)$
          (%i5) weyl(false);
          (%o5)                                done
          (%i6) nptetrad(true);
          (%t6) np =

                 [  sqrt(r - 2 m)           sqrt(r)                                     ]
                 [ ---------------   ---------------------      0             0         ]
                 [ sqrt(2) sqrt(r)   sqrt(2) sqrt(r - 2 m)                              ]
                 [                                                                      ]
                 [  sqrt(r - 2 m)            sqrt(r)                                    ]
                 [ ---------------  - ---------------------     0             0         ]
                 [ sqrt(2) sqrt(r)    sqrt(2) sqrt(r - 2 m)                             ]
                 [                                                                      ]
                 [                                              r      %i r sin(theta)  ]
                 [        0                    0             -------   ---------------  ]
                 [                                           sqrt(2)       sqrt(2)      ]
                 [                                                                      ]
                 [                                              r       %i r sin(theta) ]
                 [        0                    0             -------  - --------------- ]
                 [                                           sqrt(2)        sqrt(2)     ]

                                       sqrt(r)          sqrt(r - 2 m)
          (%t7) npi = matrix([- ---------------------, ---------------, 0, 0],
                                sqrt(2) sqrt(r - 2 m)  sqrt(2) sqrt(r)

                    sqrt(r)            sqrt(r - 2 m)
          [- ---------------------, - ---------------, 0, 0],
             sqrt(2) sqrt(r - 2 m)    sqrt(2) sqrt(r)

                     1               %i
          [0, 0, ---------, --------------------],
                 sqrt(2) r  sqrt(2) r sin(theta)

                     1                 %i
          [0, 0, ---------, - --------------------])
                 sqrt(2) r    sqrt(2) r sin(theta)

          (%o7)                                done
          (%i7) psi(true);
          (%t8)                              psi  = 0
                                                0

          (%t9)                              psi  = 0
                                                1

                                                    m
          (%t10)                             psi  = --
                                                2    3
                                                    r

          (%t11)                             psi  = 0
                                                3

          (%t12)                             psi  = 0
                                                4
          (%o12)                               done
          (%i12) petrov();
          (%o12)                                 D

     La función de clasificación de Petrov se basa en el algoritmo
     publicado en "Classifying geometries in general relativity: III
     Classification in practice" de Pollney, Skea, and d'Inverno, Class.
     Quant.  Grav.  17 2885-2902 (2000).  Excepto para algunos ejemplos
     sencillos, esta implementación no ha sido exhaustivamente probada,
     por lo que puede contener errores.

26.2.6 Torsión y no metricidad
------------------------------

El paquete 'ctensor' es capaz de calcular e incluir coeficientes de
torsión y no metricidad en los coeficientes de conexión.

Los coeficientes de torsión se calculan a partir de un tensor
suministrado por el usuario, 'tr', el cual debe ser de rango (2,1).  A
partir de ahí, los coeficientes de torsión 'kt' se calculan de acuerdo
con las siguientes fórmulas:


                   m          m      m
            - g  tr   - g   tr   - tr   g
               im  kj    jm   ki     ij  km
     kt   = -------------------------------
       ijk                 2


       k     km
     kt   = g   kt
       ij         ijm

Los coeficientes de no metricidad se calculan a partir de un vector de
no metricidad, 'nm', suministrado por el usuario.  A partir de ahí, los
coeficientes de no metricidad, 'nmc', se calculan como se indica a
continuación:


                  k    k        km
            -nm  D  - D  nm  + g   nm  g
        k      i  j    i   j         m  ij
     nmc  = ------------------------------
        ij                2

donde D es la delta de Kronecker.

 -- Función: contortion (<tr>)

     Calcula los coeficientes (2,1) de contorsión del tensor de torsión
     <tr>.

 -- Función: nonmetricity (<nm>)

     Calcula los coeficientes (2,1) de no metricidad del vector de no
     metricidad <nm>.

26.2.7 Otras funcionalidades
----------------------------

 -- Función: ctransform (<M>)
     Es una función del paquete 'ctensor'.  Realiza una transformación
     de coordenadas a partir de una matriz cuadrada simétrica <M>
     arbitraria.  El usuario debe introducir las funciones que definen
     la transformación.

 -- Función: findde (<A>, <n>)

     Devuelve la lista de las ecuaciones diferenciales que corresponden
     a los elementos del arreglo cuadrado <n>-dimensional.  El argumento
     <n> puede ser 2 ó 3; 'deindex' es una lista global que contiene los
     índices de <A> que corresponden a estas ecuaciones diferenciales.
     Para el tensor de Einstein ('ein'), que es un arreglo
     bidimensional, si se calcula para la métrica del ejemplo de más
     abajo, 'findde' devuelve las siguientes ecuaciones diferenciales
     independientes:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) dim:4;
          (%o3)                                  4
          (%i4) lg:matrix([a,0,0,0],[0,x^2,0,0],[0,0,x^2*sin(y)^2,0],[0,0,0,-d]);
                                    [ a  0       0        0  ]
                                    [                        ]
                                    [     2                  ]
                                    [ 0  x       0        0  ]
          (%o4)                     [                        ]
                                    [         2    2         ]
                                    [ 0  0   x  sin (y)   0  ]
                                    [                        ]
                                    [ 0  0       0       - d ]
          (%i5) depends([a,d],x);
          (%o5)                            [a(x), d(x)]
          (%i6) ct_coords:[x,y,z,t];
          (%o6)                            [x, y, z, t]
          (%i7) cmetric();
          (%o7)                                done
          (%i8) einstein(false);
          (%o8)                                done
          (%i9) findde(ein,2);
                                                      2
          (%o9) [d  x - a d + d, 2 a d d    x - a (d )  x - a  d d  x + 2 a d d
                  x                     x x         x        x    x            x

                                                                  2          2
                                                          - 2 a  d , a  x + a  - a]
                                                               x      x
          (%i10) deindex;
          (%o10)                     [[1, 1], [2, 2], [4, 4]]

 -- Función: cograd ()
     Calcula el gradiente covariante de una función escalar permitiendo
     al usuario elegir el nombre del vector correspondiente, tal como
     ilustra el ejemplo que acompaña a la definición de la función
     'contragrad'.

 -- Function: contragrad ()

     Calcula el gradiente contravariante de una función escalar
     permitiendo al usuario elegir el nombre del vector correspondiente,
     tal como muestra el siguiente ejemplo para la métrica de
     Schwarzschild:


          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) depends(f,r);
          (%o4)                               [f(r)]
          (%i5) cograd(f,g1);
          (%o5)                                done
          (%i6) listarray(g1);
          (%o6)                            [0, f , 0, 0]
                                                r
          (%i7) contragrad(f,g2);
          (%o7)                                done
          (%i8) listarray(g2);
                                         f  r - 2 f  m
                                          r        r
          (%o8)                      [0, -------------, 0, 0]
                                               r

 -- Función: dscalar ()
     Calcula el tensor de d'Alembertian de la función escalar una vez se
     han declarado las dependencias.  Por ejemplo:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) depends(p,r);
          (%o4)                               [p(r)]
          (%i5) factor(dscalar(p));
                                    2
                              p    r  - 2 m p    r + 2 p  r - 2 m p
                               r r           r r        r          r
          (%o5)               --------------------------------------
                                                 2
                                                r

 -- Función: checkdiv ()

     Calcula la divergencia covariante del tensor de segundo rango
     (mixed second rank tensor), cuyo primer índice debe ser covariante,
     devolviendo las 'n' componentes correspondientes del campo
     vectorial (la divergencia), siendo 'n = dim'.

 -- Función: cgeodesic (<dis>)
     Es una función del paquete 'ctensor' que calcula las ecuaciones
     geodésicas del movimiento para una métrica dada, las cuales se
     almacenan en el arreglo 'geod[i]'.  Si el argumento <dis> vale
     'true' entonces se muestran estas ecuaciones.

 -- Función: bdvac (<f>)

     Genera las componentes covariantes de las ecuaciones del campo
     vacío de la teoría gravitacional de Brans- Dicke gravitational.  El
     campo escalar se especifica con el argumento <f>, el cual debe ser
     el nombre de una función no evaluada (precedida de apóstrofo) con
     dependencias funcionales, por ejemplo, ''p(x)'.

     Las componentes del tensor covariante (second rank covariant field
     tensor) se almacenan en el arreglo 'bd'.

 -- Función: invariant1 ()

     Genera el tensor de Euler-Lagrange (ecuaciones de campo) para la
     densidad invariante de R^2.  Las ecuaciones de campo son las
     componentes del arreglo 'inv1'.

26.2.8 Utilidades
-----------------

 -- Función: diagmatrixp (<M>)

     Devuelve 'true' si <M> es una matriz diagonal o un arreglo
     bidimensional.

 -- Función: symmetricp (<M>)

     Devuelve 'true' si <M> es una matriz simétrica o un arreglo
     bidimensional.

 -- Función: ntermst (<f>)
     Permite hacerse una idea del tamaño del tensor <f>.

 -- Función: cdisplay (<ten>)
     Muestra todos los elementos del tensor <ten> como arreglo
     multidimensional.  Tensors de rango 0 y 1, así como otros tipos de
     variables, se muestran como en 'ldisplay'.  Tensors de rango 2 se
     muestran como matrices bidimensionales, mientras que tensores de
     mayor rango se muestran como listas de matrices bidimensionales.
     Por ejemplo, el tensor de Riemann de la métrica de Schwarzschild se
     puede ver como:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ratfac:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) riemann(false);
          (%o4)                                done
          (%i5) cdisplay(riem);
                         [ 0               0                    0            0      ]
                         [                                                          ]
                         [                              2                           ]
                         [      3 m (r - 2 m)   m    2 m                            ]
                         [ 0  - ------------- + -- - ----       0            0      ]
                         [            4          3     4                            ]
                         [           r          r     r                             ]
                         [                                                          ]
              riem     = [                                 m (r - 2 m)              ]
                  1, 1   [ 0               0               -----------       0      ]
                         [                                      4                   ]
                         [                                     r                    ]
                         [                                                          ]
                         [                                              m (r - 2 m) ]
                         [ 0               0                    0       ----------- ]
                         [                                                   4      ]
                         [                                                  r       ]

                                          [    2 m (r - 2 m)       ]
                                          [ 0  -------------  0  0 ]
                                          [          4             ]
                                          [         r              ]
                               riem     = [                        ]
                                   1, 2   [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]

                                          [         m (r - 2 m)    ]
                                          [ 0  0  - -----------  0 ]
                                          [              4         ]
                                          [             r          ]
                               riem     = [                        ]
                                   1, 3   [ 0  0        0        0 ]
                                          [                        ]
                                          [ 0  0        0        0 ]
                                          [                        ]
                                          [ 0  0        0        0 ]

                                          [            m (r - 2 m) ]
                                          [ 0  0  0  - ----------- ]
                                          [                 4      ]
                                          [                r       ]
                               riem     = [                        ]
                                   1, 4   [ 0  0  0        0       ]
                                          [                        ]
                                          [ 0  0  0        0       ]
                                          [                        ]
                                          [ 0  0  0        0       ]

                                         [       0         0  0  0 ]
                                         [                         ]
                                         [       2 m               ]
                                         [ - ------------  0  0  0 ]
                              riem     = [    2                    ]
                                  2, 1   [   r  (r - 2 m)          ]
                                         [                         ]
                                         [       0         0  0  0 ]
                                         [                         ]
                                         [       0         0  0  0 ]

                             [     2 m                                         ]
                             [ ------------  0        0               0        ]
                             [  2                                              ]
                             [ r  (r - 2 m)                                    ]
                             [                                                 ]
                             [      0        0        0               0        ]
                             [                                                 ]
                  riem     = [                         m                       ]
                      2, 2   [      0        0  - ------------        0        ]
                             [                     2                           ]
                             [                    r  (r - 2 m)                 ]
                             [                                                 ]
                             [                                         m       ]
                             [      0        0        0         - ------------ ]
                             [                                     2           ]
                             [                                    r  (r - 2 m) ]

                                          [ 0  0       0        0 ]
                                          [                       ]
                                          [            m          ]
                                          [ 0  0  ------------  0 ]
                               riem     = [        2              ]
                                   2, 3   [       r  (r - 2 m)    ]
                                          [                       ]
                                          [ 0  0       0        0 ]
                                          [                       ]
                                          [ 0  0       0        0 ]

                                          [ 0  0  0       0       ]
                                          [                       ]
                                          [               m       ]
                                          [ 0  0  0  ------------ ]
                               riem     = [           2           ]
                                   2, 4   [          r  (r - 2 m) ]
                                          [                       ]
                                          [ 0  0  0       0       ]
                                          [                       ]
                                          [ 0  0  0       0       ]

                                                [ 0  0  0  0 ]
                                                [            ]
                                                [ 0  0  0  0 ]
                                                [            ]
                                     riem     = [ m          ]
                                         3, 1   [ -  0  0  0 ]
                                                [ r          ]
                                                [            ]
                                                [ 0  0  0  0 ]

                                                [ 0  0  0  0 ]
                                                [            ]
                                                [ 0  0  0  0 ]
                                                [            ]
                                     riem     = [    m       ]
                                         3, 2   [ 0  -  0  0 ]
                                                [    r       ]
                                                [            ]
                                                [ 0  0  0  0 ]

                                         [   m                      ]
                                         [ - -   0   0       0      ]
                                         [   r                      ]
                                         [                          ]
                                         [        m                 ]
                                         [  0   - -  0       0      ]
                              riem     = [        r                 ]
                                  3, 3   [                          ]
                                         [  0    0   0       0      ]
                                         [                          ]
                                         [              2 m - r     ]
                                         [  0    0   0  ------- + 1 ]
                                         [                 r        ]

                                              [ 0  0  0    0   ]
                                              [                ]
                                              [ 0  0  0    0   ]
                                              [                ]
                                   riem     = [            2 m ]
                                       3, 4   [ 0  0  0  - --- ]
                                              [             r  ]
                                              [                ]
                                              [ 0  0  0    0   ]

                                          [       0        0  0  0 ]
                                          [                        ]
                                          [       0        0  0  0 ]
                                          [                        ]
                               riem     = [       0        0  0  0 ]
                                   4, 1   [                        ]
                                          [      2                 ]
                                          [ m sin (theta)          ]
                                          [ -------------  0  0  0 ]
                                          [       r                ]

                                          [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]
                                          [                        ]
                               riem     = [ 0        0        0  0 ]
                                   4, 2   [                        ]
                                          [         2              ]
                                          [    m sin (theta)       ]
                                          [ 0  -------------  0  0 ]
                                          [          r             ]

                                        [ 0  0          0          0 ]
                                        [                            ]
                                        [ 0  0          0          0 ]
                                        [                            ]
                             riem     = [ 0  0          0          0 ]
                                 4, 3   [                            ]
                                        [                2           ]
                                        [         2 m sin (theta)    ]
                                        [ 0  0  - ---------------  0 ]
                                        [                r           ]

                           [        2                                             ]
                           [   m sin (theta)                                      ]
                           [ - -------------         0                0         0 ]
                           [         r                                            ]
                           [                                                      ]
                           [                         2                            ]
                           [                    m sin (theta)                     ]
                riem     = [        0         - -------------         0         0 ]
                    4, 4   [                          r                           ]
                           [                                                      ]
                           [                                          2           ]
                           [                                   2 m sin (theta)    ]
                           [        0                0         ---------------  0 ]
                           [                                          r           ]
                           [                                                      ]
                           [        0                0                0         0 ]

          (%o5)                                done

 -- Función: deleten (<L>, <n>)
     Devuelve una nueva lista consistente en <L> sin su <n>-ésimo
     elemento.

26.2.9 Variables utilizadas por 'ctensor'
-----------------------------------------

 -- Variable opcional: dim
     Valor por defecto: 4

     Es la dimensión de la variedad, que por defecto será 4.  La
     instrucción 'dim: n' establecerá la dimensión a cualquier otro
     valor 'n'.

 -- Variable opcional: diagmetric
     Valor por defecto: 'false'

     Si 'diagmetric' vale 'true' se utilizarán rutinas especiales para
     calcular todos los objetos geométricos teniendo en cuenta la
     diagonalidad de la métrica, lo que redundará en una reducción del
     tiempo de cálculo.  Esta opción se fija automáticamente por
     'csetup' si se especifica una métrica diagonal.

 -- Variable opcional: ctrgsimp

     Provoca que se realicen simplificaciones trigonométricas cuando se
     calculan tensores.  La variable 'ctrgsimp' afecta únicamente a
     aquellos cálculos que utilicen un sistema de referencia móvil.

 -- Variable opcional: cframe_flag

     Provoca que los cálculos se realicen respecto de un sistema de
     referencia móvil.

 -- Variable opcional: ctorsion_flag

     Obliga a que se calcule también el tensor de contorsión junto con
     los coeficientes de conexión.  El propio tensor de contorsión se
     calcula con la función 'contortion' a partir del tensor 'tr'
     suministrado por el usuario.

 -- Variable opcional: cnonmet_flag

     Obliga a que se calculen también los coeficientes de no metricidad
     junto con los coeficientes de conexión.  Los coeficientes de no
     metricidad se calculan con la función 'nonmetricity' a partir del
     vector de no metricidad'nm' suministrado por el usuario.

 -- Variable opcional: ctayswitch

     Si vale 'true', obliga a que ciertos cálculos de 'ctensor' se
     lleven a cabo utilizando desarrollos de series de Taylor.  Estos
     cálculos hacen referencia a las funciones 'christof', 'ricci',
     'uricci', 'einstein' y 'weyl'.

 -- Variable opcional: ctayvar

     Variable utilizada para desarrollos de Taylor cuando la variable
     'ctayswitch' vale 'true'.

 -- Variable opcional: ctaypov

     Máximo exponente utilizado en los desarrollos de Taylor cuando
     'ctayswitch' vale 'true'.

 -- Variable opcional: ctaypt

     Punto alrededor del cual se realiza un desarrollo de Taylor cuando
     'ctayswitch' vale 'true'.

 -- Variable opcional: gdet

     Es el determinante del tensor métrico 'lg', calculado por 'cmetric'
     cuando 'cframe_flag' vale 'false'.

 -- Variable opcional: ratchristof

     Obliga a que la función 'christof' aplique la simplificación
     racional.

 -- Variable opcional: rateinstein
     Valor por defecto: 'true'

     Si vale 'true' entonces se hará la simplificación racional en los
     componentes no nulos de los tensores de Einstein; si 'ratfac' vale
     'true' entonces las componentes también serán factorizadas.

 -- Variable opcional: ratriemann
     Valor por defecto: 'true'

     Es una de las variables que controlan la simplificación de los
     tensores de Riemann; si vale 'true', entonces se llevará a cabo la
     simplificación racional; si 'ratfac' vale 'true' entonces las
     componentes también serán factorizadas.

 -- Variable opcional: ratweyl
     Valor por defecto: 'true'

     Si vale 'true', entonces la función 'weyl' llevará a cabo la
     simplificación racional de los valores del tensor de Weyl.  si
     'ratfac' vale 'true' entonces las componentes también serán
     factorizadas.

 -- Variable: lfg
     Es la covariante de la métrica del sistema de referencia.  Por
     defecto, está inicializada al sistema de referencia
     tetradimensional de Lorentz con signatura (+,+,+,-).  Se utiliza
     cuando 'cframe_flag' vale 'true'.

 -- Variable: ufg
     Es la métrica del sistema de referencia inverso.  La calcula 'lfg'
     cuando 'cmetric' es invocada tomando 'cframe_flag' el valor 'true'.

 -- Variable: riem
     Es el tensor (3,1) de Riemann.  Se calcula cuando se invoca la
     función 'riemann'.  Para información sobre el indexado, véase la
     descripción de 'riemann'.

     Si 'cframe_flag' vale 'true', 'riem' se calcula a partir del tensor
     covariante de Riemann 'lriem'.

 -- Variable: lriem

     Es el tensor covariante de Riemann.  Lo calcula la función
     'lriemann'.

 -- Variable: uriem

     Es el tensor contravariante de Riemann.  Lo calcula la función
     'uriemann'.

 -- Variable: ric

     Es el tensor de Ricci.  Lo calcula la función 'ricci'.

 -- Variable: uric

     Es el tensor contravariante de Ricci.  Lo calcula la función
     'uricci'.

 -- Variable: lg

     Es el tensor métrico.  Este tensor se debe especificar (como matriz
     cuadrada de orden 'dim') antes de que se hagan otros cálculos.

 -- Variable: ug

     Es la inversa del tensor métrico.  Lo calcula la función 'cmetric'.

 -- Variable: weyl

     Es el tensor de Weyl.  Lo calcula la función 'weyl'.

 -- Variable: fb

     Son los coeficientes del sistema de referencia soporte, tal como
     los calcula 'frame_bracket'.

 -- Variable: kinvariant

     Es la invariante de Kretchmann, tal como la calcula la función
     'rinvariant'.

 -- Variable: np

     Es la cuaterna nula de Newman-Penrose, tal como la calcula la
     función 'nptetrad'.

 -- Variable: npi

     Es la cuaterna nula "raised-index Newman-Penrose".  Lo calcula la
     función 'nptetrad'.  Se define como 'ug.np'.  El producto
     'np.transpose(npi)' es constante:

          (%i39) trigsimp(np.transpose(npi));
                                        [  0   - 1  0  0 ]
                                        [                ]
                                        [ - 1   0   0  0 ]
          (%o39)                        [                ]
                                        [  0    0   0  1 ]
                                        [                ]
                                        [  0    0   1  0 ]

 -- Variable: tr

     Tensor de rango 3 suministrado por el usuario y que representa una
     torsión.  Lo utiliza la función 'contortion'.

 -- Variable: kt

     Es el tensor de contorsión, calculado a partir de 'tr' por la
     función 'contortion'.

 -- Variable: nm

     Vector de no metricidad suministrado por el usuario.  Lo utiliza la
     función 'nonmetricity'.

 -- Variable: nmc

     Son los coeficientes de no metricidad, calculados a partir de 'nm'
     por la función 'nonmetricity'.

 -- Variable del sistema: tensorkill

     Variable que indica si el paquete de tensores se ha inicializado.
     Utilizada por 'csetup' y reinicializada por 'init_ctensor'.

 -- Variable opcional: ct_coords
     Valor por defecto: '[]'

     La variable 'ct_coords' contiene una lista de coordenadas.  Aunque
     se define normalmente cuando se llama a la función 'csetup',
     también se pueden redefinir las coordenadas con la asignación
     'ct_coords: [j1, j2, ..., jn]' donde 'j' es el nuevo nombre de las
     coordenadas.  Véase también 'csetup'.

26.2.10 Nombres reservados
--------------------------

Los siguientes nombres se utilizan internamente en el paquete 'ctensor'
y no deberían redefinirse:

       Nombre       Descripción
       ---------------------------------------
       _lg()        Toma el valor lfg si se utiliza métrica del sistema de referencia,
                    lg en otro caso
       _ug()        Toma el valor ufg si se utiliza métrica del sistema de referencia,
                    ug en otro caso
       cleanup()    Elimina elementos de la lista deindex
       contract4()  Utilizada por psi()
       filemet()    Utilizada por csetup() cuando se lee la métrica desde un fichero
       findde1()    Utilizada por findde()
       findde2()    Utilizada por findde()
       findde3()    Utilizada por findde()
       kdelt()      Delta de Kronecker (no generalizada)
       newmet()     Utilizada por csetup() para establecer una métrica interactivamente
       setflags()   Utilizada por init_ctensor()
       readvalue()
       resimp()
       sermet()     Utilizada por csetup() para definir una métrica como serie de Taylor
       txyzsum()
       tmetric()    Métrica del sistema de referencia, utilizada por cmetric()
                    cuando cframe_flag:true
       triemann()   Tensor de Riemann en la base del sistema de referencia, se utiliza cuando
                    cframe_flag:true
       tricci()     Tensor de Ricci en la base del sistema de referencia, se utiliza cuando
                    cframe_flag:true
       trrc()       Coeficientes de rotación de Ricci, utilizada por christof()
       yesp()


File: maxima.info,  Node: atensor,  Next: Sumas productos y series,  Prev: ctensor,  Up: Top

27 atensor
**********

* Menu:

* Introducción a atensor::
* Funciones y variables para atensor::


File: maxima.info,  Node: Introducción a atensor,  Next: Funciones y variables para atensor,  Prev: atensor,  Up: atensor

27.1 Introducción a atensor
===========================

El paquete 'atensor' contiene funciones para la manipulación algebraica
de tensores.  Para hacer uso de 'atensor' es necesario cargarlo en
memoria haciendo 'load(atensor)', seguido de una llamada a la función
'init_atensor'.

La parte más importante de 'atensor' es una batería de reglas de
simplificación para el producto no conmutativo ("'.'").  El paquete
'atensor' reconoce algunos tipos de álgebras; las correspondientes
reglas de simplificación se activan tan pronto como se hace una llamada
a la función 'init_atensor'.

Las capacidades de 'atensor' se pueden demostrar definiendo el álgebra
de cuaterniones como un álgebra de Clifford Cl(0,2) con una base de dos
vectores.  Las tres unidades imaginarias son los dos vectores de la base
junto con su producto:

         i = v     j = v     k = v  . v
              1         2         1    2

Aunque el paquete 'atensor' incluye su propia definición para el álgebra
de cuaterniones, no se utiliza en el siguiente ejemplo, en el cual se
construye la tabla de multiplicación como una matriz:


     (%i1) load(atensor);
     (%o1)       /share/tensor/atensor.mac
     (%i2) init_atensor(clifford,0,0,2);
     (%o2)                                done
     (%i3) atensimp(v[1].v[1]);
     (%o3)                                 - 1
     (%i4) atensimp((v[1].v[2]).(v[1].v[2]));
     (%o4)                                 - 1
     (%i5) q:zeromatrix(4,4);
                                     [ 0  0  0  0 ]
                                     [            ]
                                     [ 0  0  0  0 ]
     (%o5)                           [            ]
                                     [ 0  0  0  0 ]
                                     [            ]
                                     [ 0  0  0  0 ]
     (%i6) q[1,1]:1;
     (%o6)                                  1
     (%i7) for i thru adim do q[1,i+1]:q[i+1,1]:v[i];
     (%o7)                                done
     (%i8) q[1,4]:q[4,1]:v[1].v[2];
     (%o8)                               v  . v
                                          1    2
     (%i9) for i from 2 thru 4 do for j from 2 thru 4 do
           q[i,j]:atensimp(q[i,1].q[1,j]);
     (%o9)                                done
     (%i10) q;
                        [    1        v         v      v  . v  ]
                        [              1         2      1    2 ]
                        [                                      ]
                        [   v         - 1     v  . v    - v    ]
                        [    1                 1    2      2   ]
     (%o10)             [                                      ]
                        [   v      - v  . v     - 1      v     ]
                        [    2        1    2              1    ]
                        [                                      ]
                        [ v  . v      v        - v       - 1   ]
                        [  1    2      2          1            ]

El paquete 'atensor' reconoce como vectores de la base símbolos
indexados, donde el símbolo es el almacenado en 'asymbol' y el índice va
desde 1 hasta 'adim'.  Para símbolos indexados, y sólo para ellos, se
evalúan las formas bilineales 'sf', 'af' y 'av'.  La evaluación
sustituye el valor de 'aform[i,j]' en lugar de 'fun(v[i],v[j])', donde
'v' representa el valor de 'asymbol' y 'fun' es 'af' o 'sf'; o sustituye
'v[aform[i,j]]' en lugar de 'av(v[i],v[j])'.

Huelga decir que las funciones 'sf', 'af' y 'av' pueden volver a
definirse.

Cuando se carga el paquete 'atensor' se hacen las siguientes
asignaciones de variables:

     dotscrules:true;
     dotdistrib:true;
     dotexptsimp:false;

Si se quiere experimentar con una álgebra no asociativa, también se
puede igualar la variable 'dotassoc' a 'false'.  En tal caso, sin
embargo, 'atensimp' no será siempre capaz de realizar las
simplificaciones deseadas.


File: maxima.info,  Node: Funciones y variables para atensor,  Prev: Introducción a atensor,  Up: atensor

27.2 Funciones y variables para atensor
=======================================

 -- Función: init_atensor (<alg_type>, <opt_dims>)
 -- Función: init_atensor (<alg_type>)

     Inicializa el paquete 'atensor' con el tipo de álgebra
     especificado, <alg_type>, que puede ser una de las siguientes:

     'universal': El álgebra universal no tiene reglas de conmutación.

     'grassmann': El álgebra de Grassman se define mediante la relación
     de conmutación 'u.v+v.u=0'.

     'clifford': El álgebra de Clifford se define mediante la regla de
     conmutación 'u.v+v.u=-2*sf(u,v)' donde 'sf' es una función escalar
     simétrica.  Para esta álgebra, <opt_dims> puede contener hasta tres
     enteros no negativos, que representan el número de dimensiones
     positivas, degeneradas y negativas, respectivamente, de esta
     álgebra.  Si se suministran los valores de <opt_dims>, 'atensor'
     configurará los valores de 'adim' y 'aform' de forma apropiada.  En
     otro caso, 'adim' tomará por defecto el valor 0 y 'aform' no se
     definirá.

     'symmetric': El álgebra simétrica se define mediante la regla de
     conmutación 'u.v-v.u=0'.

     'symplectic': El álgebra simpléctica se define mediante la regla de
     conmutación 'u.v-v.u=2*af(u,v)', donde 'af' es una función escalar
     antisimétrica.  Para el álgebra simpléctica, <opt_dims> puede
     contener hasta dos enteros no negativos, que representan las
     dimensiones no degeneradas y degeneradas, respectivamente.  Si se
     suministran los valores de <opt_dims>, 'atensor' configurará los
     valores de 'adim' y 'aform' de forma apropiada.  En otro caso,
     'adim' tomará por defecto el valor 0 y 'aform' no se definirá.

     'lie_envelop': El álgebra de la envolvente de Lie se define
     mediante la regla de conmutación 'u.v-v.u=2*av(u,v)', donde 'av' es
     una función antisimétrica.

     La función 'init_atensor' también reconoce algunos tipos de
     álgebras predefinidas:

     'complex' implementa el álgebra de números complejos como un
     álgebra de Clifford Cl(0,1).  La llamada 'init_atensor(complex)'
     equivale a 'init_atensor(clifford,0,0,1)'.

     'quaternion' implementa el álgebra de cuaterniones.  La llamada
     'init_atensor(quaternion)' equivale a
     'init_atensor(clifford,0,0,2)'.

     'pauli' implementa el álgebra de Pauli como un álgebra de Clifford
     Cl(3,0).  La llamada 'init_atensor(pauli)' equivale a
     'init_atensor(clifford,3)'.

     'dirac' implementa el álgebra de Dirac como un álgebra de Clifford
     Cl(3,1).  La llamada 'init_atensor(dirac)' equivale a
     'init_atensor(clifford,3,0,1)'.

 -- Función: atensimp (<expr>)

     Simplifica la expresión algebraica de un tensor <expr> de acuerdo
     con las reglas configuradas mediante una llamada a 'init_atensor'.
     La simplificación incluye la aplicación recursiva de las reglas de
     conmutación y llamadas a 'sf', 'af' y 'av' siempre que sea posible.
     Se utiliza un algoritmo que asegure que la función termina siempre,
     incluso en el caso de expresiones complejas.

 -- Función: alg_type

     Tipo de álgebra.  Valores válidos son 'universal', 'grassmann',
     'clifford', 'symmetric', 'symplectic' y 'lie_envelop'.

 -- Variable: adim
     Valor por defecto: 0

     La dimensión del álgebra.  El paquete 'atensor' utiliza el valor de
     'adim' para determinar si un objeto indexado es un vector válido
     para la base.  Véase 'abasep'.

 -- Variable: aform
     Valor por defecto: 'ident(3)'

     Valores por defecto para las formas bilineales 'sf', 'af' y 'av'.
     El valor por defecto es la matriz identidad 'ident(3)'.

 -- Variable: asymbol
     Valor por defecto: 'v'

     Símbolo para los vectores base.

 -- Función: sf (<u>, <v>)

     Una función escalar simétrica que se utiliza en relaciones de
     conmutación.  La implementación por defecto analiza si los dos
     argumentos son vectores base mediante 'abasep' y en tal caso
     sustituye el valor correspondiente de la matriz 'aform'.

 -- Función: af (<u>, <v>)

     Una función escalar antisimétrica que se utiliza en relaciones de
     conmutación.  La implementación por defecto analiza si los dos
     argumentos son vectores base mediante 'abasep' y en tal caso
     sustituye el valor correspondiente de la matriz 'aform'.

 -- Función: av (<u>, <v>)

     Una función antisimétrica que se utiliza en relaciones de
     conmutación.  La implementación por defecto analiza si los dos
     argumentos son vectores base mediante 'abasep' y en tal caso
     sustituye el valor correspondiente de la matriz 'aform'.

     Ejemplo:

          (%i1) load(atensor);
          (%o1)       /share/tensor/atensor.mac
          (%i2) adim:3;
          (%o2)                                  3
          (%i3) aform:matrix([0,3,-2],[-3,0,1],[2,-1,0]);
                                         [  0    3   - 2 ]
                                         [               ]
          (%o3)                          [ - 3   0    1  ]
                                         [               ]
                                         [  2   - 1   0  ]
          (%i4) asymbol:x;
          (%o4)                                  x
          (%i5) av(x[1],x[2]);
          (%o5)                                 x
                                                 3

 -- Función: abasep (<v>)

     Analiza si su argumento es un vector base en 'atensor'.  Esto es,
     si se trata de un símbolo indexado, siendo el símbolo el mismo que
     el valor de 'asymbol' y si el índice tiene un valor numérico entre
     1 y 'adim'.


File: maxima.info,  Node: Sumas productos y series,  Next: Teoría de Números,  Prev: atensor,  Up: Top

28 Sumas productos y series
***************************

* Menu:

* Funciones y variables para sumas y productos::
* Introducción a las series::
* Funciones y variables para las series::
* Introducción a las series de Fourier::
* Funciones y variables para series de Fourier::
* Funciones y variables para series de Poisson::


File: maxima.info,  Node: Funciones y variables para sumas y productos,  Next: Introducción a las series,  Prev: Sumas productos y series,  Up: Sumas productos y series

28.1 Funciones y variables para sumas y productos
=================================================

 -- Función: bashindices (<expr>)
     Transforma la expresión <expr> dándole a cada sumatorio y producto
     un único índice.  Esto le da a 'changevar' mayor precisión cuando
     opera con sumas y productos.  La forma del único índice es
     'j<number>'.  La cantidad <number> se determina en función de
     'gensumnum', valor que puede cambiar el usuario.  Por ejemplo,
     haciendo 'gensumnum:0$'.

 -- Función: lsum (<expr>, <x>, <L>)
     Representa la suma de <expr> para cada elemento <x> en <L>.

     Se retornará la forma nominal ''lsum' si el argumento <L> no es una
     lista.

     Ejemplos:

          (%i1) lsum (x^i, i, [1, 2, 7]);
                                      7    2
          (%o1)                      x  + x  + x
          (%i2) lsum (i^2, i, rootsof (x^3 - 1, x));
                               ====
                               \      2
          (%o2)                 >    i
                               /
                               ====
                                             3
                               i in rootsof(x  - 1, x)

 -- Función: intosum (<expr>)
     Mueve los factores multiplicativos que están fuera de un sumatorio
     hacia dentro de éste.  Si el índice del sumatorio aparece en la
     expresión exterior, entonces 'intosum' busca un índice razonable,
     lo mismo que hace con 'sumcontract'.  Se trata de la operación
     contraria a extraer factores comunes de los sumatorios.

     En algunos caos puede ser necesario hacer 'scanmap (multthru,
     <expr>)' antes que 'intosum'.

     Ejemplo:

          (%i1) sum(2*x^2*n^k, k , 0, inf);
                                         inf
                                         ====
                                       2 \      k
          (%o1)                     2 x   >    n
                                         /
                                         ====
                                         k = 0
          (%i2) intosum(%);
                                    inf
                                    ====
                                    \        k  2
          (%o2)                      >    2 n  x
                                    /
                                    ====
                                    k = 0

 -- Función: product (<expr>, <i>, <i_0>, <i_1>)
     Representa el producto de los valores de 'expr' según el índice <i>
     varía de <i_0> hasta <i_1>.  La forma nominal ''product' se
     presenta en forma de letra pi mayúscula.

     La función 'product' evalúa <expr> y los límites inferior y
     superior, <i_0> y <i_1>, pero no evalúa el índice <i>.

     Si la diferencia entre los límites superior e inferior es un número
     entero, la expresión <expr> se evalúa para cada valor del índice
     <i>, siendo el resultado un producto en forma explícita.

     En caso contrario, el rango del índice no está definido,
     aplicándose entonces algunas reglas que permitan simplificar el
     producto.  Cuando la variable global 'simpproduct' valga 'true', se
     aplicarán reglas adicionales.  En ciertos casos, la simplificación
     dará lugar a un resultado que ya no tenga el formato del producto;
     en caso contrario se devolverá una forma nominal ''product'.

     Véanse también 'nouns' y 'evflag'.

     Ejemplos:

          (%i1) product (x + i*(i+1)/2, i, 1, 4);
          (%o1)           (x + 1) (x + 3) (x + 6) (x + 10)
          (%i2) product (i^2, i, 1, 7);
          (%o2)                       25401600
          (%i3) product (a[i], i, 1, 7);
          (%o3)                 a  a  a  a  a  a  a
                                 1  2  3  4  5  6  7
          (%i4) product (a(i), i, 1, 7);
          (%o4)          a(1) a(2) a(3) a(4) a(5) a(6) a(7)
          (%i5) product (a(i), i, 1, n);
                                       n
                                     /===\
                                      ! !
          (%o5)                       ! !  a(i)
                                      ! !
                                     i = 1
          (%i6) product (k, k, 1, n);
                                         n
                                       /===\
                                        ! !
          (%o6)                         ! !  k
                                        ! !
                                       k = 1
          (%i7) product (k, k, 1, n), simpproduct;
          (%o7)                          n!
          (%i8) product (integrate (x^k, x, 0, 1), k, 1, n);
                                       n
                                     /===\
                                      ! !    1
          (%o8)                       ! !  -----
                                      ! !  k + 1
                                     k = 1
          (%i9) product (if k <= 5 then a^k else b^k, k, 1, 10);
                                        15  40
          (%o9)                        a   b

 -- Variable opcional: simpsum
     Valor por defecto: 'false'

     Si 'simpsum' vale 'true', se simplifica el resultado de un
     sumatorio 'sum'.  Esta simplificación podrá producir en ocasiones
     una expresión compacta.  Si 'simpsum' vale 'false' o si se utiliza
     la forma apostrofada ''sum', el valor es una forma nominal que
     representa la notación sigma habitual en matemáticas.

 -- Función: sum (<expr>, <i>, <i_0>, <i_1>)

     Representa la suma de los valores de 'expr' según el índice <i>
     varía de <i_0> hasta <i_1>.  La forma nominal ''sum' se presenta en
     forma de letra sigma mayúscula.

     La función 'sum' evalúa su sumando <expr> y los límites inferior y
     superior, <i_0> y <i_1>, pero no evalúa el índice <i>.

     Si la diferencia entre los límites superior e inferior es un número
     entero, el sumando <expr> se evalúa para cada valor del índice <i>,
     siendo el resultado una suma en forma explícita.

     En caso contrario, el rango del índice no está definido,
     aplicándose entonces algunas reglas que permitan simplificar la
     suma.  Cuando la variable global 'simpsum' valga 'true', se
     aplicarán reglas adicionales.  En ciertos casos, la simplificación
     dará lugar a un resultado que ya no tenga el formato del sumatorio;
     en caso contrario se devolverá una forma nominal ''product'.

     Cuando 'cauchysum' vale 'true', el producto de sumatorios se
     expresa como un producto de Cauchy, en cuyo caso el índice del
     sumatorio interior es función del índice del exterior, en lugar de
     variar independientemente.

     La variable global 'genindex' guarda el prefijo alfabético a
     utilizar cuando sea necesario generar automáticamente el siguiente
     índice de sumatorio.

     La variable global 'gensumnum' guarda el sufijo numérico a utilizar
     cuando sea necesario generar automáticamente el siguiente índice de
     sumatorio.  Si 'gensumnum' vale 'false', un índice generado
     automáticamente constará sólo de 'genindex', sin sufijo numérico.

     Véanse también 'sumcontract', 'intosum', 'bashindices',
     'niceindices', 'nouns' y 'evflag'.

     Ejemplos:

          (%i1) sum (i^2, i, 1, 7);
          (%o1)                          140
          (%i2) sum (a[i], i, 1, 7);
          (%o2)           a  + a  + a  + a  + a  + a  + a
                           7    6    5    4    3    2    1
          (%i3) sum (a(i), i, 1, 7);
          (%o3)    a(7) + a(6) + a(5) + a(4) + a(3) + a(2) + a(1)
          (%i4) sum (a(i), i, 1, n);
                                      n
                                     ====
                                     \
          (%o4)                       >    a(i)
                                     /
                                     ====
                                     i = 1
          (%i5) sum (2^i + i^2, i, 0, n);
                                    n
                                   ====
                                   \       i    2
          (%o5)                     >    (2  + i )
                                   /
                                   ====
                                   i = 0
          (%i6) sum (2^i + i^2, i, 0, n), simpsum;
                                        3      2
                             n + 1   2 n  + 3 n  + n
          (%o6)             2      + --------------- - 1
                                            6
          (%i7) sum (1/3^i, i, 1, inf);
                                      inf
                                      ====
                                      \     1
          (%o7)                        >    --
                                      /      i
                                      ====  3
                                      i = 1
          (%i8) sum (1/3^i, i, 1, inf), simpsum;
                                          1
          (%o8)                           -
                                          2
          (%i9) sum (i^2, i, 1, 4) * sum (1/i^2, i, 1, inf);
                                        inf
                                        ====
                                        \     1
          (%o9)                      30  >    --
                                        /      2
                                        ====  i
                                        i = 1
          (%i10) sum (i^2, i, 1, 4) * sum (1/i^2, i, 1, inf), simpsum;
                                            2
          (%o10)                       5 %pi
          (%i11) sum (integrate (x^k, x, 0, 1), k, 1, n);
                                      n
                                     ====
                                     \       1
          (%o11)                      >    -----
                                     /     k + 1
                                     ====
                                     k = 1
          (%i12) sum (if k <= 5 then a^k else b^k, k, 1, 10));
                    10    9    8    7    6    5    4    3    2
          (%o12)   b   + b  + b  + b  + b  + a  + a  + a  + a  + a

 -- Función: sumcontract (<expr>)
     Combina todos los sumatorios de una suma cuyos límites inferiores y
     superiores difieren por constantes.  El resultado es una expresión
     que contiene un sumatorio por cada conjunto de tales sumatorios,
     más todos los demás términos adicionales que tuvieron que extraerse
     para formar la suma.  La función 'sumcontract' combina todos los
     sumatorios compatibles y utiliza uno de los índices de uno de los
     sumatorios si puede, si no formará un índice que sea razonable.

     Puede ser necesario hacer 'intosum (<expr>)' antes que
     'sumcontract'.

     Ejemplo:

          (%i1) 'sum(1/l,l,1,n)+'sum(k,k,1,n+2);
                                   n        n + 2
                                  ====      ====
                                  \     1   \
          (%o1)                    >    - +  >    k
                                  /     l   /
                                  ====      ====
                                  l = 1     k = 1
          (%i2) sumcontract(%);
                                      n
                                     ====
                                     \          1
          (%o2)                2 n +  >    (l + -) + 3
                                     /          l
                                     ====
                                     l = 1

 -- Variable opcional: sumexpand
     Valor por defecto: 'false'

     Si 'sumexpand' vale 'true', productos de sumatorios y de sumatorios
     con exponentes se reducen a sumatorios anidados.

     Véase también 'cauchysum'.

     Ejemplos:

          (%i1) sumexpand: true$
          (%i2) sum (f (i), i, 0, m) * sum (g (j), j, 0, n);
                               m      n
                              ====   ====
                              \      \
          (%o2)                >      >     f(i1) g(i2)
                              /      /
                              ====   ====
                              i1 = 0 i2 = 0
          (%i3) sum (f (i), i, 0, m)^2;
                               m      m
                              ====   ====
                              \      \
          (%o3)                >      >     f(i3) f(i4)
                              /      /
                              ====   ====
                              i3 = 0 i4 = 0


File: maxima.info,  Node: Introducción a las series,  Next: Funciones y variables para las series,  Prev: Funciones y variables para sumas y productos,  Up: Sumas productos y series

28.2 Introducción a las series
==============================

Maxima dispone de las funciones 'taylor' y 'powerseries' para calcular
las series de las funciones diferenciables.  También tiene herramientas
como 'nusum' capaces de encontrar la expresión compacta de algunas
series.  Operaciones como la suma y la multiplicación operan de la forma
habitual en el contexto de las series.  Esta sección presenta las
variables globales que controlan la expansión.


File: maxima.info,  Node: Funciones y variables para las series,  Next: Introducción a las series de Fourier,  Prev: Introducción a las series,  Up: Sumas productos y series

28.3 Funciones y variables para las series
==========================================

 -- Variable opcional: cauchysum
     Valor por defecto: 'false'

     Cuando se multiplican sumatorios infinitos, si 'sumexpand' vale
     'true' y 'cauchysum' vale 'true', entonces se utilizará el producto
     de Cauchy en lugar del usual.  En el producto de Cauchy el índice
     de la suma interna es función del índice de la exterior en lugar de
     variar de forma independiente.  Un ejemplo aclara esta idea:

          (%i1) sumexpand: false$
          (%i2) cauchysum: false$
          (%i3) s: sum (f(i), i, 0, inf) * sum (g(j), j, 0, inf);
                                inf         inf
                                ====        ====
                                \           \
          (%o3)                ( >    f(i))  >    g(j)
                                /           /
                                ====        ====
                                i = 0       j = 0
          (%i4) sumexpand: true$
          (%i5) cauchysum: true$
          (%i6) ''s;
                           inf     i1
                           ====   ====
                           \      \
          (%o6)             >      >     g(i1 - i2) f(i2)
                           /      /
                           ====   ====
                           i1 = 0 i2 = 0

 -- Función: deftaylor (<f_1>(<x_1>), <expr_1>, ..., <f_n>(<x_n>),
          <expr_n>)
     Para cada función <f_i> de variable <x_i>, 'deftaylor' define
     <expr_i> como una serie de Taylor alrededor de cero.  La expresión
     <expr_i> será un polinomio en <x_i> o una suma; 'deftaylor' admite
     también expresiones más generales.

     La llamada 'powerseries (<f_i>(<x_i>), <x_i>, 0)' devuelve la serie
     definida por 'deftaylor'.

     La función 'deftaylor' evalúa sus argumentos y devuelve la lista de
     las funciones <f_1>, ..., <f_n>.

     Ejemplo:

          (%i1) deftaylor (f(x), x^2 + sum(x^i/(2^i*i!^2), i, 4, inf));
          (%o1)                          [f]
          (%i2) powerseries (f(x), x, 0);
                                inf
                                ====      i1
                                \        x         2
          (%o2)                  >     -------- + x
                                /       i1    2
                                ====   2   i1!
                                i1 = 4
          (%i3) taylor (exp (sqrt (f(x))), x, 0, 4);
                                2         3          4
                               x    3073 x    12817 x
          (%o3)/T/     1 + x + -- + ------- + -------- + . . .
                               2     18432     307200

 -- Variable opcional: maxtayorder
     Valor por defecto: 'true'

     Si 'maxtayorder' vale 'true', entonces durante la manipulación
     algebraica de series truncadas de Taylor, la función 'taylor' trata
     de retener tantos términos correctos como sea posible.

 -- Función: niceindices (<expr>)
     Cambia las etiquetas de los índices de sumas y productos de <expr>.
     La función 'niceindices' trata de cambiar cada índice al valor de
     'niceindicespref[1]', a menos que esa etiqueta aparezca ya en el
     sumando o factor, en cuyo caso 'niceindices' realiza intentos con
     los siguientes elementos de 'niceindicespref', hasta que encuentre
     una variable que que no esté en uso.  Si todas las variables de la
     lista han sido ya revisadas, se formarán nuevos ínices añadiendo
     números enteros al valor de 'niceindicespref[1]', como 'i0', 'i1',
     'i2', ....

     La función 'niceindices' evalúa sus argumentos y devuelve una
     expresión.

     Ejemplo:

          (%i1) niceindicespref;
          (%o1)                  [i, j, k, l, m, n]
          (%i2) product (sum (f (foo + i*j*bar), foo, 1, inf), bar, 1, inf);
                           inf    inf
                          /===\   ====
                           ! !    \
          (%o2)            ! !     >      f(bar i j + foo)
                           ! !    /
                          bar = 1 ====
                                  foo = 1
          (%i3) niceindices (%);
                               inf  inf
                              /===\ ====
                               ! !  \
          (%o3)                ! !   >    f(i j l + k)
                               ! !  /
                              l = 1 ====
                                    k = 1

 -- Variable opcional: niceindicespref
     Valor por defecto: '[i, j, k, l, m, n]'

     La variable 'niceindicespref' es la lista de la que la función
     'niceindices' va tomando nombres de etiquetas para índices de
     sumatorios y productos.

     En 'niceindicespref' se guardan normalmente nombres de variables.

     Ejemplo:

          (%i1) niceindicespref: [p, q, r, s, t, u]$
          (%i2) product (sum (f (foo + i*j*bar), foo, 1, inf), bar, 1, inf);
                           inf    inf
                          /===\   ====
                           ! !    \
          (%o2)            ! !     >      f(bar i j + foo)
                           ! !    /
                          bar = 1 ====
                                  foo = 1
          (%i3) niceindices (%);
                               inf  inf
                              /===\ ====
                               ! !  \
          (%o3)                ! !   >    f(i j q + p)
                               ! !  /
                              q = 1 ====
                                    p = 1

 -- Función: nusum (<expr>, <x>, <i_0>, <i_1>)
     Calcula la suma hipergeométrica indefinida de <expr> con respecto a
     la variable <x> utilizando una procedimiento de decisión debido a
     R.W. Gosper.  La expresión <expr> y el resultado deben poder ser
     escritos como productos de potencias enteras, factoriales,
     coeficientes binomiales y funciones racionales.

     Los términos suma "definida" e "indefinida" se usan de forma
     análoga a integración "definida" e "indefinida".  La suma
     indefinida significa dar un resultado simbólico.

     Las funciones 'nusum' y 'unsum' disponen de cierta información
     sobre sumas y diferencias de productos finitos.  Véase también
     'unsum'.

     Ejemplos:

          (%i1) nusum (n*n!, n, 0, n);

          Dependent equations eliminated:  (1)
          (%o1)                     (n + 1)! - 1
          (%i2) nusum (n^4*4^n/binomial(2*n,n), n, 0, n);
                               4        3       2              n
                2 (n + 1) (63 n  + 112 n  + 18 n  - 22 n + 3) 4      2
          (%o2) ------------------------------------------------ - ------
                              693 binomial(2 n, n)                 3 11 7
          (%i3) unsum (%, n);
                                        4  n
                                       n  4
          (%o3)                   ----------------
                                  binomial(2 n, n)
          (%i4) unsum (prod (i^2, i, 1, n), n);
                              n - 1
                              /===\
                               ! !   2
          (%o4)              ( ! !  i ) (n - 1) (n + 1)
                               ! !
                              i = 1
          (%i5) nusum (%, n, 1, n);

          Dependent equations eliminated:  (2 3)
                                      n
                                    /===\
                                     ! !   2
          (%o5)                      ! !  i  - 1
                                     ! !
                                    i = 1

 -- Función: pade (<taylor_series>, <numer_deg_bound>,
          <denom_deg_bound>)
     Devuelve la lista de todas las funciones racionales que tienen el
     desarrollo de Taylor dado, en las que la suma de los grados del
     numerador y denominador es menor o igual que el nivel de
     truncamiento de la serie de potencias.

     La expresión <taylor_series> es una serie de Taylor univariante.
     Los argumentos <numer_deg_bound> y <denom_deg_bound> son enteros
     positivos que indican las cotas para numerador y denominador.

     La expresión <taylor_series> también puede ser una serie de
     Laurent, y las cotas de los grados pueden ser 'inf'.  El grado
     total se define como '<numer_deg_bound> + <denom_deg_bound>'.  La
     longitud de una serie de potencias se define como '"truncation
     level" + 1 - min(0, "order of series")'.

          (%i1) taylor (1 + x + x^2 + x^3, x, 0, 3);
                                        2    3
          (%o1)/T/             1 + x + x  + x  + . . .
          (%i2) pade (%, 1, 1);
                                           1
          (%o2)                       [- -----]
                                         x - 1
          (%i3) t: taylor(-(83787*x^10 - 45552*x^9 - 187296*x^8
                             + 387072*x^7 + 86016*x^6 - 1507328*x^5
                             + 1966080*x^4 + 4194304*x^3 - 25165824*x^2
                             + 67108864*x - 134217728)
                 /134217728, x, 0, 10);
                              2    3       4       5       6        7
                       x   3 x    x    15 x    23 x    21 x    189 x
          (%o3)/T/ 1 - - + ---- - -- - ----- + ----- - ----- - ------
                       2    16    32   1024    2048    32768   65536

                                            8         9          10
                                      5853 x    2847 x    83787 x
                                    + ------- + ------- - --------- + . . .
                                      4194304   8388608   134217728
          (%i4) pade (t, 4, 4);
          (%o4)                          []

     No hay ninguna función racional de grado 4 en numerador y
     denominador con este desarrollo en serie de potencias.  Es
     necesario dar un número de grados al numerador y denominador cuya
     suma sea al menos el grado del desarrollo de la serie, a fin de
     disponer de un número suficiente de coeficientes desconocidos para
     calcular.

          (%i5) pade (t, 5, 5);
                               5                4                 3
          (%o5) [- (520256329 x  - 96719020632 x  - 489651410240 x

                            2
           - 1619100813312 x  - 2176885157888 x - 2386516803584)

                         5                 4                  3
          /(47041365435 x  + 381702613848 x  + 1360678489152 x

                            2
           + 2856700692480 x  + 3370143559680 x + 2386516803584)]

 -- Función: powerseries (<expr>, <x>, <a>)
     Devuelve la forma general del desarrollo en serie de potencias de
     <expr> para la variable <x> alrededor del punto <a> (que puede ser
     'inf', de infinito):
                     inf
                     ====
                     \               n
                      >    b  (x - a)
                     /      n
                     ====
                     n = 0

     Si 'powerseries' no es capaz de desarrollar <expr>, la función
     'taylor' puede calcular los primeros términos de la serie.

     Si 'verbose' vale 'true', 'powerseries' va mostrando mensajes
     mientras progresa el cálculo.

          (%i1) verbose: true$
          (%i2) powerseries (log(sin(x)/x), x, 0);
          can't expand
                                           log(sin(x))
          so we'll try again after applying the rule:
                                                  d
                                                / -- (sin(x))
                                                [ dx
                                  log(sin(x)) = i ----------- dx
                                                ]   sin(x)
                                                /
          in the first simplification we have returned:
                                       /
                                       [
                                       i cot(x) dx - log(x)
                                       ]
                                       /
                              inf
                              ====        i1  2 i1             2 i1
                              \      (- 1)   2     bern(2 i1) x
                               >     ------------------------------
                              /                i1 (2 i1)!
                              ====
                              i1 = 1
          (%o2)                -------------------------------------
                                                2

 -- Variable opcional: psexpand
     Valor por defecto: 'false'

     Si 'psexpand' vale 'true', toda expresi'on racional se muestra
     completamente expandida.  La variable 'ratexpand' tiene el mismo
     efecto.

     Si 'psexpand' vale 'false', las expresines multivariantes se
     presentan tal como lo hace el paquete de funciones racionales.

     Si 'psexpand' vale 'multi', los términos de igual grado son
     agrupados.

 -- Función: revert (<expr>, <x>)
 -- Función: revert2 (<expr>, <x>, <n>)

     Estas funciones devuelven el recíproco de <expr> en forma de
     desarrollo de Taylor alrededor de cero respecto de la variable <x>.
     La función 'revert' devuelve un polinomio de grado igual a la mayor
     potencia en <expr>.  La función 'revert2' devuelve un polinomio de
     grado <n>, el cual puede ser mayor, igual o menor que el grado de
     <expr>.

     Para utilizar estas funciones es necesario cargarlas en memoria
     mediante 'load ("revert")'.

     Ejemplos:

          (%i1) load ("revert")$
          (%i2) t: taylor (exp(x) - 1, x, 0, 6);
                             2    3    4    5     6
                            x    x    x    x     x
          (%o2)/T/      x + -- + -- + -- + --- + --- + . . .
                            2    6    24   120   720
          (%i3) revert (t, x);
                         6       5       4       3       2
                     10 x  - 12 x  + 15 x  - 20 x  + 30 x  - 60 x
          (%o3)/R/ - --------------------------------------------
                                          60
          (%i4) ratexpand (%);
                               6    5    4    3    2
                              x    x    x    x    x
          (%o4)             - -- + -- - -- + -- - -- + x
                              6    5    4    3    2
          (%i5) taylor (log(x+1), x, 0, 6);
                              2    3    4    5    6
                             x    x    x    x    x
          (%o5)/T/       x - -- + -- - -- + -- - -- + . . .
                             2    3    4    5    6
          (%i6) ratsimp (revert (t, x) - taylor (log(x+1), x, 0, 6));
          (%o6)                           0
          (%i7) revert2 (t, x, 4);
                                    4    3    2
                                   x    x    x
          (%o7)                  - -- + -- - -- + x
                                   4    3    2

 -- Función: taylor (<expr>, <x>, <a>, <n>)
 -- Función: taylor (<expr>, [<x_1>, <x_2>, ...], <a>, <n>)
 -- Función: taylor (<expr>, [<x>, <a>, <n>, 'asymp])
 -- Función: taylor (<expr>, [<x_1>, <x_2>, ...], [<a_1>, <a_2>, ...],
          [<n_1>, <n_2>, ...])
 -- Función: taylor (<expr>, [<x_1>, <a_1>, <n_1>], [<x_2>, <a_2>,
          <n_2>], ...)

     La llamada 'taylor (<expr>, <x>, <a>, <n>)' expande la expresión
     <expr> en un desarrollo de Taylor o de Laurent respecto de la
     variable <x> alrededor del punto <a>, con términos hasta '(<x> -
     <a>)^<n>'.

     Si <expr> es de la forma '<f>(<x>)/<g>(<x>)' y '<g>(<x>)' no tiene
     términos hasta de grado <n>, entonces 'taylor' intenta expandir
     '<g>(<x>)' hasta el grado '2 <n>'.  Si aún así no hay términos no
     nulos, 'taylor' dobla el grado de la expansión de '<g>(<x>)' hasta
     que el grado de la expansión sea menor o igual que '<n>
     2^taylordepth'.

     La llamada 'taylor (<expr>, [<x_1>, <x_2>, ...], <a>, <n>)'
     devuelve la serie en potencias truncada de grado <n> en todas las
     variables <x_1>, <x_2>, ...  alrededor del punto '(<a>, <a>, ...)'.

     La llamada 'taylor (<expr>, [<x_1>, <a_1>, <n_1>], [<x_2>, <a_2>,
     <n_2>], ...)' devuelve la serie en potencias truncada en las
     variables <x_1>, <x_2>, ...  alrededor del punto '(<a_1>, <a_2>,
     ...)'; el truncamiento se realiza, respectivamente, en los grados
     <n_1>, <n_2>, ....

     La llamada 'taylor (<expr>, [<x_1>, <x_2>, ...], [<a_1>, <a_2>,
     ...], [<n_1>, <n_2>, ...])' devuelve la serie en potencias truncada
     en las variables <x_1>, <x_2>, ...  alrededor del punto '(<a_1>,
     <a_2>, ...)', el truncamiento se realiza, respectivamente, en los
     grados <n_1>, <n_2>, ....

     La llamada 'taylor (<expr>, [<x>, <a>, <n>, 'asymp])' devuelve el
     desarrollo de <expr> en potencias negativas de '<x> - <a>'.  El
     término de mayor orden es '(<x> - <a>)^<-n>'.

     Si 'maxtayorder' vale 'true', entonces durante la manipulación
     algebraica de las series (truncadas) de Taylor, la función 'taylor'
     intenta mantener tantos términos correctos como sea posible.

     Si 'psexpand' vale 'true', una expresión racional desarrollada se
     muestra completamente expandida.  La variable 'ratexpand' tiene el
     mismo efecto.  Si 'psexpand' vale 'false', una expresión
     multivariante se mostrará tal como lo hace el paquete de funciones
     racionales.  Si 'psexpand' vale 'multi', los términos del mismo
     grado son agrupados.

     Véase también la variable 'taylor_logexpand' para el control del
     desarrollo.

     Ejemplos:

          (%i1) taylor (sqrt (sin(x) + a*x + 1), x, 0, 3);
                                     2             2
                       (a + 1) x   (a  + 2 a + 1) x
          (%o1)/T/ 1 + --------- - -----------------
                           2               8

                                             3      2             3
                                         (3 a  + 9 a  + 9 a - 1) x
                                       + -------------------------- + . . .
                                                     48
          (%i2) %^2;
                                              3
                                             x
          (%o2)/T/           1 + (a + 1) x - -- + . . .
                                             6
          (%i3) taylor (sqrt (x + 1), x, 0, 5);
                                 2    3      4      5
                            x   x    x    5 x    7 x
          (%o3)/T/      1 + - - -- + -- - ---- + ---- + . . .
                            2   8    16   128    256
          (%i4) %^2;
          (%o4)/T/                  1 + x + . . .
          (%i5) product ((1 + x^i)^2.5, i, 1, inf)/(1 + x^2);
                                   inf
                                  /===\
                                   ! !    i     2.5
                                   ! !  (x  + 1)
                                   ! !
                                  i = 1
          (%o5)                   -----------------
                                        2
                                       x  + 1
          (%i6) ev (taylor(%, x,  0, 3), keepfloat);
                                         2           3
          (%o6)/T/    1 + 2.5 x + 3.375 x  + 6.5625 x  + . . .
          (%i7) taylor (1/log (x + 1), x, 0, 3);
                                         2       3
                           1   1   x    x    19 x
          (%o7)/T/         - + - - -- + -- - ----- + . . .
                           x   2   12   24    720
          (%i8) taylor (cos(x) - sec(x), x, 0, 5);
                                          4
                                     2   x
          (%o8)/T/                - x  - -- + . . .
                                         6
          (%i9) taylor ((cos(x) - sec(x))^3, x, 0, 5);
          (%o9)/T/                    0 + . . .
          (%i10) taylor (1/(cos(x) - sec(x))^3, x, 0, 5);
                                                         2          4
                      1     1       11      347    6767 x    15377 x
          (%o10)/T/ - -- + ---- + ------ - ----- - ------- - --------
                       6      4        2   15120   604800    7983360
                      x    2 x    120 x

                                                                    + . . .
          (%i11) taylor (sqrt (1 - k^2*sin(x)^2), x, 0, 6);
                         2  2       4      2   4
                        k  x    (3 k  - 4 k ) x
          (%o11)/T/ 1 - ----- - ----------------
                          2            24

                                              6       4       2   6
                                         (45 k  - 60 k  + 16 k ) x
                                       - -------------------------- + . . .
                                                    720
          (%i12) taylor ((x + 1)^n, x, 0, 4);
                                2       2     3      2         3
                              (n  - n) x    (n  - 3 n  + 2 n) x
          (%o12)/T/ 1 + n x + ----------- + --------------------
                                   2                 6

                                         4      3       2         4
                                       (n  - 6 n  + 11 n  - 6 n) x
                                     + ---------------------------- + . . .
                                                    24
          (%i13) taylor (sin (y + x), x, 0, 3, y, 0, 3);
                         3                 2
                        y                 y
          (%o13)/T/ y - -- + . . . + (1 - -- + . . .) x
                        6                 2

                              3                       2
                         y   y            2      1   y            3
                    + (- - + -- + . . .) x  + (- - + -- + . . .) x  + . . .
                         2   12                  6   12
          (%i14) taylor (sin (y + x), [x, y], 0, 3);
                               3        2      2      3
                              x  + 3 y x  + 3 y  x + y
          (%o14)/T/   y + x - ------------------------- + . . .
                                          6
          (%i15) taylor (1/sin (y + x), x, 0, 3, y, 0, 3);
                    1   y              1    1               1            2
          (%o15)/T/ - + - + . . . + (- -- + - + . . .) x + (-- + . . .) x
                    y   6               2   6                3
                                       y                    y

                                                     1            3
                                                + (- -- + . . .) x  + . . .
                                                      4
                                                     y
          (%i16) taylor (1/sin (y + x), [x, y], 0, 3);
                                       3         2       2        3
                      1     x + y   7 x  + 21 y x  + 21 y  x + 7 y
          (%o16)/T/ ----- + ----- + ------------------------------- + . . .
                    x + y     6                   360

 -- Variable opcional: taylordepth
     Valor por defecto: 3

     Si todavía no hay términos no nulos, la función 'taylor' dobla el
     grado del desarrollo de '<g>(<x>)' tantas veces como sea necesario
     para que el grado del desarrollo sea menor o igual que '<n>
     2^taylordepth'.

 -- Función: taylorinfo (<expr>)
     Devuelve información sobre el desarrollo de Taylor <expr>.  El
     valor devuelto por esta función es una lista de listas.  Cada lista
     contiene el nombre de una variable, el punto de expansión y el
     grado del desarrollo.

     La función 'taylorinfo' devuelve 'false' si <expr> no es un
     desarrollo de Taylor.

     Ejemplo:

          (%i1) taylor ((1 - y^2)/(1 - x), x, 0, 3, [y, a, inf]);
                            2                       2
          (%o1)/T/ - (y - a)  - 2 a (y - a) + (1 - a )

                   2                        2
           + (1 - a  - 2 a (y - a) - (y - a) ) x

                   2                        2   2
           + (1 - a  - 2 a (y - a) - (y - a) ) x

                   2                        2   3
           + (1 - a  - 2 a (y - a) - (y - a) ) x  + . . .
          (%i2) taylorinfo(%);
          (%o2)               [[y, a, inf], [x, 0, 3]]

 -- Función: taylorp (<expr>)
     Devuelve 'true' si <expr> es un desarrollo de Taylor y 'false' en
     caso contrario.

 -- Variable opcional: taylor_logexpand
     Valor por defecto: 'true'

     La variable 'taylor_logexpand' controla los desarrollos de
     logaritmos en la función 'taylor'.

     Si 'taylor_logexpand' vale 'true', todos los logaritmos se expanden
     completamente de manera que algunos problemas que se plantean
     debido a ciertas identidades logarítmicas no interfieran con el
     proceso del cálculo del desarrollo de Taylor.  Sin embargo, este
     proceder no es del todo correcto.

 -- Variable opcional: taylor_order_coefficients
     Valor por defecto: 'true'

     La variable 'taylor_order_coefficients' controla la ordenación de
     los coeficientes en un desarrollo de Taylor.

     Si 'taylor_order_coefficients' vale 'true', los coeficientes del
     desarrollo de Taylor se ordenan de la forma canónica.

 -- Función: taylor_simplifier (<expr>)
     Simplifica los coeficientes de la serie de potencias <expr>.  Esta
     función es llamada desde la función 'taylor'.

 -- Variable opcional: taylor_truncate_polynomials
     Valor por defecto: 'true'

     Si 'taylor_truncate_polynomials' vale 'true', los polinomios quedan
     truncados en base a los niveles de truncamiento de entrada.

     En otro caso, aquellos polinomios que se utilicen como entrada a la
     función 'taylor' se consideran que tienen precisión infinita.

 -- Función: taytorat (<expr>)
     Convierte <expr> del formato de 'taylor' al formato CRE (Canonical
     Rational Expression).  El efecto es el mismo que haciendo 'rat
     (ratdisrep (<expr>))', pero más rápido.

 -- Función: trunc (<expr>)
     Devuelve la representación interna de la expresión <expr> de tal
     forma como si sus sumas fuesen una serie truncada de Taylor.  La
     expresión <expr> no sufre ninguna otra modificación.

     Ejemplo:

          (%i1) expr: x^2 + x + 1;
                                      2
          (%o1)                      x  + x + 1
          (%i2) trunc (expr);
                                          2
          (%o2)                  1 + x + x  + . . .
          (%i3) is (expr = trunc (expr));
          (%o3)                         true

 -- Función: unsum (<f>, <n>)
     Devuelve la diferencia '<f>(<n>) - <f>(<n> - 1)'.  En cierto
     sentido 'unsum' es la inversa de 'sum'.

     Véase también 'nusum'.

     Ejemplos:

          (%i1) g(p) := p*4^n/binomial(2*n,n);
                                               n
                                            p 4
          (%o1)               g(p) := ----------------
                                      binomial(2 n, n)
          (%i2) g(n^4);
                                        4  n
                                       n  4
          (%o2)                   ----------------
                                  binomial(2 n, n)
          (%i3) nusum (%, n, 0, n);
                               4        3       2              n
                2 (n + 1) (63 n  + 112 n  + 18 n  - 22 n + 3) 4      2
          (%o3) ------------------------------------------------ - ------
                              693 binomial(2 n, n)                 3 11 7
          (%i4) unsum (%, n);
                                        4  n
                                       n  4
          (%o4)                   ----------------
                                  binomial(2 n, n)

 -- Variable opcional: verbose
     Valor por defecto: 'false'

     Si 'verbose' vale 'true', la función 'powerseries' va imprimiendo
     mensajes durante su ejecución.


File: maxima.info,  Node: Introducción a las series de Fourier,  Next: Funciones y variables para series de Fourier,  Prev: Funciones y variables para las series,  Up: Sumas productos y series

28.4 Introducción a las series de Fourier
=========================================

El paquete 'fourie' contiene funciones para el cálculo simbólico de
series de Fourier.  Hay funciones en el paquete 'fourie' para calcular
los coeficientes y para manipular las expresiones.


File: maxima.info,  Node: Funciones y variables para series de Fourier,  Next: Funciones y variables para series de Poisson,  Prev: Introducción a las series de Fourier,  Up: Sumas productos y series

28.5 Funciones y variables para series de Fourier
=================================================

 -- Función: equalp (<x>, <y>)
     Devuelve 'true' si 'equal (<x>, <y>)', en otro caso devuelve
     'false'.  No devuelve el mensaje de error que se obtiene de 'equal
     (x, y)' en un caso como éste.

 -- Función: remfun (<f>, <expr>)
 -- Función: remfun (<f>, <expr>, <x>)
     La llamada 'remfun (<f>, <expr>)' reemplaza todas las
     subexpresiones '<f> (<arg>)' por <arg> en <expr>.

     La llamada 'remfun (<f>, <expr>, <x>)' reemplaza todas las
     subexpresiones '<f> (<arg>)' por <arg> en <expr> sólo si <arg>
     contiene a la variable <x>.

 -- Función: funp (<f>, <expr>)
 -- Función: funp (<f>, <expr>, <x>)
     La llamada 'funp (<f>, <expr>)' devuelve 'true' si <expr> contiene
     la función <f>.

     La llamada 'funp (<f>, <expr>, <x>)' devuelve 'true' si <expr>
     contiene la función <f> y la variable <x> está presente en el
     argumento de alguna de las presencias de <f>.

 -- Función: absint (<f>, <x>, <halfplane>)
 -- Función: absint (<f>, <x>)
 -- Función: absint (<f>, <x>, <a>, <b>)
     La llamada 'absint (<f>, <x>, <halfplane>)' devuelve la integral
     indefinida de <f> con respecto a <x> en el semiplano dado ('pos',
     'neg' o 'both').  La función <f> puede contener expresiones de la
     forma 'abs (x)', 'abs (sin (x))', 'abs (a) * exp (-abs (b) * abs
     (x))'.

     La llamada 'absint (<f>, <x>)' equivale a 'absint (<f>, <x>, pos)'.

     La llamada 'absint (<f>, <x>, <a>, <b>)' devuelve la integral
     definida de <f> con respecto a <x> de <a> a <b>.

 -- Función: fourier (<f>, <x>, <p>)
     Devuelve una lista con los coeficientes de Fourier de '<f>(<x>)'
     definida en el intervalo '[-p, p]'.

 -- Función: foursimp (<l>)
     Simplifica 'sin (n %pi)' a 0 si 'sinnpiflag' vale 'true' y 'cos (n
     %pi)' a '(-1)^n' si 'cosnpiflag' vale 'true'.

 -- Variable opcional: sinnpiflag
     Valor por defecto: 'true'

     Véase 'foursimp'.

 -- Variable opcional: cosnpiflag
     Valor por defecto: 'true'

     Véase 'foursimp'.

 -- Función: fourexpand (<l>, <x>, <p>, <limit>)
     Calcula y devuelve la serie de Fourier a partir de la lista de los
     coeficientes de Fourier <l> hasta el término <limit> (<limit> puede
     ser 'inf').  Los argumentos <x> y <p> tienen el mismo significado
     que en 'fourier'.

 -- Función: fourcos (<f>, <x>, <p>)
     Devuelve los coeficientes de los cosenos de Fourier de '<f>(<x>)'
     definida en '[0, <p>]'.

 -- Función: foursin (<f>, <x>, <p>)
     Devuelve los coeficientes de los senos de Fourier de '<f>(<x>)'
     definida en '[0, <p>]'.

 -- Función: totalfourier (<f>, <x>, <p>)
     Devuelve 'fourexpand (foursimp (fourier (<f>, <x>, <p>)), <x>, <p>,
     'inf)'.

 -- Función: fourint (<f>, <x>)
     Calcula y devuelve la lista de los coeficientes integrales de
     Fourier de '<f>(<x>)' definida en '[minf, inf]'.

 -- Función: fourintcos (<f>, <x>)
     Devuelve los coeficientes integrales de los cosenos '<f>(<x>)' en
     '[0, inf]'.

 -- Función: fourintsin (<f>, <x>)
     Devuelve los coeficientes integrales de los senos '<f>(<x>)' en
     '[0, inf]'.


File: maxima.info,  Node: Funciones y variables para series de Poisson,  Prev: Funciones y variables para series de Fourier,  Up: Sumas productos y series

28.6 Funciones y variables para series de Poisson
=================================================

 -- Función: intopois (<a>)
     Convierte <a> en un codificado Poisson.

 -- Función: outofpois (<a>)
     Convierte <a> desde codificado de Poisson a una representación
     general.  Si <a> no está en forma de Poisson, 'outofpois' hace la
     conversión, siendo entonces el valor retornado 'outofpois (intopois
     (<a>))'.  Esta función es un simplificador canónico para sumas de
     potencias de senos y cosenos.

 -- Función: poisdiff (<a>, <b>)
     Deriva <a> con respecto a <b>.  El argumento <b> debe aparecer sólo
     en los argumentos trigonométricos o sólo en los coeficientes.

 -- Función: poisexpt (<a>, <b>)
     Idéntico a 'intopois (<a>^<b>)'.  El argumento <b> debe ser un
     entero positivo.

 -- Función: poisint (<a>, <b>)
     Integra en un sentido restringido similar a 'poisdiff'.

 -- Variable optativa: poislim
     Valor por defecto: 5

     La variable 'poislim' determina el dominio de los coeficientes en
     los argumentos de las funciones trigonométricas.  El valor por
     defecto 5 corresponde al intervalo [-2^(5-1)+1,2^(5-1)], o
     [-15,16], pero puede reasignarse para [-2^(n-1)+1, 2^(n-1)].

 -- Función: poismap (<series>, <sinfn>, <cosfn>)
     Aplica las funciones <sinfn> a los términos sinusoidales y las
     funciones <cosfn> a los cosenoidales de la serie de Poisson dada.
     Tanto <sinfn> como <cosfn> son funciones de dos argumentos, los
     cuales son un coeficiente y una parte trigonométrica de un término
     de la serie.

 -- Función: poisplus (<a>, <b>)
     Idéntico a 'intopois (a + b)'.

 -- Función: poissimp (<a>)
     Convierte <a> en una serie de Poisson para <a> en su representación
     general.

 -- Símbolo especial: poisson
     El símbolo '/P/' sigue a la etiqueta de las líneas que contienen
     expresiones que son series de Poisson.

 -- Función: poissubst (<a>, <b>, <c>)
     Sustituye <b> por <a> en <c>, donde <c> es una serie de Poisson.

     (1) Si <b> es una de las variables <u>, <v>, <w>, <x>, <y> o <z>,
     entonces <a> debe ser una expresión lineal en esas variables (por
     ejemplo, '6*u + 4*v').

     (2) Si <b> no es ninguna de esas variables, entonces <a> no puede
     contener tampoco a ninguna de ellas, ni senos, ni cosenos.

 -- Función: poistimes (<a>, <b>)
     Idéntico a 'intopois (<a>*<b>)'.

 -- Función: printpois (<a>)
     Presenta una serie de Poisson en un formato legible.  Conjuntamente
     con 'outofpois', si es necesario convertirá <a> primero en una
     codificación de Poisson.


File: maxima.info,  Node: Teoría de Números,  Next: Simetrías,  Prev: Sumas productos y series,  Up: Top

29 Teoría de Números
********************

* Menu:

* Funciones y variables para teoría de números::  


File: maxima.info,  Node: Funciones y variables para teoría de números,  Prev: Teoría de Números,  Up: Teoría de Números

29.1 Funciones y variables para teoría de números
=================================================

 -- Función: bern (<n>)
     Devuelve el <n>-ésimo número de Bernoulli del entero <n>.  Los
     números de Bernoulli iguales a cero son suprimidos si 'zerobern'
     vale 'false'.

     Véase también 'burn'.

          (%i1) zerobern: true$
          (%i2) map (bern, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
                                1  1       1      1        1
          (%o2)           [1, - -, -, 0, - --, 0, --, 0, - --]
                                2  6       30     42       30
          (%i3) zerobern: false$
          (%i4) map (bern, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
                                1  1    1   1     1   5     691   7
          (%o4)           [1, - -, -, - --, --, - --, --, - ----, -]
                                2  6    30  42    30  66    2730  6

 -- Función: bernpoly (<x>, <n>)
     Devuelve el <n>-ésimo polinomio de Bernoulli de variable <x>.

 -- Función: bfzeta (<s>, <n>)
     Devuelve la función zeta de Riemann para el argumento <s>.  El
     valor que devuelve es del tipo "big float" (bfloat) y <n> es su
     número de dígitos.

     Es necesario cargar en memoria esta función haciendo 'load
     ("bffac")'.

 -- Función: bfhzeta (<s>, <h>, <n>)
     Devuelve la función zeta de Hurwitz para los argumentos <s> y <h>.
     El valor que devuelve es del tipo "big float" (bfloat) y <n> es su
     número de dígitos.

     La función zeta de Hurwitz se define como

                                  inf
                                  ====
                                  \        1
                   zeta (s,h)  =   >    --------
                                  /            s
                                  ====  (k + h)
                                  k = 0

     Ejecútese 'load (bffac)' antes de hacer uso de esta función.

 -- Función: burn (<n>)
     Siendo <n> entero, Devuelve un número racional que aproxima el
     <n>-ésimo número de Bernoulli.  La función 'burn' aprovecha el
     hecho de que los números de Bernoulli racionales se pueden
     aproximar con notable precisión gracias a

                             n - 1  1 - 2 n
                        (- 1)      2        zeta(2 n) (2 n)!
               B(2 n) = ------------------------------------
                                          2 n
                                       %pi

     La función 'burn' puede ser más eficiente que 'bern' cuando <n> es
     un número grande, ya que 'bern' calcula todos los números de
     Bernoulli hasta el <n>-ésimo.  Por el contrario, 'burn' hace uso de
     la aproximación para enteros pares <n> > 255.  En caso de enteros
     impares y <n> <= 255, se hace uso de la función 'bern'.

     Para utilizar esta función hay que cargarla antes en memoria
     escribiendo 'load ("bffac")'.  Véase también 'bern'.

 -- Función: chinese ([<r_1>, ..., <r_n>], [<m_1>, ..., <m_n>])

     Resulve el sistema de congruencias 'x = r_1 mod m_1', ..., 'x = r_n
     mod m_n'.  Los restos <r_n> pueden ser enteros arbitrarios,
     mientras que los módulos <m_n> deben ser positivos y primos dos a
     dos.

          (%i1) mods : [1000, 1001, 1003, 1007];
          (%o1)                   [1000, 1001, 1003, 1007]
          (%i2) lreduce('gcd, mods);
          (%o2)                               1
          (%i3) x : random(apply("*", mods));
          (%o3)                         685124877004
          (%i4) rems : map(lambda([z], mod(x, z)), mods);
          (%o4)                       [4, 568, 54, 624]
          (%i5) chinese(rems, mods);
          (%o5)                         685124877004
          (%i6) chinese([1, 2], [3, n]);
          (%o6)                    chinese([1, 2], [3, n])
          (%i7) %, n = 4;
          (%o7)                              10

 -- Función: cf (<expr>)

     Calcula aproximaciones con fracciones continuas.  <expr> es una
     expresión que contiene fracciones continuas, raíces cuadradas de
     enteros, y números reales (enteros, racionales, decimales en coma
     flotante y decimales de precisión arbitraria).  'cf' calcula
     expansiones exactas de números racionales, pero las expansiones de
     nÃºmeros decimales de coma flotante se truncan de acuerdo con el
     valor de 'ratepsilon', y la de los de decimales de precisión
     arbitraria (bigfloats) lo hacen respecto de '10^(-fpprec)'.

     En las expresiones se pueden combinar operandos con operadores
     aritméticos.  Maxima no conoce operaciones con fracciones continuas
     más allá de la función 'cf'.

     La función 'cf' evalúa sus argumentos después de asignar a la
     variable 'listarith' el valor 'false', retornando una fracción
     continua en forma de lista.

     Una fracción continua 'a + 1/(b + 1/(c + ...))' se representa como
     la lista '[a, b, c, ...]', donde los elementos 'a', 'b', 'c', ...
     se evalúan como enteros.  La expresión <expr> puede contener
     también 'sqrt (n)' donde 'n' es un entero; en tal caso, 'cf'
     devolverá tantos términos de la fracción continua como indique el
     valor de la variable 'cflength' multiplicado por el período.

     Una fracción continua puede reducirse a un número evaluando la
     representación aritmética que devuelve 'cfdisrep'.  Véase también
     'cfexpand', que es otra alternativa para evaluar fracciones
     continuas.

     Véanse asimismo 'cfdisrep', 'cfexpand' y 'cflength'.

     Ejemplos:

        * La expresión <expr> contiene fracciones continuas y raíces
          cuadradas de enteros.

               (%i1) cf ([5, 3, 1]*[11, 9, 7] + [3, 7]/[4, 3, 2]);
               (%o1)               [59, 17, 2, 1, 1, 1, 27]
               (%i2) cf ((3/17)*[1, -2, 5]/sqrt(11) + (8/13));
               (%o2)        [0, 1, 1, 1, 3, 2, 1, 4, 1, 9, 1, 9, 2]

        * La variable 'cflength' controla cuantos períodos de la
          fracción continua se calculan para números irracionales
          algebraicos.

               (%i1) cflength: 1$
               (%i2) cf ((1 + sqrt(5))/2);
               (%o2)                    [1, 1, 1, 1, 2]
               (%i3) cflength: 2$
               (%i4) cf ((1 + sqrt(5))/2);
               (%o4)               [1, 1, 1, 1, 1, 1, 1, 2]
               (%i5) cflength: 3$
               (%i6) cf ((1 + sqrt(5))/2);
               (%o6)           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]

        * Una fracción continua puede calcularse evaluando la
          representación aritmética que devuelve 'cfdisrep'.

               (%i1) cflength: 3$
               (%i2) cfdisrep (cf (sqrt (3)))$
               (%i3) ev (%, numer);
               (%o3)                   1.731707317073171

        * Maxima no sabe sobre operaciones con fracciones continuas más
          de lo que aporta la función 'cf'.

               (%i1) cf ([1,1,1,1,1,2] * 3);
               (%o1)                     [4, 1, 5, 2]
               (%i2) cf ([1,1,1,1,1,2]) * 3;
               (%o2)                  [3, 3, 3, 3, 3, 6]

 -- Función: cfdisrep (<lista>)
     Construye y devuelve una expresión aritmética ordinaria de la forma
     'a + 1/(b + 1/(c + ...))' a partir de la representación en formato
     lista de la fracción continua '[a, b, c, ...]'.

          (%i1) cf ([1, 2, -3] + [1, -2, 1]);
          (%o1)                     [1, 1, 1, 2]
          (%i2) cfdisrep (%);
                                            1
          (%o2)                     1 + ---------
                                              1
                                        1 + -----
                                                1
                                            1 + -
                                                2

 -- Función: cfexpand (<x>)
     Devuelve la matriz con los numeradores y denominadores de la última
     (columna 1) y penúltima (columna 2) convergentes de la fracción
     continua <x>.

          (%i1) cf (rat (ev (%pi, numer)));

          `rat' replaced 3.141592653589793 by 103993/33102 =3.141592653011902
          (%o1)                  [3, 7, 15, 1, 292]
          (%i2) cfexpand (%);
                                   [ 103993  355 ]
          (%o2)                    [             ]
                                   [ 33102   113 ]
          (%i3) %[1,1]/%[2,1], numer;
          (%o3)                   3.141592653011902

 -- Variable opcional: cflength
     Valor por defecto: 1

     La variable 'cflength' controla el número de términos de la
     fracción continua que devuelve la función 'cf', que será 'cflength'
     multiplicado por el período.  Así, el valor por defecto será el de
     un período.

          (%i1) cflength: 1$
          (%i2) cf ((1 + sqrt(5))/2);
          (%o2)                    [1, 1, 1, 1, 2]
          (%i3) cflength: 2$
          (%i4) cf ((1 + sqrt(5))/2);
          (%o4)               [1, 1, 1, 1, 1, 1, 1, 2]
          (%i5) cflength: 3$
          (%i6) cf ((1 + sqrt(5))/2);
          (%o6)           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]

 -- Función: divsum (<n>, <k>)
 -- Función: divsum (<n>)

     La llamada 'divsum (<n>, <k>)' devuelve la suma de los divisores de
     <n> elevados a la <k>-ésima potencia.

     La llamada 'divsum (<n>)' devuelve la suma de los divisores de <n>.

          (%i1) divsum (12);
          (%o1)                          28
          (%i2) 1 + 2 + 3 + 4 + 6 + 12;
          (%o2)                          28
          (%i3) divsum (12, 2);
          (%o3)                          210
          (%i4) 1^2 + 2^2 + 3^2 + 4^2 + 6^2 + 12^2;
          (%o4)                          210

 -- Función: euler (<n>)
     Devuelve el <n>-ésimo número de Euler del entero no negativo <n>.
     Los número de Euler iguales a cero se eliminan si 'zerobern' vale
     'false'.

     Para la constante de Euler-Mascheroni, véase '%gamma'.

          (%i1) zerobern: true$
          (%i2) map (euler, [0, 1, 2, 3, 4, 5, 6]);
          (%o2)               [1, 0, - 1, 0, 5, 0, - 61]
          (%i3) zerobern: false$
          (%i4) map (euler, [0, 1, 2, 3, 4, 5, 6]);
          (%o4)               [1, - 1, 5, - 61, 1385, - 50521, 2702765]

 -- Variable opcional: factors_only
     Valor por defecto: 'false'

     Controla el resultado devuelto por 'ifactors'.  El valor por
     defecto 'false' hace que 'ifactors' no dé información sobre las
     multiplicidades de los factores primos calculados.  Cuando
     'factors_only' vale 'true', 'ifactors' solo devuelve la lista de
     factores primos.

     Para ejemplos, véase 'ifactors'.

 -- Función: fib (<n>)
     Devuelve el <n>-ésimo número de Fibonacci.  La llamada 'fib(0)'
     devuelve 0, 'fib(1)' devuelve 1 y 'fib (-<n>)' es igual a
     '(-1)^(<n> + 1) * fib(<n>)'.

     Después de llamar a 'fib', la variable 'prevfib' toma el valor 'fib
     (<n> - 1)', que es el número de Fibonacci que precede al último
     calculado.

          (%i1) map (fib, [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
          (%o1)           [- 3, 2, - 1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21]

 -- Función: fibtophi (<expr>)
     Expresa los números de Fibonacci en <expr> en términos de la razón
     áurea '%phi', que es '(1 + sqrt(5))/2', aproximadamente 1.61803399.

     Ejemplos:

          (%i1) fibtophi (fib (n));
                                     n             n
                                 %phi  - (1 - %phi)
          (%o1)                  -------------------
                                     2 %phi - 1
          (%i2) fib (n-1) + fib (n) - fib (n+1);
          (%o2)          - fib(n + 1) + fib(n) + fib(n - 1)
          (%i3) fibtophi (%);
                      n + 1             n + 1       n             n
                  %phi      - (1 - %phi)        %phi  - (1 - %phi)
          (%o3) - --------------------------- + -------------------
                          2 %phi - 1                2 %phi - 1
                                                    n - 1             n - 1
                                                %phi      - (1 - %phi)
                                              + ---------------------------
                                                        2 %phi - 1
          (%i4) ratsimp (%);
          (%o4)                           0

 -- Función: ifactors (<n>)
     Devuelve la factorización del entero positivo <n>.  Si
     'n=p1^e1..pk^nk' es la descomposición de <n> en números primos,
     'ifactors' devuelve '[[p1, e1], ... , [pk, ek]]'.

     Los métodos de factorización se basan en divisiones tentativas con
     números primos hasta 9973, en los métodos rho y p-1 de Pollard y en
     curvas elípticas.

     La respuesta que se obtiene de 'ifactors' está controlada por la
     variable opcional 'factors_only'.  El valor por defecto 'false'
     hace que 'ifactors' no dé información sobre las multiplicidades de
     los factores primos calculados.  Cuando 'factors_only' vale 'true',
     'ifactors' solo devuelve la lista de factores primos.

          (%i1) ifactors(51575319651600);
          (%o1)     [[2, 4], [3, 2], [5, 2], [1583, 1], [9050207, 1]]
          (%i2) apply("*", map(lambda([u], u[1]^u[2]), %));
          (%o2)                        51575319651600
          (%i3) ifactors(51575319651600), factors_only : true;
          (%o3)                   [2, 3, 5, 1583, 9050207]

 -- Función: igcdex (<n>, <k>)

     Devuelve la lista '[<a>, <b>, <u>]', donde <u> es el máximo común
     divisor de <n> y <k>, siendo <u> igual a '<a> <n> + <b> <k>'.  Los
     argumentos <n> y <k> deben ser enteros.

     'igcdex' implementa el algoritmo de Euclides.  Véase también
     'gcdex'.

     La instrucción 'load(gcdex)' carga esta función.

     Ejemplos:

          (%i1) load(gcdex)$

          (%i2) igcdex(30,18);
          (%o2)                      [- 1, 2, 6]
          (%i3) igcdex(1526757668, 7835626735736);
          (%o3)            [845922341123, - 164826435, 4]
          (%i4) igcdex(fib(20), fib(21));
          (%o4)                   [4181, - 2584, 1]

 -- Función: inrt (<x>, <n>)
     Devuelve la raíz entera <n>-ésima del valor absoluto de <x>.

          (%i1) l: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]$
          (%i2) map (lambda ([a], inrt (10^a, 3)), l);
          (%o2) [2, 4, 10, 21, 46, 100, 215, 464, 1000, 2154, 4641, 10000]

 -- Función: inv_mod (<n>, <m>)
     Calcula el inverso de <n> módulo <m>.  La llamada 'inv_mod (n,m)'
     devuelve 'false' si <n> es un divisor nulo módulo <m>.

          (%i1) inv_mod(3, 41);
          (%o1)                           14
          (%i2) ratsimp(3^-1), modulus = 41;
          (%o2)                           14
          (%i3) inv_mod(3, 42);
          (%o3)                          false

 -- Función: isqrt (<x>)
     Devuelve la "raíz cuadrada entera" del valor absoluto de <x>, el
     cual debe ser un entero.

 -- Función: jacobi (<p>, <q>)
     Devuelve el símbolo de Jacobi para <p> y <q>.

          (%i1) l: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]$
          (%i2) map (lambda ([a], jacobi (a, 9)), l);
          (%o2)         [1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0]

 -- Función: lcm (<expr_1>, ..., <expr_n>)
     Devuelve el mínimo común múltiplo de sus argumentos.  Los
     argumentos pueden ser tanto expresiones en general como enteros.

     Es necesario cargar en memoria esta función haciendo 'load
     ("functs")'.

 -- Función: lucas (<n>)
     Devuelve el <n>-ésimo número de Lucas.  'lucas(0)' es igual a 2,
     'lucas(1)' es igual a 1 y 'lucas(-<n>)' es igual a '(-1)^(-<n>) *
     lucas(<n>)'.

          (%i1) map (lucas, [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
          (%o1)             [7, - 4, 3, - 1, 2, 1, 3, 4, 7, 11, 18, 29, 47]

     Después de llamar a 'lucas', la variable global 'next_lucas' es
     igual a 'lucas (<n> + 1)', el número de Lucas que sigue al último
     que se ha devuelto.  El ejemplo muestra como los números de
     Fibonacci se pueden calcular mediante 'lucas' y 'next_lucas'.

          (%i1) fib_via_lucas(n) :=
                   block([lucas : lucas(n)],
                   signum(n) * (2*next_lucas - lucas)/5 )$
          (%i2) map (fib_via_lucas, [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
          (%o2)             [- 3, 2, - 1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21]

 -- Función: mod (<x>, <y>)

     Si <x> e <y> son números reales e <y> es distinto de cero, devuelve
     '<x> - <y> * floor(<x> / <y>)'.  Para todos los reales <x>, se
     tiene 'mod (<x>, 0) = <x>'.  Para información sobre la definición
     de 'mod (<x>, 0) = <x>', véase la sección 3.4 de "Concrete
     Mathematics", by Graham, Knuth, and Patashnik.  La función 'mod
     (<x>, 1)' es de diente de sierra con periodo unidad y con 'mod (1,
     1) = 0' y 'mod (0, 1) = 0'.

     Para encontrar el argumento principal (un número del intervalo
     '(-%pi, %pi]') de un número complejo, hágase uso de la función '<x>
     |-> %pi - mod (%pi - <x>, 2*%pi)', donde <x> es un argumento.

     Si <x> e <y> son expresiones constantes (por ejemplo, '10 * %pi'),
     'mod' utiliza el mismo esquema de evaluación basado en números
     grandes en coma flotante (big floats) que 'floor' y 'ceiling'.
     También es posible, pero improbable, que 'mod' pueda retornar un
     valor erróneo en tales casos.

     Para argumentos no numéricos <x> o <y>, 'mod' aplica algunas reglas
     de simplificación:

          (%i1) mod (x, 0);
          (%o1)                           x
          (%i2) mod (a*x, a*y);
          (%o2)                      a mod(x, y)
          (%i3) mod (0, x);
          (%o3)                           0

 -- Función: next_prime (<n>)
     Devuelve el menor de los primos mayores que <n>.

          (%i1) next_prime(27);
          (%o1)                       29

 -- Función: partfrac (<expr>, <var>)
     Expande la expresión <expr> en fracciones parciales respecto de la
     variable principal <var>.  La función 'partfrac' hace una
     descomposición completa en fracciones parciales.  El algoritmo que
     se utiliza se basa en el hecho de que los denominadores de la
     expansión en fracciones parciales (los factores del denominador
     original) son primos relativos.  Los numeradores se pueden escribir
     como combinaciones lineales de los denominadores.

          (%i1) 1/(1+x)^2 - 2/(1+x) + 2/(2+x);
                                2       2        1
          (%o1)               ----- - ----- + --------
                              x + 2   x + 1          2
                                              (x + 1)
          (%i2) ratsimp (%);
                                           x
          (%o2)                 - -------------------
                                   3      2
                                  x  + 4 x  + 5 x + 2
          (%i3) partfrac (%, x);
                                2       2        1
          (%o3)               ----- - ----- + --------
                              x + 2   x + 1          2
                                              (x + 1)

 -- Función: power_mod (<a>, <n>, <m>)
     Utiliza un algoritmo modular para calcular 'a^n mod m', siendo <a>
     y <n> enteros cualesquiera y <m> un entero positivo.  Si <n> es
     negativo, se utilizará 'inv_mod' para encontrar el inverso modular.

          (%i1) power_mod(3, 15, 5);
          (%o1)                          2
          (%i2) mod(3^15,5);
          (%o2)                          2
          (%i3) power_mod(2, -1, 5);
          (%o3)                          3
          (%i4) inv_mod(2,5);
          (%o4)                          3

 -- Función: primep (<n>)
     Comprueba si el número entero <n> es o no primo, devolviendo 'true'
     o 'false' según el caso.

     Cuando el resultado de 'primep (<n>)' es 'false', <n> es un número
     compuesto, y si es 'true', <n> es primo con alta probabilidad.

     Si <n> es menor que 341550071728321, se utiliza una versión
     determinística de la prueba de Miller-Rabin.  En tal caso, si
     'primep (<n>)' devuelve 'true', entonces <n> es un número primo.

     Para <n> mayor que 341550071728321 'primep' realiza
     'primep_number_of_tests' pruebas de seudo-primalidad de
     Miller-Rabin y una prueba de seudo-primalidad de Lucas.  La
     probabilidad de que un número compuesto <n> pase una prueba de
     Miller-Rabin es menor que 1/4.  Con el valor por defecto de
     'primep_number_of_tests', que es 25, la probabilidad de que <n> sea
     compuesto es menor que 10^-15.

 -- Variable opcional: primep_number_of_tests
     Valor por defecto: 25

     Número de pruebas de Miller-Rabin a realizar por 'primep'.

 -- Función: prev_prime (<n>)
     Devuelve el mayor de los primos menores que <n>.

          (%i1) prev_prime(27);
          (%o1)                       23

 -- Función: qunit (<n>)
     Devuelve la unidad principal de 'sqrt (<n>)', siendo <n> un entero;
     consiste en la resolución de la ecuación de Pell 'a^2 - <n> b^2 =
     1'.

          (%i1) qunit (17);
          (%o1)                     sqrt(17) + 4
          (%i2) expand (% * (sqrt(17) - 4));
          (%o2)                           1

 -- Función: totient (<n>)
     Devuelve el número de enteros menores o iguales a <n> que son
     primos relativos con <n>.

 -- Variable opcional: zerobern
     Valor por defecto: 'true'

     Si 'zerobern' vale 'false', 'bern' excluye los números de Bernoulli
     y 'euler' excluye los números de Euler que sean iguales a cero.
     Véase 'bern' y 'euler'.

 -- Función: zeta (<n>)
     Devuelve la función zeta de Riemann.  Si <n> es entero negativo, 0
     o número par positivo, la función zeta de Riemann devuelve un valor
     exacto; en el caso de número par positivo, la variable opcional
     'zeta%pi', además, tiene que tener el valor 'true' (véase
     'zeta%pi').  Cuando el argumento es un número decimal o bigfloat,
     entonces la función zeta de Riemann se calcula numéricamente.
     Maxima devuelve una forma nominal 'zeta (<n>)' para cualesquiera
     otros argumentos, incluidos los racionales no enteros, los números
     complejos y los enteros pares si 'zeta%pi' vale 'false'.

     'zeta(1)' no está definida, pero Maxima conce el límite de
     'limit(zeta(x), x, 1)' por ambos lados.

     La función zeta de Riemann se distribuye sobre las listas, matrices
     y ecuaciones.

     Véanse también 'bfzeta' y 'zeta%pi'.

     Ejemplos:

          (%i1) zeta([-2,-1,0,0.5,2,3,1+%i]);
                                                        2
                       1     1                       %pi
          (%o1)  [0, - --, - -, - 1.460354508809587, ----, zeta(3), zeta(%i + 1)]
                       12    2                        6

          (%i2) limit(zeta(x),x,1,plus);
          (%o2)                                 inf
          (%i3) limit(zeta(x),x,1,minus);
          (%o3)                                minf

 -- Variable opcional: zeta%pi
     Valor por defecto: 'true'

     Si 'zeta%pi' vale 'true', 'zeta' devuelve una expresión
     proporcional a '%pi^n' si 'n' es un número par positivo.  En caso
     contrario, 'zeta' no se evalúa y devuelve la forma nominal 'zeta
     (n)'.

     Ejemplos:

          (%i1) zeta%pi: true$
          (%i2) zeta (4);
                                           4
                                        %pi
          (%o2)                         ----
                                         90
          (%i3) zeta%pi: false$
          (%i4) zeta (4);
          (%o4)                        zeta(4)

 -- Función: zn_add_table (<n>)
     Muestra la tabla de la suma de todos los elementos de (Z/<n>Z).

     Véanse también 'zn_mult_table' y 'zn_power_table'.

 -- Función: zn_determinant (<matrix>, <p>)
     Utiliza el procedimiento de la descomposición LU para calcular el
     determinante de <matrix> sobre (Z/<p>Z). El argumento <p> debe ser
     un número primo.

     Si el determinante es igual a cero, el procedimiento puede fallar,
     en cuyo caso 'zn_determinant' calcula el determinante no modular y
     luego reduce.

     Véase también 'zn_invert_by_lu'.

     Ejemplo:

          (%i1) m : matrix([1,3],[2,4]);
                                          [ 1  3 ]
          (%o1)                           [      ]
                                          [ 2  4 ]
          (%i2) zn_determinant(m, 5);
          (%o2)                               3
          (%i3) m : matrix([2,4,1],[3,1,4],[4,3,2]);
                                         [ 2  4  1 ]
                                         [         ]
          (%o3)                          [ 3  1  4 ]
                                         [         ]
                                         [ 4  3  2 ]
          (%i4) zn_determinant(m, 5);
          (%o4)                               0

 -- Función: zn_invert_by_lu (<matrix>, <p>)
     Utiliza el procedimiento de la descomposición LU para calcular la
     inversa modular de <matrix> sobre (Z/<p>Z). El argumento <p> debe
     ser un número primo y <matrix> invertible.  La función
     'zn_invert_by_lu' devuelve 'false' si <matrix> no es invertible.

     Véase 'zn_determinant'.

     Ejemplo:

          (%i1) m : matrix([1,3],[2,4]);
                                          [ 1  3 ]
          (%o1)                           [      ]
                                          [ 2  4 ]
          (%i2) zn_determinant(m, 5);
          (%o2)                               3
          (%i3) mi : zn_invert_by_lu(m, 5);
                                          [ 3  4 ]
          (%o3)                           [      ]
                                          [ 1  2 ]
          (%i4) matrixmap(lambda([a], mod(a, 5)), m . mi);
                                          [ 1  0 ]
          (%o4)                           [      ]
                                          [ 0  1 ]

 -- Función: zn_log (<a>, <g>, <n>)
 -- Función: zn_log (<a>, <g>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])
     Calcula el logaritmo discreto.  Sea (Z/<n>Z)* un grupo cíclico, <g>
     una raíz primitiva módulo <n> y <a> un miembro de este grupo,
     entonces 'zn_log (a, g, n)' calcula la congruencia 'g^x = a mod n'.

     El algoritmo que se aplica necesita una factorización prima de
     'totient(n)'.  Esta factorización puede requerir mucho tiempo de
     cálculo, por lo que en ciertos casos puede ser aconsejable
     factorizar primero y luego pasar la lista de factores a 'zn_log'
     como cuarto argumento.  La lista debe ser de la misma forma que las
     lista devuelta por 'ifactors(totient(n))' utilizando la opción por
     defecto 'factors_only : false'.

     El algoritmo utiliza la reducción de Pohlig-Hellman y el método Rho
     de Pollard para los logaritmos discretos.  El tiempo de ejecución
     de 'zn_log' depende en primer lugar del número de bits del mayor
     factor primo del totient.

     Véanse también 'zn_primroot', 'zn_order', 'ifactors' y 'totient'.

     Ejemplos:

     'zn_log (a, g, n)' resuelve la congruencia 'g^x = a mod n'.

          (%i1) n : 22$
          (%i2) g : zn_primroot(n);
          (%o2)                               7
          (%i3) ord_7 : zn_order(7, n);
          (%o3)                              10
          (%i4) powers_7 : makelist(power_mod(g, x, n), x, 0, ord_7 - 1);
          (%o4)              [1, 7, 5, 13, 3, 21, 15, 17, 9, 19]
          (%i5) zn_log(21, g, n);
          (%o5)                               5
          (%i6) map(lambda([x], zn_log(x, g, n)), powers_7);
          (%o6)                [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

     El cuarto argumento opcional debe ser de la misma forma que la
     lista devuelta por 'ifactors(totient(n))'.

          (%i1) (p : 2^127-1, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors(p - 1)$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                              43
          (%i4) a : power_mod(g, 1234567890, p)$
          (%i5) zn_log(a, g, p, ifs);
          (%o5)                          1234567890
          (%i6) time(%o5);
          (%o6)                            [1.204]
          (%i7) f_max : last(ifs);
          (%o7)                       [77158673929, 1]
          (%i8) slength( printf(false, "~b", f_max[1]) );
          (%o8)                              37

 -- Función: zn_mult_table (<n>)
 -- Función: zn_mult_table (<n>, all)
     Sin el argumento opcional <all>, 'zn_mult_table(n)' muestra la
     tabla de multiplicación de los elementos de (Z/<n>Z)*, que son
     todos elementos invertibles módulo <n>.

     El argumento opcional <all> hace que la tabla se genere para todos
     los elementos no nulos.

     Véanse también 'zn_add_table' y 'zn_power_table'.

     Ejemplo:

          (%i1) zn_mult_table(4);
                                          [ 1  3 ]
          (%o1)                           [      ]
                                          [ 3  1 ]
          (%i2) zn_mult_table(4, all);
                                         [ 1  2  3 ]
                                         [         ]
          (%o2)                          [ 2  0  2 ]
                                         [         ]
                                         [ 3  2  1 ]

 -- Función: zn_order (<x>, <n>)
 -- Función: zn_order (<x>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])
     Devuelve el orden de <x> si es una unidad del grupo finito
     (Z/<n>Z)*, o devuelve 'false'.  <x> una unidad módulo <n> si es
     coprimo con <n>.

     El algoritmo que se aplica necesita una factorización prima de
     'totient(n)'.  Esta factorización puede requerir mucho tiempo de
     cálculo, por lo que en ciertos casos puede ser aconsejable
     factorizar primero y luego pasar la lista de factores a 'zn_log'
     como tercer argumento.  La lista debe ser de la misma forma que las
     lista devuelta por 'ifactors(totient(n))' utilizando la opción por
     defecto 'factors_only : false'.

     Véanse también 'zn_primroot', 'ifactors' y 'totient'.

     Ejemplos:

     'zn_order' calcula el orden de la unidad <x> en (Z/<n>Z)*.

          (%i1) n : 22$
          (%i2) g : zn_primroot(n);
          (%o2)                               7
          (%i3) units_22 : sublist(makelist(i,i,1,21), lambda([x], gcd(x, n) = 1));
          (%o3)              [1, 3, 5, 7, 9, 13, 15, 17, 19, 21]
          (%i4) (ord_7 : zn_order(7, n)) = totient(n);
          (%o4)                            10 = 10
          (%i5) powers_7 : makelist(power_mod(g,i,n), i,0,ord_7 - 1);
          (%o5)              [1, 7, 5, 13, 3, 21, 15, 17, 9, 19]
          (%i6) map(lambda([x], zn_order(x, n)), powers_7);
          (%o6)              [1, 10, 5, 10, 5, 2, 5, 10, 5, 10]
          (%i7) map(lambda([x], ord_7/gcd(x, ord_7)), makelist(i, i,0,ord_7 - 1));
          (%o7)              [1, 10, 5, 10, 5, 2, 5, 10, 5, 10]
          (%i8) totient(totient(n));
          (%o8)                               4

     El tercer argumento opcional debe ser de la misma forma que la
     lista devuelta por 'ifactors(totient(n))'.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors( totient(p) )$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                               3
          (%i4) is( (ord_3 : zn_order(g, p, ifs)) = totient(p) );
          (%o4)                             true
          (%i5) map(lambda([x], ord_3/zn_order(x, p, ifs)), makelist(i,i,2,15));
          (%o5)        [22, 1, 44, 10, 5, 2, 22, 2, 8, 2, 1, 1, 20, 1]

 -- Función: zn_power_table (<n>)
 -- Función: zn_power_table (<n>, all)
     Sin el argumento opcional <all>, 'zn_power_table(n)' muestra la
     tabla de potencias de los elementos de (Z/<n>Z)*, que son todos
     elementos invertibles módulo <n>.  El exponente se obtiene con un
     bucle desde '1' hasta 'totient(n)' y la tabla termina con una
     columna de unos al lado derecho.

     El argumento opcional <all> hace que la tabla se genere para todos
     los elementos no nulos.  En este caso, el exponente se calcula con
     un bucle desde '1' hasta 'totient(n) + 1' y la última columna es
     por lo tanto igual a la primera.

     Véanse también 'zn_add_table' y 'zn_mult_table'.

     Ejemplo:

          (%i1) zn_power_table(6);
                                          [ 1  1 ]
          (%o1)                           [      ]
                                          [ 5  1 ]
          (%i2) zn_power_table(6, all);
                                         [ 1  1  1 ]
                                         [         ]
                                         [ 2  4  2 ]
                                         [         ]
          (%o2)                          [ 3  3  3 ]
                                         [         ]
                                         [ 4  4  4 ]
                                         [         ]
                                         [ 5  1  5 ]

 -- Función: zn_primroot (<n>)
 -- Función: zn_primroot (<n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])
     Si el grupo multiplicativo es cíclico, 'zn_primroot' calcula la
     menor raíz primitiva de módulo <n>.  (Z/<n>Z)* es cíclico si <n> es
     igual a '2', '4', 'p^k' o '2*p^k', siendo 'p' primo y mayor que '2'
     y 'k' un número natural.  Si a la variable opcional
     'zn_primroot_pretest', cuyo valor por defecto es 'false', se le da
     el valor 'true', entonces 'zn_primroot' realiza una prueba previa.
     En cualquier caso, el cálculo está limitado por la cota superior
     'zn_primroot_limit'.

     Si (Z/<n>Z)* no es cíclico o si no tiene raíces primitivas menores
     que 'zn_primroot_limit', 'zn_primroot' devuelve 'false'.

     El algoritmo que se aplica necesita una factorización prima de
     'totient(n)'.  Esta factorización puede requerir mucho tiempo de
     cálculo, por lo que en ciertos casos puede ser aconsejable
     factorizar primero y luego pasar la lista de factores a 'zn_log'
     como argumento adicional.  La lista debe ser de la misma forma que
     las lista devuelta por 'ifactors(totient(n))' utilizando la opción
     por defecto 'factors_only : false'.

     Véanse también 'zn_primroot_p', 'zn_order', 'ifactors' y 'totient'.

     Ejemplos:

     'zn_primroot' calcula la menor raíz primitiva de módulo <n> o
     devuelve 'false'.

          (%i1) n : 14$
          (%i2) g : zn_primroot(n);
          (%o2)                               3
          (%i3) zn_order(g, n) = totient(n);
          (%o3)                             6 = 6
          (%i4) n : 15$
          (%i5) zn_primroot(n);
          (%o5)                             false

     El argumento opcional debe ser de la misma forma que la lista
     devuelta por 'ifactors(totient(n))'.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors( totient(p) )$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                               3
          (%i4) [time(%o2), time(%o3)];
          (%o4)                    [[15.556972], [0.004]]
          (%i5) is(zn_order(g, p, ifs) = p - 1);
          (%o5)                             true
          (%i6) n : 2^142 + 216$
          (%i7) ifs : ifactors(totient(n))$
          (%i8) zn_primroot(n, ifs),
                zn_primroot_limit : 200, zn_primroot_verbose : true;
          `zn_primroot' stopped at zn_primroot_limit = 200
          (%o8)                             false

 -- Option variable: zn_primroot_limit
     Valor por defecto: '1000'

     Si 'zn_primroot' no puede encontrar una raíz primitiva, entonces se
     para en esta cota superior.  Si a la variable opcional
     'zn_primroot_verbose' se le da el valor 'true', se imprimirá un
     mensaje cuando 'zn_primroot_limit' sea alcanzado.

 -- Función: zn_primroot_p (<x>, <n>)
 -- Función: zn_primroot_p (<x>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])
     Comprueba si <x> es una raíz primitiva en el grupo multiplizativo
     (Z/<n>Z)*.

     El algoritmo que se aplica necesita una factorización prima de
     'totient(n)'.  Esta factorización puede requerir mucho tiempo de
     cálculo, por lo que en ciertos casos puede ser aconsejable
     factorizar primero y luego pasar la lista de factores a 'zn_log'
     como tercer argumento.  La lista debe ser de la misma forma que las
     lista devuelta por 'ifactors(totient(n))' utilizando la opción por
     defecto 'factors_only : false'.

     Véanse también 'zn_primroot', 'zn_order', 'ifactors' y 'totient'.

     Ejemplos:

     'zn_primroot_p' como función de predicado.

          (%i1) n : 14$
          (%i2) units_14 : sublist(makelist(i,i,1,13), lambda([i], gcd(i, n) = 1));
          (%o2)                     [1, 3, 5, 9, 11, 13]
          (%i3) zn_primroot_p(13, n);
          (%o3)                            false
          (%i4) sublist(units_14, lambda([x], zn_primroot_p(x, n)));
          (%o4)                            [3, 5]
          (%i5) map(lambda([x], zn_order(x, n)), units_14);
          (%o5)                      [1, 6, 6, 3, 3, 2]

     El tercer argumento opcional debe ser de la misma forma que la
     lista devuelta por 'ifactors(totient(n))'.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors( totient(p) )$
          (%i3) sublist(makelist(i,i,1,50), lambda([x], zn_primroot_p(x, p, ifs)));
          (%o3)      [3, 12, 13, 15, 21, 24, 26, 27, 29, 33, 38, 42, 48]
          (%i4) [time(%o2), time(%o3)];
          (%o4)                   [[7.748484], [0.036002]]

 -- Option variable: zn_primroot_pretest
     Valor por defecto: 'false'

     El grupo multiplicativo (Z/<n>Z)* es cíclico si if <n> es igual a
     '2', '4', 'p^k' o '2*p^k', siendo 'p' un número primo mayor que '2'
     y 'k' es un número natural.

     La variable 'zn_primroot_pretest' controla si 'zn_primroot' debe
     comprobar si sucede alguna de estas situaciones antes de calcular
     la menor raíz primitiva.  Solo se realizará esta comprobación si
     'zn_primroot_pretest' toma el valor 'true'.

 -- Option variable: zn_primroot_verbose
     Valor por defecto: 'false'

     Controla si 'zn_primroot' imprime un mensaje cuando alcanza
     'zn_primroot_limit'.


File: maxima.info,  Node: Simetrías,  Next: Grupos,  Prev: Teoría de Números,  Up: Top

30 Simetrías
************

* Menu:

* Funciones y variables para simetrías::  

Paquete escrito para Macsyma-Symbolics por Annick Valibouze
(<http://www-calfor.lip6.fr/~avb/>).  Los algoritmos están descritos en
los siguientes artículos:

  1. Fonctions symétriques et changements de bases.  Annick Valibouze.
     EUROCAL'87 (Leipzig, 1987), 323-332, Lecture Notes in Comput.  Sci
     378.  Springer, Berlin, 1989.
     <http://www.stix.polytechnique.fr/publications/1984-1994.html>

  2. Résolvantes et fonctions symétriques.  Annick Valibouze.
     Proceedings of the ACM-SIGSAM 1989 International Symposium on
     Symbolic and Algebraic Computation, ISSAC'89 (Portland, Oregon).
     ACM Press, 390-399, 1989.
     <http://www-calfor.lip6.fr/~avb/DonneesTelechargeables/MesArticles/issac89ACMValibouze.pdf>

  3. Symbolic computation with symmetric polynomials, an extension to
     Macsyma.  Annick Valibouze.  Computers and Mathematics (MIT, USA,
     June 13-17, 1989), Springer-Verlag, New York Berlin, 308-320, 1989.
     <http://www.stix.polytechnique.fr/publications/1984-1994.html>

  4. Théorie de Galois Constructive.  Annick Valibouze.  Mémoire
     d'habilitation à diriger les recherches (HDR), Université P. et M.
     Curie (Paris VI), 1994


File: maxima.info,  Node: Funciones y variables para simetrías,  Prev: Simetrías,  Up: Simetrías

30.1 Funciones y variables para simetrías
=========================================

 -- Función: comp2pui (<n>, <l>)
     Realiza el paso de las funciones simétricas completas de la lista
     <l> a las funciones simétricas elementales de 0 a <n>.  En caso de
     que la lista <l> contenga menos de '<n>+1' elementos, se completará
     con valores formales.  El primer elemento de la lista <l> almacena
     el cardinal del alfabeto, en caso de que exista; en caso contrario
     se le da el valor <n>.

          (%i1) comp2pui (3, [4, g]);
                                  2                    2
          (%o1)    [4, g, 2 h2 - g , 3 h3 - g h2 + g (g  - 2 h2)]

 -- Función: cont2part (<pc>, <lvar>)
     Convierte el polinomio particionado asociado a la forma contraída
     <pc>, cuyas variables se encuentran en <lvar>.

          (%i1) pc: 2*a^3*b*x^4*y + x^5;
                                     3    4      5
          (%o1)                   2 a  b x  y + x
          (%i2) cont2part (pc, [x, y]);
                                             3
          (%o2)              [[1, 5, 0], [2 a  b, 4, 1]]

     Otras funciones para efectuar cambios de representación son:
     'contract', 'explose', 'part2cont', 'partpol', 'tcontract' y
     'tpartpol'.

 -- Función: contract (<psym>, <lvar>)
     Convierte una forma contraída (como un monomio por órbita sobre la
     acción del grupo simétrico) del polinomio <psym> cuyas variables se
     encuentran en la lista <lvar>.  La función 'explose' realiza la
     operación inversa.  A mayopes, la función 'tcontract' comprueba la
     simetría del polinomio.

          (%i1) psym: explose (2*a^3*b*x^4*y, [x, y, z]);
                   3      4      3      4      3    4        3    4
          (%o1) 2 a  b y z  + 2 a  b x z  + 2 a  b y  z + 2 a  b x  z

                                                     3      4      3    4
                                                + 2 a  b x y  + 2 a  b x  y
          (%i2) contract (psym, [x, y, z]);
                                        3    4
          (%o2)                      2 a  b x  y

     Otras funciones para efectuar cambios de representación son:

     'cont2part', 'explose', 'part2cont', 'partpol', 'tcontract',
     'tpartpol'.

 -- Función: direct ([<p_1>, ..., <p_n>], <y>, <f>, [<lvar_1>, ...,
          <lvar_n>])
     Calcula la imagen directa (véase M. Giusti, D. Lazard et A.
     Valibouze, ISSAC 1988, Roma) asociada a la función <f>, en las
     listas de variables <lvar_1>, ..., <lvar_n>, y en los polinomios
     <p_1>, ..., <p_n> de una variable <y>.  Si la expresión de <f> no
     depende de variable alguna, no sólo es inútil aportar esa variable,
     sino que también disminuyen considerablemente los cálculos cuando
     la variable no se declara.

          (%i1) direct ([z^2  - e1* z + e2, z^2  - f1* z + f2],
                        z, b*v + a*u, [[u, v], [a, b]]);
                 2
          (%o1) y  - e1 f1 y

                                           2            2             2   2
                            - 4 e2 f2 - (e1  - 2 e2) (f1  - 2 f2) + e1  f1
                          + -----------------------------------------------
                                                   2
          (%i2) ratsimp (%);
                        2                2                   2
          (%o2)        y  - e1 f1 y + (e1  - 4 e2) f2 + e2 f1
          (%i3) ratsimp (direct ([z^3-e1*z^2+e2*z-e3,z^2  - f1* z + f2],
                        z, b*v + a*u, [[u, v], [a, b]]));
                 6            5         2                        2    2   4
          (%o3) y  - 2 e1 f1 y  + ((2 e1  - 6 e2) f2 + (2 e2 + e1 ) f1 ) y

                                    3                               3   3
           + ((9 e3 + 5 e1 e2 - 2 e1 ) f1 f2 + (- 2 e3 - 2 e1 e2) f1 ) y

                   2       2        4    2
           + ((9 e2  - 6 e1  e2 + e1 ) f2

                              2       2       2                   2    4
           + (- 9 e1 e3 - 6 e2  + 3 e1  e2) f1  f2 + (2 e1 e3 + e2 ) f1 )

            2          2                      2     3          2
           y  + (((9 e1  - 27 e2) e3 + 3 e1 e2  - e1  e2) f1 f2

                           2            2    3                5
           + ((15 e2 - 2 e1 ) e3 - e1 e2 ) f1  f2 - 2 e2 e3 f1 ) y

                     2                   3           3     2   2    3
           + (- 27 e3  + (18 e1 e2 - 4 e1 ) e3 - 4 e2  + e1  e2 ) f2

                   2      3                   3    2   2
           + (27 e3  + (e1  - 9 e1 e2) e3 + e2 ) f1  f2

                             2    4        2   6
           + (e1 e2 e3 - 9 e3 ) f1  f2 + e3  f1

     Búsqueda del polinomio cuyas raíces son la suma a+u o a es la raíz
     de z^2 - e1* z + e2 y u es la raíz de z^2 - f1* z + f2

          (%i1) ratsimp (direct ([z^2  - e1* z + e2, z^2  - f1* z + f2],
                                    z, a + u, [[u], [a]]));
                 4                    3             2
          (%o1) y  + (- 2 f1 - 2 e1) y  + (2 f2 + f1  + 3 e1 f1 + 2 e2

               2   2                              2               2
           + e1 ) y  + ((- 2 f1 - 2 e1) f2 - e1 f1  + (- 2 e2 - e1 ) f1

                            2                     2            2
           - 2 e1 e2) y + f2  + (e1 f1 - 2 e2 + e1 ) f2 + e2 f1  + e1 e2 f1

               2
           + e2

     La función 'direct' acepta dos indicadores: 'elementaires'
     (elementales) y 'puissances' (potenciales, que es el valor por
     defecto) que permiten hacer la descomposición de los polinomios
     simétricos que aparezcan en los cálculos en funciones simétricas
     elementales o en funciones potenciales, respectivamente.

     Funciones de 'sym' utilizadas en esta función:

     'multi_orbit'(por tanto 'orbit'),'pui_direct', 'multi_elem' (por
     tanto 'elem'), 'multi_pui' (por tanto 'pui'), 'pui2ele', 'ele2pui'
     (si al indicador 'direct' se le asignó 'puissances').

 -- Función: ele2comp (<m>, <l>)
     Pasa las funciones simétricas elementales a funciones completas, de
     forma similar a 'comp2ele' y 'comp2pui'.

     Otras funciones para cambio de bases son:

     'comp2ele', 'comp2pui', 'ele2pui', 'elem', 'mon2schur',
     'multi_elem', 'multi_pui', 'pui', 'pui2comp', 'pui2ele', 'puireduc'
     y 'schur2comp'.

 -- Función: ele2polynome (<l>, <z>)
     Devuelve el polinomio en <z> en el que las funciones simétricas
     elementales de las raíces son las de la lista <l>.  '<l> = [<n>,
     <e_1>, ..., <e_n>]', donde <n> es el grado del polinomio y <e_i> la
     <i>-ésima función simétrica elemental.

          (%i1) ele2polynome ([2, e1, e2], z);
                                    2
          (%o1)                    z  - e1 z + e2
          (%i2) polynome2ele (x^7 - 14*x^5 + 56*x^3  - 56*x + 22, x);
          (%o2)          [7, 0, - 14, 0, 56, 0, - 56, - 22]
          (%i3) ele2polynome ([7, 0, -14, 0, 56, 0, -56, -22], x);
                            7       5       3
          (%o3)            x  - 14 x  + 56 x  - 56 x + 22

     La función recíproca es 'polynome2ele (<P>, <z>)'

     Véanse también 'polynome2ele' y 'pui2polynome'.

 -- Función: ele2pui (<m>, <l>)
     Pasa las funciones simétricas elementales a funciones completas, de
     forma similar a 'comp2ele' y 'comp2comp'.

     Otras funciones para cambio de bases son:

     'comp2ele', 'comp2pui', 'ele2comp', 'elem', 'mon2schur',
     'multi_elem', 'multi_pui', 'pui', 'pui2comp', 'pui2ele', 'puireduc'
     y 'schur2comp'.

 -- Función: elem (<ele>, <sym>, <lvar>)
     Descompone el polinomio simétrico <sym> con las variables continuas
     de la lista <lvar> en las funciones simétricas elementales
     contenidas en la lista <ele>.  El primer elemento de la lista <ele>
     almacena el cardinal del alfabeto, en caso de que exista; en caso
     contrario se le da como valor el grado del polinomio <sym>.  Si
     faltan valores en la lista <ele>, ésta se completará con valores
     formales del tipo "ei".  El polinomio <sym> puede especificarse de
     tres formas diferentes: contraído (en cuyo caso 'elem' debe valer
     1, que es el valor por defecto), particionado ('elem' valdrá 3) o
     extendido (por ejemplo, el polinomio completo) (en este caso,
     'elem' valdrá 2).  La utilización de la función 'pui' se hace
     siguiendo este mismo modelo.

     Con un alfabeto de cardinal 3 con <e1>, la primera función
     simétrica elemental valiendo 7, el polinomio simétrico de tres
     variables cuya forma contraída (aquí dependiendo solamente de dos
     de sus variables) es ^4-2*x*y, se descompone en funciones
     simétricas elementales:

          (%i1) elem ([3, 7], x^4 - 2*x*y, [x, y]);
          (%o1) 7 (e3 - 7 e2 + 7 (49 - e2)) + 21 e3

                                                   + (- 2 (49 - e2) - 2) e2
          (%i2) ratsimp (%);
                                        2
          (%o2)             28 e3 + 2 e2  - 198 e2 + 2401

     Otras funciones para cambio de bases son: 'comp2ele', 'comp2pui',
     'ele2comp', 'ele2pui', 'mon2schur', 'multi_elem', 'multi_pui',
     'pui', 'pui2comp', 'pui2ele', 'puireduc' y 'schur2comp'.

 -- Función: explose (<pc>, <lvar>)
     Devuelve el polinomio simétrico asociado a la forma contraída <pc>.
     La lista <lvar> contiene las variables.

          (%i1) explose (a*x + 1, [x, y, z]);
          (%o1)                  a z + a y + a x + 1

     Otras funciones para efectuar cambios de representación son:
     'contract', 'cont2part', 'part2cont', 'partpol', 'tcontract' y
     'tpartpol'.

 -- Función: kostka (<part_1>, <part_2>)
     Función escrita por P. Espert, calcula el número de Kostka asociado
     a las particiones <part_1> y <part_2>.

          (%i1) kostka ([3, 3, 3], [2, 2, 2, 1, 1, 1]);
          (%o1)                           6

 -- Función: lgtreillis (<n>, <m>)
     Devuelve la lista de particiones de peso <n> y longitud <m>.

          (%i1) lgtreillis (4, 2);
          (%o1)                   [[3, 1], [2, 2]]

     Véanse también 'ltreillis', 'treillis' y 'treinat'.

 -- Función: ltreillis (<n>, <m>)
     Devuelve la lista de particiones de peso <n> y longitud menor o
     igual que <m>.

          (%i1) ltreillis (4, 2);
          (%o1)               [[4, 0], [3, 1], [2, 2]]

     Véanse tambiént 'lgtreillis', 'treillis' y 'treinat'.

 -- Función: mon2schur (<l>)
     La lista <l> representa la función de Schur S_<l>: Se tiene <l> =
     [<i_1>, <i_2>, ..., <i_q>] con <i_1> <= <i_2> <= ...  <= <i_q>.  La
     función de Schur es S_[<i_1>, <i_2>, ..., <i_q>], el menor de la
     matriz infinita (h_{i-j}) <i> >= 1, <j> >= 1 compuesto de las <q>
     primeras filas y columnas <i_1> + 1, <i_2> + 2, ..., <i_q> + <q>.

     Se ha escrito esta función de Schur en función de las formas
     monomiales utilizando las funciones 'treinat' y 'kostka'.  La forma
     devuelta es un polinomio simétrico en una de sus representaciones
     contraídas con las variables <x_1>, <x_2>, ...

          (%i1) mon2schur ([1, 1, 1]);
          (%o1)                       x1 x2 x3
          (%i2) mon2schur ([3]);
                                            2        3
          (%o2)                x1 x2 x3 + x1  x2 + x1
          (%i3) mon2schur ([1, 2]);
                                                2
          (%o3)                  2 x1 x2 x3 + x1  x2

     Para 3 variables se tendrá:

             2 x1 x2 x3 + x1^2 x2 + x2^2 x1 + x1^2 x3 + x3^2 x1
              + x2^2 x3 + x3^2 x2

     Otras funciones para cambio de bases son:

     'comp2ele', 'comp2pui', 'ele2comp', 'ele2pui', 'elem',
     'multi_elem', 'multi_pui', 'pui', 'pui2comp', 'pui2ele', 'puireduc'
     y 'schur2comp'.

 -- Función: multi_elem (<l_elem>, <multi_pc>, <l_var>)
     Descompone un polinomio multisimétrico sobre una forma
     multicontraída <multi_pc> en los grupos de variables contenidas en
     la lista de listas <l_var> sobre los grupos de funciones simétricas
     elementales contenidas en <l_elem>.

          (%i1) multi_elem ([[2, e1, e2], [2, f1, f2]], a*x + a^2 + x^3,
                [[x, y], [a, b]]);
                                                            3
          (%o1)         - 2 f2 + f1 (f1 + e1) - 3 e1 e2 + e1
          (%i2) ratsimp (%);
                                   2                       3
          (%o2)         - 2 f2 + f1  + e1 f1 - 3 e1 e2 + e1

     Otras funciones para cambio de bases son:

     'comp2ele', 'comp2pui', 'ele2comp', 'ele2pui', 'elem', 'mon2schur',
     'multi_pui', 'pui', 'pui2comp', 'pui2ele', 'puireduc' y
     'schur2comp'.

 -- Función: multi_orbit (<P>, [<lvar_1>, <lvar_2>, ..., <lvar_p>])
     <P> es un polinomio en el conjunto de variables contenidas en las
     listas <lvar_1>, <lvar_2>, ..., <lvar_p>.  Esta función restablece
     la órbita del polinomio <P> sobre la acción del producto de los
     grupos simétricos de los conjuntos de variables representadas por
     esas <p> listas.

          (%i1) multi_orbit (a*x + b*y, [[x, y], [a, b]]);
          (%o1)                [b y + a x, a y + b x]
          (%i2) multi_orbit (x + y + 2*a, [[x, y], [a, b, c]]);
          (%o2)        [y + x + 2 c, y + x + 2 b, y + x + 2 a]

     Véase también 'orbit' para la acción de un solo grupo simérico.

 -- Función: multi_pui
     Es a la función 'pui' lo que la función 'multi_elem' es a la
     función 'elem'.

          (%i1) multi_pui ([[2, p1, p2], [2, t1, t2]], a*x + a^2 + x^3,
                [[x, y], [a, b]]);
                                                      3
                                          3 p1 p2   p1
          (%o1)              t2 + p1 t1 + ------- - ---
                                             2       2

 -- Función: multinomial (<r>, <part>)
     El argumento <r> es el peso de la partición <part>.  Esta función
     calcula el coeficiente multinomial asociado: si las partes de las
     particiones <part> son <i_1>, <i_2>, ..., <i_k>, el resultado de
     'multinomial' es '<r>!/(<i_1>! <i_2>! ... <i_k>!)'.

 -- Función: multsym (<ppart_1>, <ppart_2>, <n>)
     Calcula el producto de dos polinomios simétricos de <n> variables
     operando solamente con el módulo de la acción del grupo simétrico
     de orden <n>.  Los polinomios están en su representación
     particionada.

     Sean los dos polinomios simétricos en 'x' e 'y': '3*(x + y) +
     2*x*y' y '5*(x^2 + y^2)' cuyas formas particionadas son '[[3, 1],
     [2, 1, 1]]' y '[[5, 2]]', respectivamente; el producto de ambos
     será:

          (%i1) multsym ([[3, 1], [2, 1, 1]], [[5, 2]], 2);
          (%o1)         [[10, 3, 1], [15, 3, 0], [15, 2, 1]]

     o sea, '10*(x^3*y + y^3*x) + 15*(x^2*y + y^2*x) + 15*(x^3 + y^3)'.

     Funciones de cambio de representación de un polinomio simétrico:

     'contract', 'cont2part', 'explose', 'part2cont', 'partpol',
     'tcontract' y 'tpartpol'.

 -- Función: orbit (<P>, <lvar>)
     Calcula la órbita de un polinomio <P> en las variables de la lista
     <lvar> bajo la acción del grupo simétrico del conjunto de variables
     contenidas en la lista <lvar>.

          (%i1) orbit (a*x + b*y, [x, y]);
          (%o1)                [a y + b x, b y + a x]
          (%i2) orbit (2*x + x^2, [x, y]);
                                  2         2
          (%o2)                 [y  + 2 y, x  + 2 x]

     Véase también 'multi_orbit' para la acción de un producto de grupos
     simétricos sobre un polinomio.

 -- Función: part2cont (<ppart>, <lvar>)
     Transforma un polinomio simétrico de su forma particionada a su
     forma contraída.  La forma contraída se devuelve con las variables
     contenidas en <lvar>.

          (%i1) part2cont ([[2*a^3*b, 4, 1]], [x, y]);
                                        3    4
          (%o1)                      2 a  b x  y

     Otras funciones para efectuar cambios de representación son:

     'contract', 'cont2part', 'explose', 'partpol', 'tcontract' y
     'tpartpol'.

 -- Función: partpol (<psym>, <lvar>)
     Restablece la representación particionada del polinomio simétrico
     <psym> de variables en <lvar>.

          (%i1) partpol (-a*(x + y) + 3*x*y, [x, y]);
          (%o1)               [[3, 1, 1], [- a, 1, 0]]

     Otras funciones para efectuar cambios de representación son:

     'contract', 'cont2part', 'explose', 'part2cont', 'tcontract' y
     'tpartpol'.

 -- Función: permut (<l>)
     Devuelve la lista de permutaciones de la lista <l>.

 -- Función: polynome2ele (<P>, <x>)
     Devuelve la lista '<l> = [<n>, <e_1>, ..., <e_n>]', en la que <n>
     es el grado del polinomio <P> de variable <x> y <e_i> es la
     <i>-ésima función simétrica elemental de las raíces de <P>.

          (%i1) polynome2ele (x^7 - 14*x^5 + 56*x^3 - 56*x + 22, x);
          (%o1)          [7, 0, - 14, 0, 56, 0, - 56, - 22]
          (%i2) ele2polynome ([7, 0, -14, 0, 56, 0, -56, -22], x);
                            7       5       3
          (%o2)            x  - 14 x  + 56 x  - 56 x + 22

     La función recíproca es 'ele2polynome (<l>, <x>)'.

 -- Función: prodrac (<l>, <k>)
     Siendo <l> una lista que contiene las funciones simétricas
     elementales sobre un conjunto <A>, la función 'prodrac' calcula el
     polinomio cuyas raíces son los productos <k> a <k> de los elementos
     de <A>.

 -- Función: pui (<l>, <sym>, <lvar>)
     Descompone el polinomio simétrico <sym>, cuyas variables son las
     contenidas en <lvar>, en las funciones potenciales contenidas en la
     lista <l>.  El primer elemento de la lista <l> almacena el cardinal
     del alfabeto, en caso de que exista; en caso contrario se le da el
     grado del polinomio <sym>.  Si faltan los valores de la lista <l>,
     en su lugar serán colocados valores formales del tipo "pi".  El
     polinomio <sym> puede especificarse de tres formas diferentes:
     contraído (en cuyo caso 'pui' debe valer 1, que es el valor por
     defecto), particionado ('pui' valdrá 3) o extendido (por ejemplo,
     el polinomio completo) (en este caso, 'pui' valdrá 2).  La
     utilización de la función 'elem' se hace siguiendo este mismo
     modelo.

          (%i1) pui;
          (%o1)                           1
          (%i2) pui ([3, a, b], u*x*y*z, [x, y, z]);
                                 2
                             a (a  - b) u   (a b - p3) u
          (%o2)              ------------ - ------------
                                  6              3
          (%i3) ratsimp (%);
                                                 3
                                (2 p3 - 3 a b + a ) u
          (%o3)                 ---------------------
                                          6

     Otras funciones para cambio de bases son: 'comp2ele', 'comp2pui',
     'ele2comp', 'ele2pui', 'elem', 'mon2schur', 'multi_elem',
     'multi_pui', 'pui2comp', 'pui2ele', 'puireduc' y 'schur2comp'.

 -- Función: pui2comp (<n>, <lpui>)
     Devuelve la lista de las <n> primeras funciones completas (con el
     cardinal en primer lugar) en función de las funciones potenciales
     dadas en la lista <lpui>.  Si la lista <lpui> estuviese vacía, el
     cardinal sería <N>; si no estuviese vacía, se tomaría como cardinal
     su primer elemento, de forma similar a como se procede en
     'comp2ele' y en 'comp2pui'.

          (%i1) pui2comp (2, []);
                                                 2
                                          p2 + p1
          (%o1)                   [2, p1, --------]
                                             2
          (%i2) pui2comp (3, [2, a1]);
                                                      2
                                           a1 (p2 + a1 )
                                   2  p3 + ------------- + a1 p2
                            p2 + a1              2
          (%o2)     [2, a1, --------, --------------------------]
                               2                  3
          (%i3) ratsimp (%);
                                      2                     3
                               p2 + a1   2 p3 + 3 a1 p2 + a1
          (%o3)        [2, a1, --------, --------------------]
                                  2               6

     Otras funciones para cambio de bases son: 'comp2ele', 'comp2pui',
     'ele2comp', 'ele2pui', 'elem', 'mon2schur', 'multi_elem',
     'multi_pui', 'pui', 'pui2ele', 'puireduc' y 'schur2comp'.

 -- Función: pui2ele (<n>, <lpui>)
     Transforma las funciones potenciales a funciones simétricas
     elementales.  Si la variable global 'pui2ele' vale 'girard', se
     recupera la lista de funciones simétricas elementales de 1 <n>, y
     si es igual a 'close', se recupera la <n>-ésima función simétrica
     elemental.

     Otras funciones para cambio de bases son: 'comp2ele', 'comp2pui',
     'ele2comp', 'ele2pui', 'elem', 'mon2schur', 'multi_elem',
     'multi_pui', 'pui', 'pui2comp', 'puireduc' y 'schur2comp'.

 -- Función: pui2polynome (<x>, <lpui>)
     Calcula el polinomio en <x> cuyas raíces tienen como funciones
     potenciales las dadas en la lista <lpui>.

          (%i1) pui;
          (%o1)                           1
          (%i2) kill(labels);
          (%o0)                         done
          (%i1) polynome2ele (x^3 - 4*x^2 + 5*x - 1, x);
          (%o1)                     [3, 4, 5, 1]
          (%i2) ele2pui (3, %);
          (%o2)                     [3, 4, 6, 7]
          (%i3) pui2polynome (x, %);
                                  3      2
          (%o3)                  x  - 4 x  + 5 x - 1

     Véanse también 'polynome2ele' y 'ele2polynome'.

 -- Función: pui_direct (<orbite>, [<lvar_1>, ..., <lvar_n>], [<d_1>,
          <d_2>, ..., <d_n>])
     Sea <f> un polinomio en <n> bloques de variables <lvar_1>, ...,
     <lvar_n>.  Sea <c_i> el número de variables en <lvar_i> y <SC> el
     producto de los <n> grupos simétricos de grados <c_1>, ..., <c_n>,
     que actúan sobre <f>.  La lista <orbite> es la órbita, representada
     por '<SC>(<f>)', de la función <f> sobre la acción de <SC>, la cual
     puede ser obtenida por medio de la función 'multi_orbit'.  Los
     valores 'd_i' son enteros tales que <c_1> <= <d_1>, <c_2> <= <d_2>,
     ..., <c_n> <= <d_n>.  Por último, sea <SD> el producto de los
     grupos simétricos <S_d1> x <S_d2> x ...  x <S_dn>.

     La función 'pui_direct' devuelve las <n> primeras funciones
     potenciales de '<SD>(<f>)' deducidas de las funciones potenciales
     de '<SC>(<f>)', siendo <n> el cardinal de '<SD>(<f>)'.

     El resultado se devuelve en la forma multicontraída respecto de
     <SD>.

          (%i1) l: [[x, y], [a, b]];
          (%o1)                   [[x, y], [a, b]]
          (%i2) pui_direct (multi_orbit (a*x + b*y, l), l, [2, 2]);
                                                 2  2
          (%o2)               [a x, 4 a b x y + a  x ]
          (%i3) pui_direct (multi_orbit (a*x + b*y, l), l, [3, 2]);
                                       2  2     2    2        3  3
          (%o3) [2 a x, 4 a b x y + 2 a  x , 3 a  b x  y + 2 a  x ,

              2  2  2  2      3    3        4  4
          12 a  b  x  y  + 4 a  b x  y + 2 a  x ,

              3  2  3  2      4    4        5  5
          10 a  b  x  y  + 5 a  b x  y + 2 a  x ,

              3  3  3  3       4  2  4  2      5    5        6  6
          40 a  b  x  y  + 15 a  b  x  y  + 6 a  b x  y + 2 a  x ]
          (%i4) pui_direct ([y + x + 2*c, y + x + 2*b, y + x + 2*a],
                [[x, y], [a, b, c]], [2, 3]);
                                       2              2
          (%o4) [3 x + 2 a, 6 x y + 3 x  + 4 a x + 4 a ,

                           2                   3        2       2        3
                        9 x  y + 12 a x y + 3 x  + 6 a x  + 12 a  x + 8 a ]

 -- Función: puireduc (<n>, <lpui>)
     Siendo <lpui> una lista en la que el primer elemento es un entero
     <m>, 'puireduc' devuelve las <n> primeras funciones potenciales en
     función de las <m> primeras.

          (%i1) puireduc (3, [2]);
                                                   2
                                             p1 (p1  - p2)
          (%o1)          [2, p1, p2, p1 p2 - -------------]
                                                   2
          (%i2) ratsimp (%);
                                                     3
                                         3 p1 p2 - p1
          (%o2)              [2, p1, p2, -------------]
                                               2

 -- Función: resolvante (<P>, <x>, <f>, [<x_1>, ..., <x_d>])
     Calcula la resolvente del polinomio <P> de variable <x> y grado <n>
     >= <d> por la función <f> de variables <x_1>, ..., <x_d>.  Para
     mejorar los cálculos, es importante no incluir en la lista '[<x_1>,
     ..., <x_d>]' las variables que no intervienen en la función de
     transformación <f>.

     Con el fin de hacer más eficaces los cálculos, se puede asignar a
     'resolvante' un indicador que permita seleccionar el algoritmo más
     apropiado:

        * 'unitaire',
        * 'lineaire',
        * 'alternee',
        * 'somme',
        * 'produit',
        * 'cayley',
        * 'generale'.

          (%i1) resolvante: unitaire$
          (%i2) resolvante (x^7 - 14*x^5 + 56*x^3 - 56*x + 22, x, x^3 - 1,
                [x]);

          " resolvante unitaire " [7, 0, 28, 0, 168, 0, 1120, - 154, 7840,
                                   - 2772, 56448, - 33880,

          413952, - 352352, 3076668, - 3363360, 23114112, - 30494464,

          175230832, - 267412992, 1338886528, - 2292126760]
            3       6      3       9      6      3
          [x  - 1, x  - 2 x  + 1, x  - 3 x  + 3 x  - 1,

           12      9      6      3       15      12       9       6      3
          x   - 4 x  + 6 x  - 4 x  + 1, x   - 5 x   + 10 x  - 10 x  + 5 x

                 18      15       12       9       6      3
           - 1, x   - 6 x   + 15 x   - 20 x  + 15 x  - 6 x  + 1,

           21      18       15       12       9       6      3
          x   - 7 x   + 21 x   - 35 x   + 35 x  - 21 x  + 7 x  - 1]
          [- 7, 1127, - 6139, 431767, - 5472047, 201692519, - 3603982011]
                 7      6        5         4          3           2
          (%o2) y  + 7 y  - 539 y  - 1841 y  + 51443 y  + 315133 y

                                                        + 376999 y + 125253
          (%i3) resolvante: lineaire$
          (%i4) resolvante (x^4 - 1, x, x1 + 2*x2 + 3*x3, [x1, x2, x3]);

          " resolvante lineaire "
                 24       20         16            12             8
          (%o4) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i5) resolvante: general$
          (%i6) resolvante (x^4 - 1, x, x1 + 2*x2 + 3*x3, [x1, x2, x3]);

          " resolvante generale "
                 24       20         16            12             8
          (%o6) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i7) resolvante (x^4 - 1, x, x1 + 2*x2 + 3*x3, [x1, x2, x3, x4]);

          " resolvante generale "
                 24       20         16            12             8
          (%o7) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i8) direct ([x^4 - 1], x, x1 + 2*x2 + 3*x3, [[x1, x2, x3]]);
                 24       20         16            12             8
          (%o8) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i9) resolvante :lineaire$
          (%i10) resolvante (x^4 - 1, x, x1 + x2 + x3, [x1, x2, x3]);

          " resolvante lineaire "
                                        4
          (%o10)                       y  - 1
          (%i11) resolvante: symetrique$
          (%i12) resolvante (x^4 - 1, x, x1 + x2 + x3, [x1, x2, x3]);

          " resolvante symetrique "
                                        4
          (%o12)                       y  - 1
          (%i13) resolvante (x^4 + x + 1, x, x1 - x2, [x1, x2]);

          " resolvante symetrique "
                                     6      2
          (%o13)                    y  - 4 y  - 1
          (%i14) resolvante: alternee$
          (%i15) resolvante (x^4 + x + 1, x, x1 - x2, [x1, x2]);

          " resolvante alternee "
                      12      8       6        4        2
          (%o15)     y   + 8 y  + 26 y  - 112 y  + 216 y  + 229
          (%i16) resolvante: produit$
          (%i17) resolvante (x^7 - 7*x + 3, x, x1*x2*x3, [x1, x2, x3]);

          " resolvante produit "
                  35      33         29        28         27        26
          (%o17) y   - 7 y   - 1029 y   + 135 y   + 7203 y   - 756 y

                   24           23          22            21           20
           + 1323 y   + 352947 y   - 46305 y   - 2463339 y   + 324135 y

                    19           18             17              15
           - 30618 y   - 453789 y   - 40246444 y   + 282225202 y

                       14              12             11            10
           - 44274492 y   + 155098503 y   + 12252303 y   + 2893401 y

                        9            8            7             6
           - 171532242 y  + 6751269 y  + 2657205 y  - 94517766 y

                      5             3
           - 3720087 y  + 26040609 y  + 14348907
          (%i18) resolvante: symetrique$
          (%i19) resolvante (x^7 - 7*x + 3, x, x1*x2*x3, [x1, x2, x3]);

          " resolvante symetrique "
                  35      33         29        28         27        26
          (%o19) y   - 7 y   - 1029 y   + 135 y   + 7203 y   - 756 y

                   24           23          22            21           20
           + 1323 y   + 352947 y   - 46305 y   - 2463339 y   + 324135 y

                    19           18             17              15
           - 30618 y   - 453789 y   - 40246444 y   + 282225202 y

                       14              12             11            10
           - 44274492 y   + 155098503 y   + 12252303 y   + 2893401 y

                        9            8            7             6
           - 171532242 y  + 6751269 y  + 2657205 y  - 94517766 y

                      5             3
           - 3720087 y  + 26040609 y  + 14348907
          (%i20) resolvante: cayley$
          (%i21) resolvante (x^5 - 4*x^2 + x + 1, x, a, []);

          " resolvante de Cayley "
                  6       5         4          3            2
          (%o21) x  - 40 x  + 4080 x  - 92928 x  + 3772160 x  + 37880832 x

                                                                 + 93392896

     Para la resolvente de Cayley, los dos últimos argumentos son
     neutros y el polinomio dado en el argumento debe ser necesariamente
     de grado 5.

     Véanse también:
     'resolvante_bipartite', 'resolvante_produit_sym',
     'resolvante_unitaire', 'resolvante_alternee1', 'resolvante_klein',
     'resolvante_klein3', 'resolvante_vierer', 'resolvante_diedrale'.

 -- Función: resolvante_alternee1 (<P>, <x>)
     Calcula la transformación de '<P>(<x>)' de grado <n> por la función
     $\prod_{1\leq i<j\leq n-1} (x_i-x_j)$.

     Véanse también:
     'resolvante_produit_sym', 'resolvante_unitaire',
     'resolvante' , 'resolvante_klein', 'resolvante_klein3',
     'resolvante_vierer', 'resolvante_diedrale', 'resolvante_bipartite'.

 -- Función: resolvante_bipartite (<P>, <x>)
     Calcula la transformación de '<P>(<x>)' de grado <n> (<n> par) por
     la función $x_1x_2\ldots x_{n/2}+x_{n/2+1}\ldotsx_n$

          (%i1) resolvante_bipartite (x^6 + 108, x);
                        10        8           6             4
          (%o1)        y   - 972 y  + 314928 y  - 34012224 y

     Véanse también:
     'resolvante_produit_sym', 'resolvante_unitaire',
     'resolvante', 'resolvante_klein', 'resolvante_klein3',
     'resolvante_vierer', 'resolvante_diedrale', 'resolvante_alternee1'.

 -- Función: resolvante_diedrale (<P>, <x>)
     Calcula la transformación de '<P>(<x>)' por la función '<x_1> <x_2>
     + <x_3> <x_4>'.

          (%i1) resolvante_diedrale (x^5 - 3*x^4 + 1, x);
                 15       12       11       10        9         8         7
          (%o1) x   - 21 x   - 81 x   - 21 x   + 207 x  + 1134 x  + 2331 x

                  6         5          4          3          2
           - 945 x  - 4970 x  - 18333 x  - 29079 x  - 20745 x  - 25326 x

           - 697

     Véanse también:
     'resolvante_produit_sym', 'resolvante_unitaire',
     'resolvante_alternee1', 'resolvante_klein', 'resolvante_klein3',
     'resolvante_vierer', 'resolvante'.

 -- Función: resolvante_klein (<P>, <x>)
     Calcula la transformación de '<P>(<x>)' por la función '<x_1> <x_2>
     <x_4> + <x_4>'.

     Véanse también:
     'resolvante_produit_sym', 'resolvante_unitaire',
     'resolvante_alternee1', 'resolvante', 'resolvante_klein3',
     'resolvante_vierer', 'resolvante_diedrale'.

 -- Función: resolvante_klein3 (<P>, <x>)
     Calcula la transformación de '<P>(<x>)' por la función '<x_1> <x_2>
     <x_4> + <x_4>'.

     Véanse también:
     'resolvante_produit_sym', 'resolvante_unitaire',
     'resolvante_alternee1', 'resolvante_klein', 'resolvante',
     'resolvante_vierer', 'resolvante_diedrale'.

 -- Función: resolvante_produit_sym (<P>, <x>)
     Calcula la lista de todas las resolventes producto del polinomio
     '<P>(<x>)'.

          (%i1) resolvante_produit_sym (x^5 + 3*x^4 + 2*x - 1, x);
                  5      4             10      8       7       6       5
          (%o1) [y  + 3 y  + 2 y - 1, y   - 2 y  - 21 y  - 31 y  - 14 y

              4       3      2       10      8       7    6       5       4
           - y  + 14 y  + 3 y  + 1, y   + 3 y  + 14 y  - y  - 14 y  - 31 y

                 3      2       5      4
           - 21 y  - 2 y  + 1, y  - 2 y  - 3 y - 1, y - 1]
          (%i2) resolvante: produit$
          (%i3) resolvante (x^5 + 3*x^4 + 2*x - 1, x, a*b*c, [a, b, c]);

          " resolvante produit "
                 10      8       7    6        5       4       3     2
          (%o3) y   + 3 y  + 14 y  - y  - 14 y  - 31 y  - 21 y  - 2 y  + 1

     Véanse también:
     'resolvante', 'resolvante_unitaire',
     'resolvante_alternee1', 'resolvante_klein',
     'resolvante_klein3', 'resolvante_vierer',
     'resolvante_diedrale'.

 -- Función: resolvante_unitaire (<P>, <Q>, <x>)
     Calcula la resolvente del polinomio '<P>(<x>)' por el polinomio
     '<Q>(<x>)'.

     Véanse también:
     'resolvante_produit_sym', 'resolvante',
     'resolvante_alternee1', 'resolvante_klein', 'resolvante_klein3',
     'resolvante_vierer', 'resolvante_diedrale'.

 -- Función: resolvante_vierer (<P>, <x>)
     Calcula la transformación de '<P>(<x>)' por la función '<x_1> <x_2>
     - <x_3> <x_4>'.

     Véanse también:
     'resolvante_produit_sym', 'resolvante_unitaire',
     'resolvante_alternee1', 'resolvante_klein', 'resolvante_klein3',
     'resolvante', 'resolvante_diedrale'.

 -- Función: schur2comp (<P>, <l_var>)
     <P> es un polinomio de variables contenidas en la lista <l_var>.
     Cada una de las variables de <l_var> representa una función
     simétrica completa.  La <i>-ésima función simétrica completa de
     <l_var> se representa como la concatenación de la letra 'h' con el
     entero <i>: 'h<i>'.  La función 'schur2comp' devuelve la expresión
     de <P> en función de las funciones de Schur.

          (%i1) schur2comp (h1*h2 - h3, [h1, h2, h3]);
          (%o1)                         s
                                         1, 2
          (%i2) schur2comp (a*h3, [h3]);
          (%o2)                         s  a
                                         3

 -- Función: somrac (<l>, <k>)
     Si la lista <l> contiene las funciones simétricas elementales de un
     polinomio <P>, la función 'somrac' calcula el polinomio cuyas
     raíces son las sumas <k> a <k> de las raíces de <P>.

     Véase también 'prodrac'.

 -- Función: tcontract (<pol>, <lvar>)
     Comprueba si el polinomio <pol> es simétrico en las variable
     contenidas en la lista <lvar>.  En caso afirmativo, devuelve una
     forma contraída tal como lo hace la función 'contract'.

     Otras funciones para efectuar cambios de representación son:
     'contract', 'cont2part', 'explose', 'part2cont', 'partpol' y
     'tpartpol'.

 -- Función: tpartpol (<pol>, <lvar>)
     Comprueba si el polinomio <pol> es simétrico en las variable
     contenidas en la lista <lvar>.  En caso afirmativo, devuelve una
     forma particionada tal como lo hace la función 'partpol'.

     Otras funciones para efectuar cambios de representación son:
     'contract', 'cont2part', 'explose', 'part2cont', 'partpol' y
     'tcontract'.

 -- Función: treillis (<n>)
     Devuelve todas las particiones de pesos <n>.

          (%i1) treillis (4);
          (%o1)    [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]

     Véanse también 'lgtreillis', 'ltreillis' y 'treinat'.

 -- Función: treinat (<part>)
     Devuelve la lista de las particiones inferiores de la partición
     <part> en su orden natural.

          (%i1) treinat ([5]);
          (%o1)                         [[5]]
          (%i2) treinat ([1, 1, 1, 1, 1]);
          (%o2) [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1],

                                                           [1, 1, 1, 1, 1]]
          (%i3) treinat ([3, 2]);
          (%o3)                 [[5], [4, 1], [3, 2]]

     Véanse también 'lgtreillis', 'ltreillis' y 'treillis'.


File: maxima.info,  Node: Grupos,  Next: Entorno de Ejecución,  Prev: Simetrías,  Up: Top

31 Grupos
*********

* Menu:

* Funciones y variables para grupos::


File: maxima.info,  Node: Funciones y variables para grupos,  Prev: Grupos,  Up: Grupos

31.1 Funciones y variables para grupos
======================================

 -- Función: todd_coxeter (<relaciones>, <subgrupo>)
 -- Función: todd_coxeter (<relaciones>)

     Busca el orden de G/H donde G es el módulo del Grupo Libre de
     <relations>, y H es el subgrupo de G generado por 'subgrupo'.
     'subgrupo' es un argumento opcional, cuyo valor por defecto es [].

     En este proceso se obtiene una tabla de multiplicación para la
     acción correcta de G sobre G/H, donde los co-cojuntos son
     enumerados [H,Hg2,Hg3,...].  Esto puede ser observado internamente
     en el 'todd_coxeter_state'.

     Ejemplo:

          (%i1) symet(n):=create_list(
                  if (j - i) = 1 then (p(i,j))^^3 else
                      if (not i = j) then (p(i,j))^^2 else
                          p(i,i) , j, 1, n-1, i, 1, j);
                                                                 <3>
          (%o1) symet(n) := create_list(if j - i = 1 then p(i, j)

                                          <2>
           else (if not i = j then p(i, j)    else p(i, i)), j, 1, n - 1,

          i, 1, j)
          (%i2) p(i,j) := concat(x,i).concat(x,j);
          (%o2)        p(i, j) := concat(x, i) . concat(x, j)
          (%i3) symet(5);
                   <2>           <3>    <2>           <2>           <3>
          (%o3) [x1   , (x1 . x2)   , x2   , (x1 . x3)   , (x2 . x3)   ,

                      <2>           <2>           <2>           <3>    <2>
                    x3   , (x1 . x4)   , (x2 . x4)   , (x3 . x4)   , x4   ]
          (%i4) todd_coxeter(%o3);

          Rows tried 426
          (%o4)                          120
          (%i5) todd_coxeter(%o3,[x1]);

          Rows tried 213
          (%o5)                          60
          (%i6) todd_coxeter(%o3,[x1,x2]);

          Rows tried 71
          (%o6)                          20


File: maxima.info,  Node: Entorno de Ejecución,  Next: Miscelánea de opciones,  Prev: Grupos,  Up: Top

32 Entorno de Ejecución
***********************

* Menu:

* Introducción al entorno de ejecución::   
* Interrupciones::  
* Funciones y variables para el entorno de ejecución::


File: maxima.info,  Node: Introducción al entorno de ejecución,  Next: Interrupciones,  Prev: Entorno de Ejecución,  Up: Entorno de Ejecución

32.1 Introducción al entorno de ejecución
=========================================

El fichero 'maxima-init.mac' se carga automáticamente cada vez que se
empieza a ejecutar Maxima.  Se puede utilizar 'maxima-init.mac' para
personalizar el entorno de Maxima.  Si existe, 'maxima-init.mac' se
almacena normalmente en el directorio indicado por 'maxima_userdir',
aunque puede estar alojado en cualquier otro directorio que esté al
alcance de la función 'file_search'.

He aquí un ejemplo de fichero 'maxima-init.mac':

     setup_autoload ("specfun.mac", ultraspherical, assoc_legendre_p);
     showtime:all;

En este ejemplo, 'setup_autoload' le dice a Maxima que cargue en memoria
el fichero 'specfun.mac' si cualquiera de las funciones 'ultraspherical'
o 'assoc_legendre_p' es invocada pero todavía no está definida.  De esta
manera, no es necesario recordar cargar el fichero antes de llamar a las
funciones.

La sentencia 'showtime: all' le dice a Maxima que haga una asignación a
la variable 'showtime'.  El fichero 'maxima-init.mac' puede contener
cualesquiera otras asignaciones o sentencias de Maxima.


File: maxima.info,  Node: Interrupciones,  Next: Funciones y variables para el entorno de ejecución,  Prev: Introducción al entorno de ejecución,  Up: Entorno de Ejecución

32.2 Interrupciones
===================

El usuario puede detener un cómputo que esté consumiendo recursos
excesivos con el carácter ^C (control-C). La acción que se sigue por
defecto es la detención del cómputo y la impresión de otro prompt.  En
este caso, no será posible reiniciar la tarea interrumpida.

Si a la variable Lisp '*debugger-hook*' se le asigna 'nil' haciendo

     :lisp (setq *debugger-hook* nil)

entonces tras recibir ^C, Maxima entra en el depurador de Lisp y el
usuario podrá utilizar el depurador para inspeccionar el entorno Lisp.
La tarea que haya sido interrumpida podrá reiniciarse escribiendo
'continue' en el depurado de Lisp.  La forma de volver a Maxima desde el
depurador de Lisp, que no sea la de permitir la computación hasta la
terminación de la tarea, dependerá de la versión de Lisp.

En sistemas Unix el carácter ^Z (control-Z) hace que Maxima deje de
ejecutarse devolviendo el control al terminal del sistema.  El comando
'fg' hace que la ejecución de Maxima se reanude en el punto que lo dejó.


File: maxima.info,  Node: Funciones y variables para el entorno de ejecución,  Prev: Interrupciones,  Up: Entorno de Ejecución

32.3 Funciones y variables para el entorno de ejecución
=======================================================

 -- Variable del sistema: maxima_tempdir

     La variable 'maxima_tempdir' almacena la ruta del directorio en el
     que Maxima crea ciertos ficheros temporales.  En particular, los
     ficheros temporales para la realización de gráficos se guardan en
     'maxima_tempdir'.

     El valor que inicialmente toma esta variable es el directorio de
     inicio del usuario, si Maxima es capaz de localizarlo; en caso
     contrario, Maxima intenta encontrar un directorio que sea
     aceptable.

     A la variable 'maxima_tempdir' se le puede asignar una cadena de
     caracteres con la ruta del directorio.

 -- Variable del sistema: maxima_userdir

     La variable 'maxima_userdir' almacena la ruta del directorio en el
     que Maxima buscará ficheros Lisp y de Maxima.  Maxima también busca
     en otros directorios, guardando las variables 'file_search_maxima'
     y 'file_search_lisp' la lista completa de búsqueda.

     El valor que inicialmente toma esta variable es el de un
     subdirectorio del directorio de inicio del usuario, si Maxima es
     capaz de localizarlo; en caso contrario, Maxima intenta encontrar
     un directorio que sea aceptable.

     A la variable 'maxima_userdir' se le puede asignar una cadena de
     caracteres con la ruta del directorio.  Sin embargo, cambiando el
     valor de la variable 'maxima_userdir' no se alteran
     'file_search_maxima' ni 'file_search_lisp', cuyos contenidos se
     modifican mediante otro sistema.

 -- Función: room ()
 -- Función: room (true)
 -- Función: room (false)

     Presenta una descrpción del estado de almacenamiento y gestión de
     la pila en Maxima.  La llamada 'room' invoca a la función Lisp
     homónima.

        * 'room ()' prints out a moderate description.
        * 'room (true)' prints out a verbose description.
        * 'room (false)' prints out a terse description.

 -- Función: sstatus (<keyword>, <item>)

     Si <keyword> es el símbolo 'feature', <item> será colocado en la
     lista de propiedades del sistema.  Una vez ejecutado 'sstatus
     (keyword, item)', 'status (feature, item)' devuelve 'true'.  Si
     <keyword> es el símbolo 'nofeature', <item> se borrará de la lista
     de propiedades del sistema.  Esto puede ser de utilidad para los
     autores de paquetes, permitiendo mantener el control sobre las
     propiedades que se han ido estableciendo.

     Véase también 'status'.

 -- Función: status ('feature')
 -- Función: status ('feature', <item>)

     Devuelve información sobre la presencia o ausencia de ciertas
     propiedades dependientes del sistema.

        * 'status (feature)' devuelve una lista con características del
          sistema.  Éstas incluyen la versión de Lisp, tipo de sistema
          operativo, etc.  La lista puede variar de un Lisp a otro.

        * 'status (feature, item)' devuelve 'true' si <item> está en la
          lista de elementos retornados por 'status (feature)' y 'false'
          en otro caso.  La función 'status' no evalúa el argumento
          <item>.  El operador de doble comilla simple, '''', permite la
          evaluación.  Una propiedad cuyo nombre contenga un carácter
          especial debe ser suministrada como un argumento del tipo
          cadena.  Por ejemplo, 'status (feature, "ansi-cl")'.

     Véase también 'sstatus'.

     La variable 'features' contiene una lista de propiedades que se
     aplican a expresiones matemáticas.  Véanse 'features' y 'featurep'
     para más información.

 -- Función: system (<command>)
     Ejecuta la instrucción <command> como un proceso independiente de
     Maxima.  La instrucción se le pasa a la consola del sistema para su
     ejecución.  La función 'system' no está soportada por todos los
     sistemas operativos, pero suele estarlo en todos los entornos Unix
     y similares.

     Suponiendo que '_hist.out' es una lista de frecuencias que se
     quieren representar en un diagrama de barras utilizando el programa
     'xgraph',

          (%i1) (with_stdout("_hist.out",
                     for i:1 thru length(hist) do (
                       print(i,hist[i]))),
                 system("xgraph -bar -brw .7 -nl < _hist.out"));

     A fin de hacer el diagrama y eliminar el archivo temporal
     posteriormente, hágase:

          system("(xgraph -bar -brw .7 -nl < _hist.out;  rm -f _hist.out)&")

 -- Función: time (%o1, %o2, %o3, ...)

     Devuelve una lista de los tiempos, en segundos, que fueron
     necesarios para calcular los resultados de las salidas '%o1',
     '%o2', '%o3', ....  Los tiempos devueltos son estimaciones hechas
     por Maxima del tiempo interno de computación.  La función 'time'
     sólo puede utilizarse para variables correspondientes a líneas de
     salida; para cualquier otro tipo de variables, 'time' devuelve
     'unknown'.

     Hágase 'showtime: true' para que Maxima devuelva el tiempo de
     ejecución de cada línea de salida.

 -- Función: timedate ()
 -- Función: timedate (<T>)

     Sin argumento, 'timedate' devuelve una cadena que representa la
     hora y fecha actuales.  La cadena tiene el formato 'YYYY-MM-DD
     HH:MM:SS[+|-]ZZ:ZZ', donde los campos indicados son: año, mes, día,
     horas, minutos, segundos y número de horas de diferencia con
     respecto a la hora GMT.

     Con argumento, 'timedate(<T>)' devuelve la hora <T> como una cadena
     con formato 'YYYY-MM-DD HH:MM:SS[+|-]ZZ:ZZ'.  <T> se interpreta
     como el número de segundos transcurridos desde la medianoche del
     uno de enero de 1900, tal como lo devuelve 'absolute_real_time'.

     Ejemplos:

     'timedate' sin argumento devuelve una cadena con la hora y fecha
     actuales.

          (%i1) d : timedate ();
          (%o1)                      2010-06-08 04:08:09+01:00
          (%i2) print ("timedate reports current time", d) $
          timedate reports current time 2010-06-08 04:08:09+01:00

     'timedate' con argumento devuelve una cadena que representa al
     propio argumento.

          (%i1) timedate (0);
          (%o1)                      1900-01-01 01:00:00+01:00
          (%i2) timedate (absolute_real_time () - 7*24*3600);
          (%o2)                      2010-06-01 04:19:51+01:00

 -- Función: absolute_real_time ()

     Devuelve el número de segundos transcurridos desde la medianoche
     del 1 de enero de 1900 UTC. Este valor es un número entero
     positivo.

     Véanse también 'elapsed_real_time' y 'elapsed_run_time'.

     Ejemplo:

          (%i1) absolute_real_time ();
          (%o1)                      3385045277
          (%i2) 1900 + absolute_real_time () / (365.25 * 24 * 3600);
          (%o2)                   2007.265612087104

 -- Función: elapsed_real_time ()

     Devuelve los segundos (incluyendo fracciones de segundo)
     transcurridos desde que Maxima se inició (o reinició) la sesión de
     Maxima.  Este valor es un decimal en coma flotante.

     Véanse también 'absolute_real_time' y 'elapsed_run_time'.

     Ejemplo:

          (%i1) elapsed_real_time ();
          (%o1)                       2.559324
          (%i2) expand ((a + b)^500)$
          (%i3) elapsed_real_time ();
          (%o3)                       7.552087

 -- Función: elapsed_run_time ()

     Devuelve una estimación en segundos (incluyendo fracciones de
     segundo) durante los cuales Maxima ha estado realizando cálculos
     desde que se inició (o reinició) la sesión actual.  Este valor es
     un decimal en coma flotante.

     Véanse también 'absolute_real_time' y 'elapsed_real_time'.

     Ejemplo:

          (%i1) elapsed_run_time ();
          (%o1)                         0.04
          (%i2) expand ((a + b)^500)$
          (%i3) elapsed_run_time ();
          (%o3)                         1.26


File: maxima.info,  Node: Miscelánea de opciones,  Next: Reglas y patrones,  Prev: Entorno de Ejecución,  Up: Top

33 Miscelánea de opciones
*************************

* Menu:

* Introducción a la miscelánea de opciones::  
* Share::  
* Funciones y variables para la miscelánea de opciones::


File: maxima.info,  Node: Introducción a la miscelánea de opciones,  Next: Share,  Prev: Miscelánea de opciones,  Up: Miscelánea de opciones

33.1 Introducción a la miscelánea de opciones
=============================================

En esta sección se comentan varias opciones que tienen un efecto global
sobre le comportamiento de Maxima.  También se comentan varias listas,
como la de las funciones definidas por el usuario.


File: maxima.info,  Node: Share,  Next: Funciones y variables para la miscelánea de opciones,  Prev: Introducción a la miscelánea de opciones,  Up: Miscelánea de opciones

33.2 Share
==========

El directorio "share" de Maxima contiene programas y ficheros de interés
para los usuarios de Maxima, pero no forman parte del núcleo de Maxima.
Estos programas se cargan en memoria con llamadas a las funciones 'load'
o 'setup_autoload'.

El código ':lisp *maxima-sharedir*' muestra la localización del
directorio "share" dentro del sistema de ficheros del usuario.

El código 'printfile ("share.usg")' muestra una lista actualizada de
paquetes en "share".  Los usuarios pueden encontrar más información
accediendo directamente a los contenidos del directorio "share".


File: maxima.info,  Node: Funciones y variables para la miscelánea de opciones,  Prev: Share,  Up: Miscelánea de opciones

33.3 Funciones y variables para la miscelánea de opciones
=========================================================

 -- Variable del sistema: askexp
     Cuando se invoca a 'asksign', la expresión que se va a analizar es
     precisamente 'askexp'.

 -- Variable optativa: genindex
     Valor por defecto: 'i'

     La variable 'genindex' es el prefijo alfabético utilizado para
     generar la siguiente variable de sumación en caso de necesidad.

 -- Variable optativa: gensumnum
     Valor por defecto: 0

     La variable 'gensumnum' es el sufijo numérico utilizado para
     generar la siguiente variable de sumación.  Si vale 'false'
     entonces el índice consistirá solamente de 'genindex', sin sufijo
     numérico.

 -- Función: gensym ()
 -- Función: gensym (<x>)

     'gensym()' crea y devuelve una nueva símbolo o variable sin valor
     asignado.

     El nombre del nuevo símbolo está formado por la concatenación de un
     prefijo, cuyo valor por defecto es "g", y de un sufijo, el cual es
     la representación decimal de un número que coincide, por defecto,
     con el valor de un contador interno de Lisp.

     En caso de suministrar el argumento <x>, siendo este una cadena, se
     utilizará como prefijo en lugar de "g", lo cual tendrá efecto sólo
     para esta llamada a 'gensym'Â·

     En caso de suministrar el argumento <x>, siendo este un número
     entero, se utilizará como sufijo en lugar del contador interno de
     Lisp, lo cual tendrá efecto sólo para esta llamada a 'gensym'Â·

     Si no se suministra el sufijo en forma explícita, y sólo en este
     caso, el contador interno sufrirá un incremento después de haber
     sido utilizado.

     Ejemplos:

          (%i1) gensym();
          (%o1)                         g887
          (%i2) gensym("new");
          (%o2)                        new888
          (%i3) gensym(123);
          (%o3)                         g123

 -- Variable opcional: packagefile
     Valor por defecto: 'false'

     Los autores de paquetes que utilizan 'save' o 'translate' para
     crear librerías para otros usuarios pueden hacer la asignación
     'packagefile: true' para prevenir que se añada información a las
     listas con información del sistema de Maxima, como 'values' o
     'functions'.

 -- Función: remvalue (<nombre_1>, ..., <nombre_n>)
 -- Función: remvalue (all)

     Elimina del sistema los valores de las variable de usuario
     <nombre_1>, ..., <nombre_n> (incluso las que tienen subíndices).

     La llamada 'remvalue (all)' elimina los valores de todas las
     variables en 'values', la lista de todas las variables a las que el
     usuario a dado algún nombre, pero no de aquéllas a las que Maxima
     asigna automáticamente un valor.

     Véase también 'values'.

 -- Función: rncombine (<expr>)

     Transforma <expr> combinando todos los términos de <expr> que
     tengan denominadores idénticos o que difieran unos de otros por
     factores numéricos.  Su comportamiento es diferente al de la
     función 'combine', que combina términos con iguales denominadores.

     Haciendo 'pfeformat: true' y utilizando 'combine' se consiguen
     resultados similares a aquéllos que se pueden obtener con
     'rncombine', pero 'rncombine' realiza el paso adicional de
     multiplicar denominadores numéricos.  Esto da como resultado
     expresiones en las que se pueden reconocer algunas cancelaciones.

     Antes de utilizar esta función ejecútese 'load(rncomb)'.

 -- Función: setup_autoload (<nombre_fichero>, <función_1>, ...,
          <función_n>)

     Especifica que si alguna de las funciones <function_1>, ...,
     <function_n> es referenciada pero todavía no ha sido definida, se
     cargará <nombre_fichero> mediante una llamada a 'load'.  El
     <nombre_fichero> normalmente contendrá las definiciones de las
     funciones especificadas, aunque esto no es imperativo.

     La función 'setup_autoload' no opera con arreglos de funciones.

     La función 'setup_autoload' no evalúa sus argumentos.

     Ejemplo:

          (%i1) legendre_p (1, %pi);
          (%o1)                  legendre_p(1, %pi)
          (%i2) setup_autoload ("specfun.mac", legendre_p, ultraspherical);
          (%o2)                         done
          (%i3) ultraspherical (2, 1/2, %pi);
          Warning - you are redefining the Macsyma function ultraspherical
          Warning - you are redefining the Macsyma function legendre_p
                                      2
                           3 (%pi - 1)
          (%o3)            ------------ + 3 (%pi - 1) + 1
                                2
          (%i4) legendre_p (1, %pi);
          (%o4)                          %pi
          (%i5) legendre_q (1, %pi);
                                        %pi + 1
                                %pi log(-------)
                                        1 - %pi
          (%o5)                 ---------------- - 1
                                       2

 -- Función: tcl_output (<list>, <i0>, <skip>)
 -- Función: tcl_output (<list>, <i0>)
 -- Función: tcl_output ([<list_1>, ..., <list_n>], <i>)

     Imprime los elementos de una lista encerrándolos con llaves '{ }',
     de forma apropiada para ser utilizado en un programa en el lenguaje
     Tcl/Tk.

     'tcl_output (<list>, <i0>, <skip>)' imprime <list>, empezando por
     el elemento <i0> siguiendo luego con los elementos '<i0> + <skip>',
     '<i0> + 2 <skip>', etc.

     'tcl_output (<list>, <i0>)' equivale a 'tcl_output (<list>, <i0>,
     2)'.

     'tcl_output ([<list_1>, ..., <list_n>], <i>)' imprime los
     <i>-ésimos elementos de <list_1>, ..., <list_n>.

     Ejemplos:

          (%i1) tcl_output ([1, 2, 3, 4, 5, 6], 1, 3)$

           {1.000000000     4.000000000
           }
          (%i2) tcl_output ([1, 2, 3, 4, 5, 6], 2, 3)$

           {2.000000000     5.000000000
           }
          (%i3) tcl_output ([3/7, 5/9, 11/13, 13/17], 1)$

           {((RAT SIMP) 3 7) ((RAT SIMP) 11 13)
           }
          (%i4) tcl_output ([x1, y1, x2, y2, x3, y3], 2)$

           {$Y1 $Y2 $Y3
           }
          (%i5) tcl_output ([[1, 2, 3], [11, 22, 33]], 1)$

           {SIMP 1.000000000     11.00000000
           }


File: maxima.info,  Node: Reglas y patrones,  Next: Conjuntos,  Prev: Miscelánea de opciones,  Up: Top

34 Reglas y patrones
********************

* Menu:

* Introducción a reglas y patrones::  
* Funciones y variables sobre reglas y patrones::  


File: maxima.info,  Node: Introducción a reglas y patrones,  Next: Funciones y variables sobre reglas y patrones,  Prev: Reglas y patrones,  Up: Reglas y patrones

34.1 Introducción a reglas y patrones
=====================================

Esta sección describe las reglas de simplificación y los patrones de
comparación definidos por el usuario.  Hay dos grupos de funciones que
implementan diferentes esquemas de comparación de patrones.  En un grupo
están 'tellsimp', 'tellsimpafter', 'defmatch', 'defrule', 'apply1',
'applyb1' y 'apply2'.  En el otro, se encuentran 'let' y 'letsimp'.
Ambos esquemas definen patrones en términos de variables de patrones
declaradas mediante 'matchdeclare'.

Las reglas de comparación de patrones definidas por 'tellsimp' y
'tellsimpafter' se aplican automáticamente por el simplificador de
Maxima.  Las reglas definidas por 'defmatch', 'defrule' y 'let' se
aplican previa llamada a una función.

Hay otros mecanismos para las reglas; las relativas a polinomios se
controlan mediante 'tellrat' y las del álgebra conmutativa y no
conmutativa se definen en el paquete 'affine'.


File: maxima.info,  Node: Funciones y variables sobre reglas y patrones,  Prev: Introducción a reglas y patrones,  Up: Reglas y patrones

34.2 Funciones y variables sobre reglas y patrones
==================================================

 -- Función: apply1 (<expr>, <regla_1>, ..., <regla_n>)

     Aplica de forma repetida la <regla_1> a <expr> hasta que falla, a
     continuación aplica repetidamente la misma regla a todas las
     subexpresiones de <expr>, de izquierda a derecha, hasta que la
     <regla_1> haya fallado en todas las subexpresiones.  Llámese
     <expr_2> al resultado de transformar <expr> de esta forma.
     Entonces la <regla_2> se aplica de la misma manera comenzando en el
     nivel superior de <expr_2>.  Cuando la <regla_n> falla en la última
     expresión, se devuelve el resultado.

     'maxapplydepth' es el nivel de las subexpresiones más internas
     procesadas por 'apply1' y 'apply2'.

     Véase también 'applyb1', 'apply2' y 'let'.

 -- Función: apply2 (<expr>, <regla_1>, ..., <regla_n>)

     Si la <regla_1> falla en una subexpresión dada, entonces se aplica
     la <regla_2> repetidamente, etc.  Sólo si todas las reglas fallan
     en una subexpresión serán aplicadas todas las reglas de forma
     repetida a la siguiente subexpresión.  Si alguna de las reglas
     tiene éxito entonces la misma subexpresión es reprocesada,
     comenzando por la primera regla.

     'maxapplydepth' es el nivel de las subexpresiones más internas
     procesadas por 'apply1' y 'apply2'.

     Véase también 'applyb1' y 'let'.

 -- Función: applyb1 (<expr>, <regla_1>, ..., <regla_n>)

     Aplica la <regla_1> reiteradamente hasta la subexpresión más
     interna de <expr> hasta que falle, a continuación pasa a aplicar la
     misma regla en un nivel superior (esto es, en subexpresiones más
     grandes), hasta que la <regla_1> falle en la expresión de nivel más
     alto.  Después se aplica la <regla_2> de la misma manera al
     resultado obtenido de <regla_1>.  Tras la aplicación de la
     <regla_n> a la expresión de mayor nivel, se devuelve el resultado.

     La función 'applyb1' es similar a 'apply1' pero opera de
     abajo-arriba, en lugar de arriba-abajo.

     'maxapplyheight' es la máxima altura a la que llega 'applyb1' antes
     de terminar su cometido.

     Véase también 'apply1', 'apply2' y 'let'.

 -- Variable opcional: current_let_rule_package
     Valor por defecto: 'default_let_rule_package'

     La variable 'current_let_rule_package' es el nombre del paquete de
     reglas que están utilizando las funciones del paquete 'let'
     ('letsimp', etc.), a menos que se especifique otro paquete de
     reglas.  A esta variable se le puede asignar el nombre de cualquier
     paquete de reglas definido por medio de la instrucción 'let'.

     Si se hace la llamada 'letsimp (expr, rule_pkg_name)', el paquete
     de reglas 'rule_pkg_name' será utilizado únicamente para esa
     llamada y el valor de 'current_let_rule_package' no cambia.

 -- Variable opcional: default_let_rule_package
     Valor por defecto: 'default_let_rule_package'

     La variable 'default_let_rule_package' es el nombre del paquete de
     reglas utilizado cuando el usuario no especifica otro
     explícitamente con 'let' o cambiando el valor de
     'current_let_rule_package'.

 -- Función: defmatch (<nombre_prog>, <patrón>, <x_1>, ..., <x_n>)
 -- Función: defmatch (<progname>, <pattern>)

     Define una función '<nombre_prog>(<expr>, <x_1>, ..., <x_n>)' que
     analiza si <expr> coincide con el <patrón>.

     El argumento <patrón> es una expresión que contiene los argumentos
     de patrón <x_1>, ..., <x_n> y algunas variables de patrón.  Los
     argumentos de patrón se dan de forma explícita como argumentos a
     'defmatch', mientras que las variables de patrón se declaran
     mediante la función 'matchdeclare'.  Cualquier variable no
     declarada bien como variable patrón en 'matchdeclare', bien como
     argumento patrón en 'defmatch' se hace coincidir con ella misma.

     El primer argumento de la función definida <nombre_prog> es una
     expresión a ser comparada con el patrón y los demás argumentos son
     los argumentos que se corresponden con las variables ficticias
     <x_1>, ..., <x_n> del patrón.

     Si el resultado de la comparación es positivo, <nombre_prog>
     devuelve una lista de ecuaciones cuyos miembros izquierdos son los
     argumentos y variables de patrón, y cuyos miembros derechos son las
     subexpresiones en las que se han producido las coincidencias con
     patrones.  A las variables de patrón, no a los argumentos, se les
     asignan las subexpresiones con las que coinciden.  Si la
     comparación falla, <nombre_prog> devuelve 'false'.

     Un patrón literal, es decir, que no contiene ni argumentos ni
     variables de patrón, devuelve 'true' en caso de coincidencia.

     A literal pattern (that is, a pattern which contains neither
     pattern arguments nor pattern variables) returns 'true' if the
     match succeeds.

     Véase también 'matchdeclare', 'defrule', 'tellsimp' y
     'tellsimpafter'.

     Ejemplos:

     Define una función 'linearp(expr, x)' que comprueba si 'expr' es de
     la forma 'a*x + b', donde ni 'a' ni 'b' contienen a 'x' y 'a' es no
     nulo.  La función definida reconoce expresiones lineales respecto
     de cualquier variable, pues el argumento de patrón 'x' es pasado a
     '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

     Define una función 'linearp(expr)' que comprueba si 'expr' es de la
     forma 'a*x + b', donde ni 'a' ni 'b' contienen a 'x' y 'a' es no
     nulo.  La función definida sólo reconoce expresiones lineales
     únicamente respecto de 'x', pues no se le pasa a 'defmatch' nigún
     argumento de patrón

          (%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]

     Define una función 'checklimits(expr)' que comprueba si 'expr' es
     una integral definida.

          (%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)]

 -- Función: defrule (<nombre_regla>, <patrón>, <reemplazamiento>)

     Define y da nombre a una regla de reemplazamiento para el patrón
     dado.  Si la regla <nombre_regla> es aplicada a una expresión (por
     'apply1', 'applyb1' o 'apply2'), cada subexpresión que coincida con
     el patrón será reemplazada por el contenido de <reemplazamiento>.

     Las propias reglas pueden ser tratadas como funciones que
     transforman una expresión mediante una operación consistente en la
     búsqueda de una coincidencia y posterior aplicación de un
     reemplazamiento.  Si la comparación falla, la función que
     implementa la regla devuelve 'false'.

 -- Función: disprule (<nombre_regla_1>, ..., <nombre_regla_n>)
 -- Función: disprule (all)

     Muestra las reglas de <nombre_regla_1>, ..., <nombre_regla_n>, tal
     como son devueltas por 'defrule', 'tellsimp' o 'tellsimpafter', o
     un patrón definido por 'defmatch'.  Cada regla se muestra con una
     etiqueta de expresión intermedia ('%t').

     La llamada 'disprule (all)' muestra todas las reglas.

     La función 'disprule' no evalúa sus argumentos y devuelve la lista
     de etiquetas de expresiones intermedias correspondientes a las
     reglas mostradas.

     Véase también 'letrules', que muestra las reglas definidas por
     'let'.

     Ejemplos:

          (%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) -> []]

 -- Función: let (<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>)
 -- Función: let ([<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>],
          <nombre_paquete>)

     Define una regla de sustitución para 'letsimp' tal que <prod> es
     sustituido por <repl>, donde <prod> es un producto de potencias
     positivas o negativas de los términos siguientes:

        * Átomos que 'letsimp' buscará a menos que antes de llamar a
          'letsimp' se utilice la función 'matchdeclare' para asociar un
          predicado con el átomo.  En este caso 'letsimp' hará coincidir
          el átomo con cualquier término del producto que satisfaga el
          predicado.
        * Expresiones básicas como 'sin(x)', 'n!', 'f(x,y)', etc.  Como
          en el caso anterior, 'letsimp' buscará coincidencias exactas,
          a menos que se utilice 'matchdeclare' para asociar un
          predicado con el argumento de la expresión básica ('sin(x)',
          'n!', 'f(x,y)', ...).

     Si se incluye un predicado en la función 'let' seguido de una lista
     de argumentos, una coincidencia aceptable (es decir, una que fuese
     aceptada si se hubiese omitido el predicado) se aceptará sólo si
     'predname (arg_1', ..., arg_n')' vale 'true', donde <arg_i'> es el
     valor coincidente con <arg_i>.  El argumento <arg_i> puede ser el
     nombre de cualquier átomo o el argumento de cualquier expresión
     básica que aparezca en <prod>.  <repl> puede ser cualquier
     expresión racional.  Si cualquiera de los átomos o argumentos de
     <prod> aparece en <repl> se llevan a cabo las sustituciones
     correspondientes.

     La variable global 'letrat' controla la simplificación de los
     cocientes por 'letsimp'.  Cuando 'letrat' vale 'false', 'letsimp'
     simplifica separadamente el numerador y denominador de <expr> y no
     simplifica el cociente.  Sustituciones como que 'n!/n' se reduzca a
     '(n-1)!' ya no se realizarán.  Cuando 'letrat' vale 'true',
     entonces se simplifican el numerador, el denominador y el cociente,
     en este orden.

     Estas funciones de sustitución permiten al usuario trabajar con
     varios paquetes de reglas al mismo tiempo.  Cada paquete de reglas
     puede contener cierto número de reglas 'let' que son referenciadas
     por un nombre dado por el usuario.  'let ([<prod>, <repl>,
     <predname>, <arg_1>, ..., <arg_n>], <nombre_paquete>)' añade la
     regla <predname> al paquete de reglas <nombre_paquete>.  'letsimp
     (<expr>, <package_name>)' aplica las reglas de <nombre_paquete>.
     La llamada 'letsimp (<expr>, <nombre_paquete1>, <nombre_paquete2>,
     ...)' es equivalente a 'letsimp (<expr>, <nombre_paquete1>)'
     seguida de 'letsimp (%, <nombre_paquete2>)', ....

     'current_let_rule_package' es el nombre del paquete de reglas que
     se está utilizando.  A esta variable se le puede asignar el nombre
     de cualquier paquete de reglas definido mediante el comando 'let'.
     Siempre que una de las funciones incluidas en el paquete 'let' sean
     invocadas sin nombre de paquete, se utilizará el paquete cuyo
     nombre se guarde en 'current_let_rule_package'.  Si se hace una
     llamada tal como 'letsimp (<expr>, <rule_pkg_name>)', el paquete de
     reglas <rule_pkg_name> es utilizado solamente para ese comando
     'letsimp', sin efectuarse cambios en 'current_let_rule_package'.  A
     menos que se indique otra cosa, 'current_let_rule_package' toma por
     defecto el valor de '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

 -- Variable opcional: letrat
     Valor por defecto: 'false'

     Cuando 'letrat' vale 'false', 'letsimp' simplifica separadamente el
     numerador y denominador de una fracción sin simplificar luego el
     cociente.

     Cuando 'letrat' vale 'true', se simplifican el numerador,
     denominador y cociente, por este orden.

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

 -- Función: letrules ()
 -- Función: letrules (<nombre_paquete>)

     Muestra las reglas de un paquete de reglas.  La llamada 'letrules
     ()' muestra las reglas del paquete de reglas actual.  La llamada
     'letrules (<nombre_paquete>)' muestra las reglas de
     <nombre_paquete>.

     El paquete de reglas actual tiene su nombre almacenado en by
     'current_let_rule_package'.  A menos que se indique de otra manera,
     'current_let_rule_package' toma por defecto el valor de
     'default_let_rule_package'.

     Véase también 'disprule', que muestra las reglas definidas por
     'tellsimp' y 'tellsimpafter'.

 -- Función: letsimp (<expr>)
 -- Función: letsimp (<expr>, <nombre_paquete>)
 -- Función: letsimp (<expr>, <nombre_paquete_1>, ...,
          <nombre_paquete_n>)

     Aplica repetidamente las reglas definidas por 'let' hasta que no se
     puedan hacer más cambios en <expr>.

     La llamada 'letsimp (<expr>)' utiliza las reglas de
     'current_let_rule_package'.

     La llamada 'letsimp (<expr>, <nombre_paquete>)' utiliza las reglas
     de <nombre_paquete> sin efectuar cambios en
     'current_let_rule_package'.

     La llamada 'letsimp (<expr>, <nombre_paquete_1>, ...,
     <nombre_paquete_n>)' es equivalente a 'letsimp (<expr>,
     <nombre_paquete_1>', seguida de 'letsimp (%, <nombre_paquete_2>)' y
     así sucesivamente.

 -- Variable opcional: let_rule_packages
     Valor por defecto: '[default_let_rule_package]'

     La variable 'let_rule_packages' guarda una lista con todos los
     paquetes de reglas definidos por el usuario, junto con el paquete
     por defecto 'default_let_rule_package'.

 -- Función: matchdeclare (<a_1>, <pred_1>, ..., <a_n>, <pred_n>)
     Asocia un predicado <pred_k> con una variable o lista de variables
     <a_k>, de forma que <a_k> se comparará con expresiones para las
     cuales el predicado devuelva algo que no sea 'false'.

     Un predicado puede ser el nombre de una función, una expresión
     lambda, una llamada a función, una llamada a una expresión lambda
     sin el último argumento, 'true' o 'all'.  Cualquier expresión se
     hace coincidir con 'true' o 'all'.

     Si el predicado se especifica como una llamada a función o a una
     expresión lambda, la expresión a ser analizada es añadida a la
     lista de argumentos, siendo los argumentos evaluados en el momento
     de ser evaluada la comparación.  En cambio, si el predicado se
     especifica como un nombre de función o como una expresión lambda,
     la expresión a ser analizada será su único argumento.  No es
     necesario definir una función de predicado cuando se hace una
     llamada a 'matchdeclare'; el predicado no se evalúa hasta que se
     ensaya una comparación.

     Un predicado puede devolver tanto una expresión booleana, como
     'true' o 'false'.  Las expresiones booleanas se evalúan con 'is'
     dentro de la regla, por lo que no es necesario llamar a 'is' desde
     dentro del predicado.

     Si una expresión satisface un predicado, se asigna a la variable de
     comparación la expresión, excepto cuando las variables de
     comparación son operandos de sumas '+' o multiplicaciones '*'.
     Solamente las sumas y multiplicaciones son tratadas de forma
     especial; los demás operadores n-arios (tanto los del sistema como
     los definidos por el usuario) son tratados como funciones
     ordinarias.

     En el caso de sumas y multiplicaciones, a la variable de
     comparación se le puede asignar una expresión simple que satisfaga
     el predicado de comparación, o una suma o producto,
     respectivamente, de tales expresiones.  Los predicados son
     evaluados en el orden en el que sus variables asociadas aparecen en
     el patrón de comparación, y un término que satisfaga más de un
     predicado es tomado por el primer predicado que satisfaga.  Cada
     predicado se compara con todos los operandos de la suma o producto
     antes de ser evaluado el siguiente predicado.  Además, si 0 o 1,
     respectivamente, satisface un predicado de comparación, y no hay
     otros términos que lo satisfagan, se asignará el 0 o 1 a la
     variable de comparación asociada al predicado.

     El algoritmo para procesar patrones de suma y multiplicación hace
     que los resultados de algunas comparaciones dependan del orden de
     los términos en el patrón de comparación y en la expresión a ser
     comparada.  Sin embargo, si todos los predicados de comparación son
     mutuamente excluyentes, el resultado de la comparación no depende
     para nada de la ordenación, puesto que un predicado de comparación
     no puede aceptar términos aceptados por otros predicados.

     Invocando 'matchdeclare' con una variable <a> como argumento cambia
     la propiedad de 'matchdeclare' para <a>, si ya había una declarada;
     solamente el 'matchdeclare' más reciente está activo cuando se
     define una regla.  Cambios posteriores en la propiedad de
     'matchdeclare' (via 'matchdeclare' o 'remove') no afectan a las
     reglas existentes.

     'propvars (matchdeclare)' devuelve la lista de todas las variables
     para las cuales hay una propiedad de 'matchdeclare'.  La llamada
     'printprops (<a>, matchdeclare)' devuelve el predicado para la
     variable 'a'.  La llamada 'printprops (all, matchdeclare)' devuelve
     la lista de predicados de todas las variables de 'matchdeclare'.
     La llamada 'remove (<a>, matchdeclare)' borra la propiedad
     'matchdeclare' de <a>.

     Las funciones 'defmatch', 'defrule', 'tellsimp', 'tellsimpafter' y
     'let' construyen reglas que analizan expresiones mediante patrones.

     'matchdeclare' no evalúa sus argumentos y siempre devuelve 'done'.

     Ejemplos:

     Un predicado puede ser el nombre de una función, una expresión
     lambda, una llamada a función, una llamada a una expresión lambda
     sin el último argumento, 'true' o '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

     Si una expresión satisface un predicado, se asigna a la variable de
     comparación la expresión.

          (%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]

     En el caso de sumas y multiplicaciones, a la variable de
     comparación se le puede asignar una expresión simple que satisfaga
     el predicado de comparación, o una suma o producto,
     respectivamente, de tales expresiones.

          (%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)]

 -- Variable opcional: maxapplydepth
     Valor por defecto: 10000

     La variable 'maxapplydepth' es la máxima profundidad a la que van a
     introducirse 'apply1' y 'apply2'.

 -- Variable opcional: maxapplyheight
     Valor por defecto: 10000

     La variable 'maxapplyheight' es la m2'axima altura a la que
     escalará 'applyb1' antes de detenerse.

 -- Función: remlet (<prod>, <nombre>)
 -- Función: remlet ()
 -- Función: remlet (all)
 -- Función: remlet (all, <nombre>)

     Elimina la última regla de sustitución <prod> -> repl que haya sido
     definida por la función 'let'.  Si se suministar el nombre la regla
     será borrada del paquete con ese mismo nombre.

     Las llamadas 'remlet()' y 'remlet(all)' eliminan todas las reglas
     de sustitución del paquete de reglas actual.  Si se suministra el
     nombre de un paquete de reglas, como en 'remlet (all, <nombre>)',
     el paquete de reglas con ese <nombre> es también eliminado.

     Si es necesario cambiar una sustitución haciendo uso de la misma
     producción, no es necesario llamar a 'remlet', simplemente
     redefínase la sustitución utilizando la misma producción con la
     función 'let' junto con el nuevo reemplazamiento y/o nombre de
     predicado.  De ser llamado nuevamente 'remlet (<prod>)' la
     sustitución original sería recuperada.

     Véase también 'remrule', que elimina una regla definida por
     'tellsimp' o 'tellsimpafter'.

 -- Función: remrule (<op>, <nombre_regla>)
 -- Función: remrule (<op>, all)

     Elimina las reglas previamente definidas por 'tellsimp' o
     'tellsimpafter'.

     La llamada 'remrule (<op>, <nombre_regla>)' elimina la regla de
     nombre <nombre_regla> del operador <op>.

     Independientemente de que <op> sea un operador propio de Maxima o
     haya sido definido por el usario (como los establecidos por
     'infix', 'prefix', etc.), tanto <op> como <rulename> deben ir
     encerrados entre comillas dobles.

     La llamada 'remrule (<function>, all)' borra todas las reglas para
     el operador <op>.

     Véase también 'remlet', que elimina una regla definida mediante
     'let'.

     Ejemplos:

          (%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)]

 -- Función: tellsimp (<patrón>, <reemplazamiento>)

     La función 'tellsimp' es similar a 'tellsimpafter' pero coloca
     nueva información antes que la antigua, de manera que se aplica
     antes que las reglas de simplificación de Maxima.

     La función 'tellsimp' se utiliza cuando es importante utilizar la
     expresión antes de que el simplificador opere sobre ella; por
     ejemplo, cuando el simplificador ya "sabe" algo sobre una
     expresión, pero lo que devuelve no es lo que quiere el usuario.  En
     cambio, cuando el simplificador ya "sabe" algo sobre una expresión
     pero lo que devuelve no es lo suficiente para el usuario, entonces
     éste podrá estar interesado en utilizar 'tellsimpafter'.

     El patrón no puede ser una suma, ni un producto, ni una variable ni
     un número.

     'rules' es la lista de reglas definidas por 'defrule', 'defmatch',
     'tellsimp' y 'tellsimpafter'.

     Ejemplos:

          (%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)

 -- Función: tellsimpafter (<patrón>, <reemplazamiento>)

     Define una regla de simplificación que el simplificador aplicará
     después de las reglas de simplificación propias de de Maxima.  El
     <patrón> es una expresión que contiene variables de patrón
     (declaradas por 'matchdeclare') junto con otros átomos y
     operadores.  El contenido de <reemplazamiento> sustituye una
     expresión que coincida con el patrón; a las variables de patrón en
     <reemplazamiento> se les asignan los valores coincidentes en la
     expresión.

     El <patrón> puede ser una expresión no atómica en la que el
     operador principal no sea una variable de patrón; la regla de
     simplificación se asocia con el operador principal.  Los nombres de
     las funciones (con una excepción que se indica más abajo), listas y
     arrays pueden aparecer en el <patrón> como operador principal sólo
     como literales (no variables de patrones); esto excluye expresiones
     como 'aa(x)' y 'bb[y]', si tanto 'aa' como 'bb' son patrones de
     variables.  Nombres de funciones, listas y arrays que sean
     variables de patrón pueden aparecer como operadores que no sean el
     operador principal de <patrón>.

     Hay una excepción a la regla indicada más arriba concerniente a los
     nombres de funciones.  El nombre de una función subindicada en una
     expresión tal como 'aa[x](y)' puede ser una variable de patrón
     porque el operador principal no es 'aa' sino el átomo de Lisp
     'mqapply'.  Esta es una consecuencia de la representación de
     expresiones que contienen funciones subindicadas.

     Las reglas de simplificación se aplican tras las evaluaciones (a
     menos que se supriman con el apóstrofo o la variable 'noeval').
     Las reglas establecidas por 'tellsimpafter' se aplican en el orden
     en que han sido definidas y después de las reglas propias de
     Maxima.  Las reglas se aplican de abajo arriba, esto es, se aplican
     primero a las subexpresiones antes que a toda la expresión.  Puede
     ser necesario simplificar repetidamente un resultado (por ejemplo,
     mediante el operador de doble comilla simple '''' o la variable
     'infeval') para asegurar que se aplican todas las reglas.

     Las variables de patrón se tratan como variables locales en las
     reglas de simplificación.  Una vez definida una regla, el valor de
     una variable de patrón no afecta a la regla, ni se ve influenciada
     poe ésta.  Una asignación a una variable de patrón que resulta de
     la aplicación exitosa de una regla no afecta a la asignación actual
     de la variable de patrón.  Sin embargo, como cualquier otro átomo
     de Maxima, las propiedades de las variables de patrón (tal como se
     definen con 'put' y sus funciones relacionadas) son globales.

     La regla construida por 'tellsimpafter' es nombrada detrás del
     operador principal de <patrón>.  Reglas para operadores de Maxima y
     operadores definidos por el usuario con 'infix', 'prefix',
     'postfix', 'matchfix' y 'nofix', tienen nombres que son cadenas
     alfanuméricas de Maxima.  Reglas para otras funciones tienen
     nombres que son identificadores ordinarios de Maxima.

     El tratamiento de formas nominales y verbales es hasta cierto punto
     confuso.  Si se define una regla para una forma nominal (o verbal)
     y ya existe una regla para la correspondiente forma verbal (o
     nominal), la regla recién definida se aplica a ambas formas
     (nominal y verbal).  Si no existe regla para una forma verbal (o
     nominal) la regla recién definida se aplica únicamente a la forma
     nominal (o verbal).

     La regla construida por 'tellsimpafter' es una típica función de
     Lisp.  Si el nombre de la regla es '$foorule1', la sentencia ':lisp
     (trace $foorule1)' hace una traza de la función y ':lisp
     (symbol-function '$foorule1)' muestra su definición.

     La función 'tellsimpafter' no evalúa sus argumentos y devuelve la
     lista de reglas para el operador principal de <patrón>, incluida la
     regla recién establecida.

     Véanse también 'matchdeclare', 'defmatch', 'defrule', 'tellsimp',
     'let', 'kill', 'remrule' y 'clear_rules'.

     Ejemplos:

     <pattern> puede ser cualquier expresión no atómica en la que el
     operador principal no sea una variable de patrón.

          (%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))

     Las reglas se aplican en el orden en que se definen.  Si dos reglas
     coinciden con una expresión, se aplica aquélla que haya sido
     definida en primer lugar.

          (%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)

     Las variables de patrón se tratan como variables locales en las
     reglas de simplificación.  (Compárese con 'defmatch', que trata las
     variables de patrón como globales.)

          (%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

     Como cualquier otro átomo, las propiedades de las variables de
     patrón son globales, incluso cuando sus valores sean locales.  En
     este ejemplo se declara una propiedad de asignación a treavés de
     'define_variable'.  Esta es una propiedad del átomo 'bb' en todo
     Maxima.

          (%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);

     Las reglas se nombran después de los operadores principales.  Los
     nombres de reglas tanto para las funciones de Maxima como para las
     definidas por el usuario son cadenas alfanuméricas, mientras que
     los nombres de las otras funciones son identificadores típicos.

          (%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)                          ^

     Un ejemplo de producto anticonmutativo.

          (%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

 -- Función: clear_rules ()

     Ejecuta 'kill (rules)' y después inicializa el siguiente número de
     regla a 1 para la adición '+', multiplicación '*' y exponenciación
     '^'.

