@c English version 2013-06-15
@menu
* Funciones y variables para to_poly_solve::
@end menu

@node Funciones y variables para to_poly_solve,  , to_poly_solve, to_poly_solve
@section Funciones y variables para to_poly_solve

Los paquetes @code{to_poly} y @code{to_poly_solve} son experimentales,
siendo posible que las especificaciones de sus funciones puedan
cambiar en el futuro, o que algunas de estas funciones puedan ser
incorporadas a otras partes de Maxima.

Los paquetes @code{to_poly} y @code{to_poly_solve}, junto con su documentación,
fue escrito por Barton Willis de la Universidad de Nebraska en Kearney. 






@deffn {Operador} %and
@ifinfo
@fnindex Conjunción lógica
@end ifinfo

El operador @code{%and} es una conjunción lógica. Maxima simplifica
una expresión @code{%and} a @code{true}, @code{false} o a una expresión
lógicamente equivalente, pero simplificada. El operador @code{%and}
es asociativo, conmutativo e idempotente. Así, cuando @code{%and}
devuelva una forma nominal, sus argumentos no serán redundantes; por ejemplo,

@example
(%i1) a %and (a %and b);
(%o1)                       a %and b
@end example

Si uno de los argumentos de la conjunción es la negación de otro argumento,
@code{%and} devuelve @code{false}:

@example
 (%i2) a %and (not a);
 (%o2) false
@end example

Si cualquiera de los argumentos vale @code{false}, la conjunción devuelve
@code{false}, incluso cuando haya algún otro argumento que sea una
expresión no booleana; por ejemplo,

@example
(%i2) a %and (not a);
(%o2)                         false
@end example

Los argumentos de la expresión @code{%and} que sean inecuaciones se
reducen con la simplificación de Fourier; el método que se
aplica dispone de un pre-procesador que convierte algunas, pero no
todas, las inecuaciones no lineales a lineales. Por ejemplo, el
método de simplificación de Fourier simplifica @code{abs(x) + 1 > 0}
a @code{true}:

@example
(%i4) (x < 1) %and (abs(x) + 1 > 0);
(%o4)                         x < 1
@end example

@b{Notas}  
@itemize @bullet
@item La variable opcional @code{prederror} no altera la
simplificación de las expresiones @code{%and}.

@item Para evitar errores en la precedencia de las operaciones,
se recomienda utilizar paréntesis en las expresiones combinadas
en las que aparezcan los operadores @code{%and},  @code{%or} y @code{not} .

@item Los operadores @code{and} y @code{or}, tal como están
programados en Maxima, no conocen las propiedades asociativa
ni conmutativa.

@end itemize

@b{Limitaciones} La conjunción @code{%and} simplifica inecuaciones
@i{locamente}, no @i{globalmente}, lo que significa que conjunciones tales como

@example
(%i5) (x < 1) %and (x > 1);
(%o5)                 (x > 1) %and (x < 1)
@end example

@i{no} simplifican a @code{false}. Además, las rutinas de eliminación de Fourier
ignoran los hechos almacenados en la base de datos.

@example
(%i6) assume(x > 5);
(%o6)                        [x > 5]
(%i7) (x > 1) %and (x > 2);
(%o7)                 (x > 1) %and (x > 2)
@end example

Por último, las inecuaciones no lineales que no se puedan reducir de
manera sencilla a formas lineales, no se simplifican.

No está soportada la distributividad de @code{%and} respecto de @code{%or},
ni la negación respecto de @code{%and}.

Para hacer uso de este operador, ejecútese @code{load("to_poly_solve")}.

Véanse también @code{%or}, @code{%if}, @code{and}, @code{or} y @code{not}.

@end deffn






@deffn {Operador} %if ( @var{bool}, @var{a}, @var{b})
@ifinfo
@fnindex Evaluación condicionada
@end ifinfo

El operador @code{%if} es un condicional. La condición @var{bool}
debe tomar un valor lógico; cuando sea @code{true}, se devolverá
el segundo argumento, y cuando valga @code{false}, el segundo. En
cualquier otro caso, se obtiene una forma nominal.

En Maxima, las expresiones con desigualdades o igualdades no adquieren
valores lógicos; por ejemplo, @math{5 < 6} no se simplifica a @code{true},
ni @math{5 = 6} @code{false}. Sin embargo, en la condición de una
sentencia @code{%if}, Maxima intenta determinar el valor lógico
de la expresión de forma automática. Véase un ejemplo:

@example
(%i1) f : %if(x # 1, 2, 8);
(%o1)                 %if(x - 1 # 0, 2, 8)
(%i2) [subst(x = -1,f), subst(x=1,f)];
(%o2)                        [2, 8]
@end example

Si en la condición aparece una inecuación, Maxima la
reduce con una simplificación de Fourier.

@b{Notas} 
@itemize bullet
@item Si la condición no se reduce a un valor lógico, Maxima devuelve
una forma nominal:
@example
(%i3) %if(42,1,2);
(%o3)                     %if(42, 1, 2)
@end example

@item El operador @code{if} de Maxima es n-ario, pero el operador @code{%if} no lo es.
@end itemize

Por último, las inecuaciones no lineales que no se puedan reducir de
manera sencilla a formas lineales, no se simplifican.

Para hacer uso de este operador, ejecútese @code{load("to_poly_solve")}.
@end deffn




  
@deffn {Operador} %or
@ifinfo
@fnindex Disyunción lógica
@end ifinfo

El operador @code{%or} es una disyunción lógica. Maxima simplifica
una expresión @code{%or} a @code{true}, @code{false} o a una expresión
lógicamente equivalente, pero simplificada. El operador @code{%or}
es asociativo, conmutativo e idempotente. Así, cuando @code{%or}
devuelva una forma nominal, sus argumentos no serán redundantes; por ejemplo,

@example
(%i1) a %or (a %or b);
(%o1)                        a %or b
@end example

Si uno de los argumentos de la disyunción es la negación de otro argumento,
@code{%or} devuelve @code{true}:

@example
(%i2) a %or (not a);
(%o2)                         true
@end example

Si cualquiera de los argumentos vale @code{true}, la disyunción devuelve
@code{true}, incluso cuando haya algún otro argumento que sea una
expresión no booleana; por ejemplo,

@example
(%i3) 42 %or true;
(%o3)                         true
@end example

Los argumentos de la expresión @code{%or} que sean inecuaciones se
reducen con la simplificación de Fourier. Por ejemplo, el
método de simplificación de Fourier simplifica @code{abs(x) + 1 > 0}
a @code{true}:

@example
(%i4) (x < 1) %or (abs(x) + 1 > 0);
(%o4)                         true
@end example

@b{Notas}  
@itemize @bullet
@item La variable opcional @code{prederror} no altera la
simplificación de las expresiones @code{%or}.

@item Para evitar errores en la precedencia de las operaciones,
se recomienda utilizar paréntesis en las expresiones combinadas
en las que aparezcan los operadores @code{%and},  @code{%or} y @code{not} .

@item Los operadores @code{and} y @code{or}, tal como están
programados en Maxima, no conocen las propiedades asociativa
ni conmutativa.

@end itemize

@b{Limitaciones} La conjunción @code{%or} simplifica inecuaciones
@i{locamente}, no @i{globalmente}, lo que significa que disyunciones tales como

@example
 (%i1) (x < 1) %or (x >= 1);
 (%o1) (x > 1) %or (x >= 1)
@end example

@i{no} simplifican a @code{true}. Además, las rutinas de eliminación de Fourier
ignoran los hechos almacenados en la base de datos.

@example
(%i2) assume(x > 5);
(%o2)                        [x > 5]
(%i3) (x > 1) %and (x > 2);
(%o3)                 (x > 1) %and (x > 2)
@end example

Por último, las inecuaciones no lineales que no se puedan reducir de
manera sencilla a formas lineales, no se simplifican.

No está soportada la distributividad de @code{%or} respecto de @code{%and},
ni la negación respecto de @code{%or}.

Para hacer uso de este operador, ejecútese @code{load("to_poly_solve")}.

Véanse también @code{%and}, @code{%if}, @code{and}, @code{or} y @code{not}.

@end deffn





@deffn {Función} complex_number_p (@var{x})

La función @code{complex_number_p} devuelve @code{true} si su
argumento es de cualquiera de las formas @code{a + %i * b}, @code{a}, @code{%i b} o
@code{%i}, donde @code{a} y @code{b} son racionales o decimales en coma flotante,
de precisión doble o arbitraria (@i{bigfloats}); para cualesquiera otros argumentos,
@code{complex_number_p} devuelve @code{false}.

Ejemplo:

@example
(%i1) map('complex_number_p,[2/3, 2 + 1.5 * %i, %i]);
(%o1)                  [true, true, true]
(%i2) complex_number_p((2+%i)/(5-%i));
(%o2)                         false
(%i3) complex_number_p(cos(5 - 2 * %i));
(%o3)                         false
@end example

Véase también @code{isreal_p}.

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.
@end deffn






@deffn {Función} compose_functions (@var{l})

La función @code{compose_functions(l)} devuelve una expresión lambda
que es la composición de las funciones presentes en la lista @var{l}.
Las funciones se aplican de derecha a izquierda.

Ejemplo:

@example
(%i1) compose_functions([cos, exp]);
                                        %g151
(%o1)             lambda([%g151], cos(%e     ))
(%i2) %(x);
                                  x
(%o2)                       cos(%e )
@end example

Si la lista está vacía devuelve la función identidad:

@example
(%i3) compose_functions([]);
(%o3)                lambda([%g152], %g152)
(%i4)  %(x);
(%o4)                           x
@end example

@b{Notas} 
@itemize @bullet
@item Cuando Maxima detecta que un miembro de la lista no es un
símbolo o expresión lambda, la función 
@code{funmake} (no @code{compose_functions}) muestra un mensaje de
error:
@example
(%i5) compose_functions([a < b]);

funmake: first argument must be a symbol, subscripted symbol,
string, or lambda expression; found: a < b
#0: compose_functions(l=[a < b])(to_poly_solve.mac line 40)
 -- an error. To debug this try: debugmode(true);
@end example

@item Para evitar conflictos de nombres, la variable independiente se determina
con la función @code{new_variable}:
@example
(%i6) compose_functions([%g0]);
(%o6)              lambda([%g154], %g0(%g154))
(%i7) compose_functions([%g0]);
(%o7)              lambda([%g155], %g0(%g155))
@end example
Aunque las variables dependientes sean diferentes, Maxima es capaz de
determinar que las expresiones lambda son semánticamente equivalentes:
@example
(%i8) is(equal(%o6,%o7));
(%o8)                         true
@end example
@end itemize

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.
@end deffn






@deffn {Función} dfloat (@var{x})

La función @code{dfloat} es similar a @code{float}, pero @code{dfloat} 
aplica @code{rectform} cuando @code{float} no puede evaluar a un número
decimal de coma flotante de doble precisión. Ejemplo:

@example
(%i1) float(4.5^(1 + %i));
                               %i + 1
(%o1)                       4.5
(%i2) dfloat(4.5^(1 + %i));
(%o2)        4.48998802962884 %i + .3000124893895671
@end example

@b{Notas} 

@itemize @bullet
@item La forma rectangular de una expresión puede no ser la
más adecuada para cálculos numéricos

@item El identificador @code{float} es al mismo tiempo una variable opcional,
cuyo valor por defecto es @code{false} y el nombre de una función.
@end itemize

Véanse también @code{float} y @code{bfloat}.

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

@end deffn






@deffn {Función} elim (@var{l}, @var{x})

La función @code{elim} elimina las variables que se indican en el conjunto
o lista @code{x} del conjunto o lista de ecuaciones en @code{l}. Cada
elemento de @code{x} debe ser un símbolo, mientras que los
elementos de @code{l} pueden ser ecuaciones o expresiones que se suponen
igualadas a cero.

La función @code{elim} devuelve una lista formada por dos listas; la
primera está formada por las expresiones con las variables eliminadas y
la segunda es la lista de pivotes o, en otras palabras, es la lista de
expresiones que @code{elim} ha utilizado para proceder con la eliminación.

Ejemplo:

Eliminación entre ecuaciones lineales. Eliminando @code{x} e @code{y}
se obtiene una única ecuación @code{2 z - 7 = 0}; las ecuaciones
@code{y + 7 = 0} y @code{z - z + 1 = 1} se han utilizado como pivotes.

@example
(%i1) elim(set(x + y + z = 1, x - y  - z = 8, x - z = 1), 
           set(x,y));
(%o1)            [[2 z - 7], [y + 7, z - x + 1]]
@end example

Eliminando las tres variables de estas ecuaciones se triangulariza el sistema
lineal:

@example
(%i2) elim(set(x + y + z = 1, x - y  - z = 8, x - z = 1),
           set(x,y,z));
(%o2)           [[], [2 z - 7, y + 7, z - x + 1]]
@end example

Las ecuaciones no necesitan ser lineales:

@example
(%i3) elim(set(x^2 - 2 * y^3 = 1,  x - y = 5), [x,y]);
                     3    2
(%o3)       [[], [2 y  - y  - 10 y - 24, y - x + 5]]
@end example

El usuario no puede controlar el orden en el que se eliminan las
variables. El algoritmo utiliza una heurística con
la que intenta escoger el mejor pivote y el mejor orden de eliminación.

@b{Notas} 

@itemize @bullet

@item Al contrario que la función relacionada @code{eliminate}, la
función @code{elim} no llama a la función @code{solve} cuando el
número de ecuaciones iguala al de variables.

@item La función @code{elim} trabaja aplicando resultantes; la variable
opcional @code{resultant} determina qué algoritmo va a utilizar Maxima.
Con @code{sqfr}, Maxima factoriza cada resultante y suprime ceros múltiples.

@item @code{elim} triangulariza un conjunto de ecuaciones polinómicas no
lineales; el conjunto solución del conjunto triangularizado puede ser mayor
que el conjunto de soluciones del conjunto no triangularizado, por lo que
las ecuaciones triangularizadas pueden tener soluciones falsas.

@end itemize

Véanse también @code{elim_allbut}, @code{eliminate_using}, @code{eliminate}
y @code{resultant}.

Para hacer uso de esta función, ejecútese @code{load("to_poly")}.

@end deffn







@deffn {Función} elim_allbut (@var{l}, @var{x})

Es similar a @code{elim}, excepto por el hecho de que elimina todas las variables
que aparecen en la lista de ecuaciones @code{l} que no están en @code{x}.

Ejemplo:

@example
(%i1) elim_allbut([x+y = 1, x - 5*y = 1],[]);
(%o1)                 [[], [y, y + x - 1]]
(%i2) elim_allbut([x+y = 1, x - 5*y = 1],[x]);
(%o2)                [[x - 1], [y + x - 1]]
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly")}.

Véanse también @code{elim}, @code{eliminate_using}, @code{eliminate}
y @code{resultant}.

@end deffn





@deffn {Función} eliminate_using (@var{l}, @var{e}, @var{x})

Elmina el símbolo @code{x} de la lista o conjunto de ecuaciones
@code{l} haciendo uso del pivote @code{e}.

Ejemplos:

@example
(%i1) eq : [x^2 - y^2 - z^3 , x*y - z^2 - 5, x - y + z];
               3    2    2     2
(%o1)      [- z  - y  + x , - z  + x y - 5, z - y + x]
(%i2) eliminate_using(eq,first(eq),z);
        3              2      2      3    2
(%o2) @{y  + (1 - 3 x) y  + 3 x  y - x  - x , 
                        4    3  3       2  2             4
                       y  - x  y  + 13 x  y  - 75 x y + x  + 125@}
(%i3) eliminate_using(eq,second(eq),z);
        2            2       4    3  3       2  2             4
(%o3) @{y  - 3 x y + x  + 5, y  - x  y  + 13 x  y  - 75 x y + x
                                                           + 125@}
(%i4) eliminate_using(eq, third(eq),z);
        2            2       3              2      2      3    2
(%o4) @{y  - 3 x y + x  + 5, y  + (1 - 3 x) y  + 3 x  y - x  - x @}
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly")}.

Véanse también @code{elim}, @code{elim_allbut}, @code{eliminate}
y @code{resultant}.

@end deffn






@deffn {Función} fourier_elim ([@var{eq1}, @var{eq2}, ...], [@var{var1}, @var{var}, ...])

La instrucción @code{fourier_elim([eq1,eq2,...], [var1,var2,...]} aplica el
algoritmo de eliminación de Fourier para resolver el sistema de inecuaciones 
lineales @code{[eq1,eq2,...]} respecto de las variables @code{[var1,var2,...]}.

Ejemplos:

@example
(%i1) fourier_elim([y-x < 5, x - y < 7, 10 < y],[x,y]);
(%o1)            [y - 5 < x, x < y + 7, 10 < y]
(%i2) fourier_elim([y-x < 5, x - y < 7, 10 < y],[y,x]);
(%o2)        [max(10, x - 7) < y, y < x + 5, 5 < x]
@end example

Eliminando primero respecto de @math{x} y luego respecto de @math{y},
se obtienen límites inferior y superior para @math{x}
que dependen de @math{y}, y límites numéricos para @math{y}.
Si se eliminan en orden inverso, se obtienen los límites
de @math{y} en función de @math{x}, y los de @math{x} son números.

De ser necesario, @code{fourier_elim} devuelve una disyunción de listas
de ecuaciones:

@example
(%i3) fourier_elim([x # 6],[x]);
(%o3)                  [x < 6] or [6 < x]
@end example

Si no existe solución, @code{fourier_elim} devuelve @code{emptyset},
y si la solución son todos los reales, @code{fourier_elim} devuelve 
@code{universalset}:

@example
(%i4) fourier_elim([x < 1, x > 1],[x]);
(%o4)                       emptyset
(%i5) fourier_elim([minf < x, x < inf],[x]);
(%o5)                     universalset
@end example

En caso de que las inecuaciones no sean lineales, @code{fourier_elim}
devuelve una lista de inecuaciones simplificadas:

@example
(%i6) fourier_elim([x^3 - 1 > 0],[x]);
               2                             2
(%o6) [1 < x, x  + x + 1 > 0] or [x < 1, - (x  + x + 1) > 0]
(%i7) fourier_elim([cos(x) < 1/2],[x]);
(%o7)                  [1 - 2 cos(x) > 0]
@end example

En lugar de una lista de inecuaciones, el primer argumento pasado a
@code{fourier_elim} puede ser una conjunción o disyunción lógica.

@example
(%i8) fourier_elim((x + y < 5) and (x - y >8),[x,y]);
                                              3
(%o8)            [y + 8 < x, x < 5 - y, y < - -]
                                              2
(%i9) fourier_elim(((x + y < 5) and x < 1) or  (x - y >8),[x,y]);
(%o9)          [y + 8 < x] or [x < min(1, 5 - y)]
@end example

La función @code{fourier_elim} soporta los operadores de desigualdad 
@code{<}, @code{<=}, @code{>}, @code{>=}, @code{#} y @code{=}.

La rutina de eliminación de Fourier dispone de un preprocesador que
convierte algunas inecuaciones no lineales formadas con las funciones
del valor absoluto, mínimo y máximo a inecuaciones 
lineales. Además, el preprocesador admite algunas expresiones 
que son productos o cocientes de términos lineales:

@example
(%i10) fourier_elim([max(x,y) > 6, x # 8, abs(y-1) > 12],[x,y]);
(%o10) [6 < x, x < 8, y < - 11] or [8 < x, y < - 11]
 or [x < 8, 13 < y] or [x = y, 13 < y] or [8 < x, x < y, 13 < y]
 or [y < x, 13 < y]
(%i11) fourier_elim([(x+6)/(x-9) <= 6],[x]);
(%o11)           [x = 12] or [12 < x] or [x < 9]
(%i12) fourier_elim([x^2 - 1 # 0],[x]);
(%o12)      [- 1 < x, x < 1] or [1 < x] or [x < - 1]
@end example

Para hacer uso de esta función, ejecútese @code{load("fourier_elim")}.

@end deffn







@deffn {Función} isreal_p (@var{e})

El predicado @code{isreal_p} devuelve @code{true} si @code{e} representa un
número real y @code{false} si no representa un punto de la recta; en cualquier
otro caso devuelve una forma nominal.

@example
(%i1) map('isreal_p, [-1, 0, %i, %pi]);
(%o1)               [true, true, false, true]
@end example

Las variables de Maxima se interpretan como números reales:

@example
(%i2) isreal_p(x);
(%o2)                         true
@end example

La función @code{isreal_p} consulta los hechos almacenados en la base de datos:
@example
(%i3) declare(z,complex)$

(%i4) isreal_p(z);
(%o4)                      isreal_p(z)
@end example

Con frecuencia, @code{isreal_p} devuelve una forma nominal cuando debería
devolver @code{false}; por ejemplo, la función logarítmica no toma valores
reales en toda la recta real, por lo que  @code{isreal_p(log(x))} debería
devolver @code{false}, sin embargo:

@example
(%i5) isreal_p(log(x));
(%o5)                   isreal_p(log(x))
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

Véase también @code{complex_number_p}.

La función @code{isreal_p} es experimental; sus
especificaciones pueden cambiar y su funcionalidad puede incorporarse a otras funciones
de Maxima.
@end deffn






@deffn {Función} new_variable (@var{type})

Devuelve un símbolo de la forma @code{%[z,n,r,c,g]k},
siendo @code{k} un número entero. Los valores admisibles para @var{type}
son @code{integer}, @code{natural_number}, @code{real}, @code{natural_number}
y @code{general}. Por número natural se entiende @i{entero negativo}, de 
manera que el ceero es un número natural.

Cuando @var{type} no es de ninguno de los tipos indicados más arriba,
@var{type} toma por defecto el valor @code{general}. Para enteros, números
naturales y números complejos, Maxima añade esta información a la base de
datos de forma automática.

@example
(%i1) map('new_variable,
          ['integer, 'natural_number, 'real, 'complex, 'general]);
(%o1)          [%z144, %n145, %r146, %c147, %g148]
(%i2) nicedummies(%);
(%o2)               [%z0, %n0, %r0, %c0, %g0]
(%i3) featurep(%z0, 'integer);
(%o3)                         true
(%i4) featurep(%n0, 'integer);
(%o4)                         true
(%i5) is(%n0 >= 0);
(%o5)                         true
(%i6) featurep(%c0, 'complex);
(%o6)                         true
@end example

Es recomendable que al argumento de @code{new_variable} se le
aplique el operador de comilla simple para evitar su evaluación,
de esta manera se evitan errores como el siguiente:

@example
(%i7) integer : 12$

(%i8) new_variable(integer);
(%o8)                         %g149
(%i9) new_variable('integer);
(%o9)                         %z150
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

Véase también @code{nicedummies}.

@end deffn






@deffn {Función} nicedummies

La función @code{nicedummies} reescribe los índices,
comenzando por cero, de las variables de una expresión qua hayan
sido introducidas por @code{new_variable}:

@example
(%i1) new_variable('integer) + 52 * new_variable('integer);
(%o1)                   52 %z136 + %z135
(%i2) new_variable('integer) - new_variable('integer);
(%o2)                     %z137 - %z138
(%i3) nicedummies(%);
(%o3)                       %z0 - %z1
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

Véase también @code{new_variable}.

@end deffn





@deffn {Función} parg (@var{x})

La función @code{parg} es una versión con capacidades simplificadoras
de la función de argumento complejo @code{carg}:

@example
(%i1) map('parg,[1,1+%i,%i, -1 + %i, -1]);
                        %pi  %pi  3 %pi
(%o1)               [0, ---, ---, -----, %pi]
                         4    2     4
@end example

Si el argumento pasado a la función @code{parg} no es una constante,
se devolverá una forma nominal:

@example
(%i2) parg(x + %i * sqrt(x));
(%o2)                 parg(x + %i sqrt(x))
@end example

Si @code{sign} detecta que la entrada es un número real negativo o
positivo, @code{parg} devuelve una forma no nominal aunque la entrada
no sea una constante:

@example
(%i3) parg(abs(x));
(%o3) 0
(%i4) parg(-x^2-1);
(%o4)                          %pi
@end example

La función @code{sign} suele ignorar las variables declaradas complejas
(@code{declare(x,complex)}); en tales casos, @code{parg}
puede retornar valores incorrectos:

@example
(%i1) declare(x,complex)$

(%i2) parg(x^2 + 1);
(%o2) 0
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

Véanse también @code{carg}, @code{isreal_p}.

@end deffn






@deffn {Función} real_imagpart_to_conjugate (@var{e})

La función @code{real_imagpart_to_conjugate} reemplaza todas las
llamadas a @code{realpart} y @code{imagpart} presentes en una expresión 
por llamadas a @code{conjugate}, obteniendo otra expresión equivalente:

@example
(%i1) declare(x, complex)$

(%i2) real_imagpart_to_conjugate(realpart(x) +  imagpart(x) = 3);
          conjugate(x) + x   %i (x - conjugate(x))
(%o2)     ---------------- - --------------------- = 3
                 2                     2
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

@end deffn





@deffn {Función} rectform_log_if_constant (@var{e})

La función @code{rectform_log_if_constant} convierte todos los términos
de la forma @code{log(c)} a @code{rectform(log(c))}, siendo @code{c} 
una expresión constante o declarada como tal.

@example
(%i1) rectform_log_if_constant(log(1-%i) - log(x - %i));
                                 log(2)   %i %pi
(%o1)            - log(x - %i) + ------ - ------
                                   2        4
(%i2) declare(a,constant, b,constant)$

(%i3) rectform_log_if_constant(log(a + %i*b));
                       2    2
                  log(b  + a )
(%o3)             ------------ + %i atan2(b, a)
                       2
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

@end deffn





@deffn {Función} simp_inequality (@var{e})

La función @code{simp_inequality} aplica ciertas simplificaciones
a conjunciones y disyunciones de inecuaciones.

@b{Limitaciones} La función @code{simp_inequality} está limitada en
al menos dos aspectos; en primer lugar, las simplificaciones son locales:

@example
(%i1) simp_inequality((x > minf) %and (x < 0));
(%o2) (x>1) %and (x<1)
@end example

En segundo lugar, @code{simp_inequality} no tiene en cuenta los hechos de la
base de datos:

@example
(%i2) assume(x > 0)$

(%i3) simp_inequality(x > 0);
(%o3)                         x > 0
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

@end deffn





@deffn {Función} standardize_inverse_trig (@var{e})

Esta función aplica las identidades @code{cot(x) = atan(1/x)} y
@code{acsc(x) = asin(1/x)} y similares con @code{asec}, @code{acoth}
y @code{acsch}. Consúltese Abramowitz y Stegun, ecuaciones
4.4.6 a 4.4.8 y 4.6.4 a 4.6.6.

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

@end deffn





@deffn {Función} subst_parallel (@var{l}, @var{e})

Dada la ecuación o lista de ecuaciones @var{l} y la expresión
@var{e}, sustituye @i{en paralelo} en @var{e} los miembros izquierdos
de las ecuaciones por los derechos:

@example
(%i1) load("to_poly_solve")$

(%i2) subst_parallel([x=y,y=x], [x,y]);
(%o2)                        [y, x]
@end example

Compárese el resultado anterior con las sustituciones hechas en serie: 

@example
(%i3) subst([x=y,y=x],[x,y]);
(%o3)                        [x, x]
@end example

La función @code{subst_parallel} es similar a @code{sublis}, excepto por
el hecho de que @code{subst_parallel} permite la sustitución de expresiones
no atómicas:

@example
(%i4) subst_parallel([x^2 = a, y = b], x^2 * y);
(%o4)                          a b
(%i5) sublis([x^2 = a, y = b], x^2 * y);

                                                             2
sublis: left-hand side of equation must be a symbol; found: x
 -- an error. To debug this try: debugmode(true);
@end example

Las sustituciones hechas por @code{subst_parallel} son literales, no semánticas,
por lo que @code{subst_parallel} no reconoce que @math{x * y} sea una subexpresión
de @math{x^2 * y}:

@example
(%i6) subst_parallel([x * y = a], x^2 * y);
                               2
(%o6)                         x  y
@end example

La función @code{subst_parallel} realiza todas las sustituciones
antes de proceder a la simplificación, lo que permite sustituciones
en expresiones condicionales que podrín producir 
errores en caso de simplificar antes de sustituir:

@example
(%i7) subst_parallel([x = 0], %if(x < 1, 5, log(x)));
(%o7)                           5
(%i8) subst([x = 0], %if(x < 1, 5, log(x)));

log: encountered log(0).
 -- an error. To debug this try: debugmode(true);
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve_extra.lisp")}.

Véanse también @code{subst}, @code{sublis} y @code{ratsubst}.

@end deffn






@deffn {Función} to_poly (@var{e}, @var{l})

La función @code{to_poly} intenta convertir la ecuación @var{e}
en un sistema de polinomios, junto con restricciones en forma de
desigualdades. Las soluciones del sistema polinómico que cumplan
las restricciones son, a su vez, las soluciones de la ecuación @var{e}.
Dicho de manera informal, @code{to_poly} intenta pasar a forma de
polinomio la ecuación @var{e}; un ejemplo ayudará a aclarar su
comportamiento:

@example
(%i1) load("to_poly_solve")$

(%i2) to_poly(sqrt(x) = 3, [x]);
                            2
(%o2) [[%g130 - 3, x = %g130 ], 
                      %pi                               %pi
                   [- --- < parg(%g130), parg(%g130) <= ---], []]
                       2                                 2
@end example

Las condiciones @code{-%pi/2<parg(%g130),parg(%g130)<=%pi/2} dicen que
@code{%g130} está en el rango de la función radical; cuando eso se
cumpla, el conjunto de ecuaciones de @code{sqrt(x) = 3} coincide con
el de @code{%g130-3,x=%g130^2}.

Para convertir a forma polinómica una expresión trigonométrica,
es necesario introducir una sustitución no algebraica; tal sustitución
se devuelve en la tercera lista de la respuesta de @code{to_poly}:

@example
(%i3) to_poly(cos(x),[x]);
                2                                 %i x
(%o3)    [[%g131  + 1], [2 %g131 # 0], [%g131 = %e    ]]
@end example

Los términos constantes no se transforman a polinomios a menos que el
número uno se introduzca en la lista de variables:

@example
(%i4) to_poly(x = sqrt(5),[x]);
(%o4)                [[x - sqrt(5)], [], []]
(%i5) to_poly(x = sqrt(5),[1,x]);
                            2
(%o5) [[x - %g132, 5 = %g132 ], 
                      %pi                               %pi
                   [- --- < parg(%g132), parg(%g132) <= ---], []]
                       2                                 2
@end example

Para generar un polinomio que tenga @math{sqrt(5) + sqrt(7)} como
raíz puede hacerse lo siguiente:

@example
(%i6) first(elim_allbut(first(to_poly(x = sqrt(5) + sqrt(7),
                                      [1,x])), [x]));
                          4       2
(%o6)                   [x  - 24 x  + 4]
@end example

Para hacer uso de esta función, ejecútese @code{load("to_poly")}.

Véase también @code{to_poly_solve}.

@end deffn






@deffn {Función} to_poly_solve (@var{e}, @var{l}, [options])

La función @code{to_poly_solve} intenta resolver las ecuaciones @var{e}
de incógnitas @var{l}. El argumento @var{e} puede ser una única ecuación,
o una lista o conjunto de ecuaciones; de forma similar, @var{l} puede ser un
símbolo o una lista o conjunto de símbolos. Cuando
uno de los elementos de @var{e} no sea una igualdad, como @math{x^2 -1},
se supodrá que es igual a cero.

La estrategia básica de @code{to_poly_solve} consiste en convertir la entrada en un
polinomio y luego invocar a la función @code{algsys}. Internamente,  @code{to_poly_solve}
asigna a @code{algexact} el valor @code{true}. Para cambiar el valor de @code{algexact},
debe anñadirse @code{'algexact=false} a la lista de argumentos de @code{to_poly_solve}.

Cuando @code{to_poly_solve} consigue determinar el conjunto de soluciones, cada
miembro del conjunto de soluciones es una lista en un objeto  @code{%union}:

@example
(%i1) load("to_poly_solve")$

(%i2) to_poly_solve(x*(x-1) = 0, x);
(%o2)               %union([x = 0], [x = 1])
@end example

Cuando @code{to_poly_solve} es incapaz de determinar el conjunto de soluciones,
devuelve una forma nominal de @code{%solve} y muestra un mensaje de aviso:

@example
(%i3) to_poly_solve(x^k + 2* x + 1 = 0, x);

Nonalgebraic argument given to 'to_poly'
unable to solve
                          k
(%o3)            %solve([x  + 2 x + 1 = 0], [x])
@end example

A veces se puede obtener la solución haciendo una sustitución en @code{%solve}:

@example
(%i4) subst(k = 2, %);
(%o4)                   %union([x = - 1])
@end example

Especialmente en el caso de las funciones trigonométricas, los resultados pueden
incorporar números enteros arbitrarios de la forma @code{%zXXX}, siendo @code{XXX}
un índice entero:

@example
(%i5) to_poly_solve(sin(x) = 0, x);
(%o5)   %union([x = 2 %pi %z33 + %pi], [x = 2 %pi %z35])
@end example

Para inicializar los índices, hágase uso de @code{nicedummies}:

@example
(%i6) nicedummies(%);
(%o6)    %union([x = 2 %pi %z0 + %pi], [x = 2 %pi %z1])
@end example

En ocasiones, se introducen números complejos arbitrarios de la forma
@code{%cXXX}, o reales de la forma @code{%rXXX}. La función @code{nicedummies}
inicializa estos identificadores a cero.

También a veces, la solución incorpora versiones simplificadas de los
operadores lógicos @code{%and}, @code{%or} y @code{%if}, que representan, respectivamente,
la conjunción, la disyunción y la implicación:

@example
(%i7) sol : to_poly_solve(abs(x) = a, x);
(%o7) %union(%if(isnonnegative_p(a), [x = - a], %union()), 
                      %if(isnonnegative_p(a), [x = a], %union()))
(%i8) subst(a = 42, sol);
(%o8)             %union([x = - 42], [x = 42])
(%i9) subst(a = -42, sol);
(%o9)                       %union()
@end example

El conjunto vacío se representa por @code{%union}.

La función @code{to_poly_solve} es capaz de resolver algunas ecuaciones
con potencias racionales, potencias no racionales, valores absolutos, funciones
trigonométricas y funciones del mínimo y del máximo. 
También puede resolver algunas ecuaciones resolubles en términos de la
función W de Lambert:

@example
(%i1) load("to_poly_solve")$

(%i2) to_poly_solve(set(max(x,y) = 5, x+y = 2), set(x,y));
(%o2)      %union([x = - 3, y = 5], [x = 5, y = - 3])
(%i3) to_poly_solve(abs(1-abs(1-x)) = 10,x);
(%o3)             %union([x = - 10], [x = 12])
(%i4) to_poly_solve(set(sqrt(x) + sqrt(y) = 5, x + y = 10),
                    set(x,y));
                     3/2               3/2
                    5    %i - 10      5    %i + 10
(%o4) %union([x = - ------------, y = ------------], 
                         2                 2
                                3/2                 3/2
                               5    %i + 10        5    %i - 10
                          [x = ------------, y = - ------------])
                                    2                   2
(%i5) to_poly_solve(cos(x) * sin(x) = 1/2,x,
                    'simpfuncs = ['expand, 'nicedummies]);
                                         %pi
(%o5)              %union([x = %pi %z0 + ---])
                                          4
(%i6) to_poly_solve(x^(2*a) + x^a + 1,x);
                                        2 %i %pi %z81
                                        -------------
                                  1/a         a
                  (sqrt(3) %i - 1)    %e
(%o6) %union([x = -----------------------------------], 
                                  1/a
                                 2
                                                  2 %i %pi %z83
                                                  -------------
                                            1/a         a
                          (- sqrt(3) %i - 1)    %e
                     [x = -------------------------------------])
                                           1/a
                                          2
(%i7) to_poly_solve(x * exp(x) = a, x);
(%o7)              %union([x = lambert_w(a)])
@end example

En el caso de inecuaciones lineales, @code{to_poly_solve} aplica automáticamente
la eliminación de Fourier:

@example
(%i8) to_poly_solve([x + y < 1, x - y >= 8], [x,y]);
                               7
(%o8) %union([x = y + 8, y < - -], 
                               2
                                                              7
                                 [y + 8 < x, x < 1 - y, y < - -])
                                                              2
@end example

Los argumentos opcionales deben tener forma de ecuación; generalmente, el orden
de estas opciones no reviste importancia.

@itemize

@item @code{simpfuncs = l}, siendo @code{l} una lista de funciones,
aplica la composición de los elementos de @code{l} a cada solución:
@example
(%i1) to_poly_solve(x^2=%i,x);
                               1/4             1/4
(%o1)       %union([x = - (- 1)   ], [x = (- 1)   ])
(%i2) to_poly_solve(x^2= %i,x, 'simpfuncs = ['rectform]);
                      %i         1             %i         1
(%o2) %union([x = - ------- - -------], [x = ------- + -------])
                    sqrt(2)   sqrt(2)        sqrt(2)   sqrt(2)
@end example

A veces, una simplificación puede anular una simplificación anterior:
@example
(%i3) to_poly_solve(x^2=1,x);
(%o3)              %union([x = - 1], [x = 1])
(%i4) to_poly_solve(x^2= 1,x, 'simpfuncs = [polarform]);
                                        %i %pi
(%o4)            %union([x = 1], [x = %e      ]
@end example

Maxima no comprueba que los elementos de la lista de funciones @code{l} sean
todos simplificaciones:
@example
(%i5) to_poly_solve(x^2 = %i,x, 'simpfuncs = [lambda([s],s^2)]);
(%o5)                   %union([x = %i])
@end example

Para convertir cada solución a real de doble precisión hágase uso de
@code{simpfunc = ['dfloat]}:
@example
(%i6) to_poly_solve(x^3 +x + 1 = 0,x, 
                    'simpfuncs = ['dfloat]), algexact : true;
(%o6) %union([x = - .6823278038280178], 
[x = .3411639019140089 - 1.161541399997251 %i], 
[x = 1.161541399997251 %i + .3411639019140089])
@end example

@item Con la opción @code{use_grobner = true} se aplica la función 
@code{poly_reduced_grobner} a las ecuaciones antes de intentar resolverlas.
En primer lugar, esta opción proporciona una manera de soslayar algunas
debilidades de la función @code{algsys}:

@example
(%i7) to_poly_solve([x^2+y^2=2^2,(x-1)^2+(y-1)^2=2^2],[x,y],
                    'use_grobner = true);
                    sqrt(7) - 1      sqrt(7) + 1
(%o7) %union([x = - -----------, y = -----------], 
                         2                2
                                 sqrt(7) + 1        sqrt(7) - 1
                            [x = -----------, y = - -----------])
                                      2                  2
(%i8) to_poly_solve([x^2+y^2=2^2,(x-1)^2+(y-1)^2=2^2],[x,y]);
(%o8)                       %union()
@end example

@item @code{maxdepth = k}, siendo @code{k} un positivo entero, controla el nivel
de recursión. El valor por defecto es cinco. Cuando se excede el nivel de recursión
se obtiene un mensaje de error:
@example
(%i9) to_poly_solve(cos(x) = x,x, 'maxdepth = 2);

Unable to solve
Unable to solve
(%o9)        %solve([cos(x) = x], [x], maxdepth = 2)
@end example

@item Con @code{parameters = l}, siendo @code{l} una lista de símbolos,
el programa intenta encontrar una solución válida para todos los miembros de la
lista @code{l}:
@example
(%i10) to_poly_solve(a * x = x, x);
(%o10)                   %union([x = 0])
(%i11) to_poly_solve(a * x = x, x, 'parameters = [a]);
(%o11) %union(%if(a - 1 = 0, [x = %c111], %union()), 
                               %if(a - 1 # 0, [x = 0], %union()))
@end example
En @code{(%o2)}, el programa introduce una variable ficticia; para reinicializarla,
úsese la función @code{nicedummies}:
@example
(%i12) nicedummies(%);
(%o12) %union(%if(a - 1 = 0, [x = %c0], %union()), 
                               %if(a - 1 # 0, [x = 0], %union()))
@end example
@end itemize

@code{to_poly_solve} utiliza información almacenada en el array @code{one_to_one_reduce}
para resolver ecuaciones de la forma  @math{f(a) = f(b)}. La asignación 
@code{one_to_one_reduce['f,'f] : lambda([a,b], a=b)} le dice a @code{to_poly_solve}
que el conjunto de soluciones de @math{f(a) = f(b)} es igual al conjunto de soluciones
de @math{a=b}:
@example
(%i13) one_to_one_reduce['f,'f] : lambda([a,b], a=b)$

(%i14) to_poly_solve(f(x^2-1) = f(0),x);
(%o14)             %union([x = - 1], [x = 1])
@end example

De forma más general, la asignación 
@code{one_to_one_reduce['f,'g] : lambda([a,b], w(a,b)=0} le indica a
@code{to_poly_solve} que el cojunto de soluciones de @math{f(a) = f(b)} 
es igual al conjunto de soluciones de @math{w(a,b) = 0}:
@example
(%i15) one_to_one_reduce['f,'g] : lambda([a,b], a = 1 + b/2)$

(%i16) to_poly_solve(f(x) - g(x),x);
(%o16)                   %union([x = 2])
@end example

Además, @code{to_poly_solve} utiliza información almacenada en el array
@code{function_inverse} para resolver ecuaciones de la forma @math{f(a) = b}.
La asignación @code{function_inverse['f] : lambda([s], g(s))} le dice a
@code{to_poly_solve} que el conjunto de soluciones de @math{f(x) = b} es
igual al conjunto de soluciones de @math{x = g(b)}:
@example
(%i17) function_inverse['Q] : lambda([s], P(s))$

(%i18) to_poly_solve(Q(x-1) = 2009,x);
(%o18)              %union([x = P(2009) + 1])
(%i19) function_inverse['G] : lambda([s], s+new_variable(integer));
(%o19)       lambda([s], s + new_variable(integer))
(%i20) to_poly_solve(G(x - a) = b,x);
(%o20)             %union([x = b + a + %z125])
@end example

@b{Notas}

@itemize

@item Las incógnitas a resolver no necesitan ser símbolos, lo cual es
cierto cuando @code{fullratsubst} es capaz de hacer las sustituciones de forma apropiadas:
@example
(%i1) to_poly_solve([x^2 + y^2 + x * y = 5, x * y = 8],
                    [x^2 + y^2, x * y]);
                                  2    2
(%o1)           %union([x y = 8, y  + x  = - 3])
@end example

@item Cuando las ecuaciones involucran conjugados de complejos, el programa
añade automáticamente las ecuaciones conjugadas:
@example
(%i1) declare(x,complex)$

(%i2) to_poly_solve(x + (5 + %i) * conjugate(x) = 1, x);
                                   %i + 21
(%o2)              %union([x = - -----------])
                                 25 %i - 125
(%i3) declare(y,complex)$

(%i4) to_poly_solve(set(conjugate(x) - y = 42 + %i,
                        x + conjugate(y) = 0), set(x,y));
                           %i - 42        %i + 42
(%o4)        %union([x = - -------, y = - -------])
                              2              2
@end example

@item Cuando las funciones involucran valores absolutos, @code{to_poly_solve}
consulta los hechos de la base de datos para decidir si los argumentos de los valores
absolutos son números complejos:
@example
(%i1) to_poly_solve(abs(x) = 6, x);
(%o1)              %union([x = - 6], [x = 6])
(%i2) declare(z,complex)$

(%i3) to_poly_solve(abs(z) = 6, z);
(%o3) %union(%if((%c11 # 0) %and (%c11 conjugate(%c11) - 36 = 
                                       0), [z = %c11], %union()))
@end example

Esta es la única situación en la que @code{to_poly_solve} consulta la base de
datos; si una incógnita se declara, por ejemplo, como entero, @code{to_poly_solve} lo ignora.
@end itemize

Para hacer uso de esta función, ejecútese @code{load("to_poly_solve")}.

Véase también @code{algexact}, @code{resultant}, @code{algebraic} y @code{to_poly}.

@end deffn

