Transformaciones algebraicas: desarrollar, simplificar, evaluar, sustituir...
Maxima puede realizar operaciones algebraicas conceptualmente simples (multiplicar expresiones, factorizar, simplificar, sustituir, evaluar...) pero cuyo
cálculo puede resultar tedioso para humanos. En este apartado describimos
los comandos que permiten realizar las operaciones algebraicas usuales como desarrollar productos de sumas o
potencias de sumas, simplificar funciones racionales, factorizar
polinómios, hacer sustituciones formales en una expresión o evaluar una expresión,
por ejemplo, asignando valores a algunos de los parámetros de la misma. También
explicamos comandos para calcular el máximo común divisor y el mínimo
común múltiplo de polinomios, realizar divisiones enteras de polinomios,
realizar desarrollos o simplificaciones de expresiones trigonométricas o logarítmicas,
eliminar varias entre varias ecuaciones, incluso realizar descomposiciones en
fracciones simples.
Desarrollar
Los comandos expand y ratexpand sirven para efectuar el desarrollo de
expresiones algebraicas, tales como elevar a una potencia, multiplicar polinomios o fracciones polinómicas.
- expand(Expresión,PotenciasPositivas,PotenciasNegativas)
Los argumentos PotenciasPositivas y PotenciasNegativas son optativos.
El primero indica el exponente máximo en las potencias positivas que debe ser desarrollado, el segundo es análogo pero referido a las potencias negativas.
- ratexpand(Expresión)
Realiza el desarrollo combinando fracciones sobre un denominador común
que corresponde al mínimo común múltiplo de los denominadores y parte el numerador
(si se trata de una suma) en sus monomios correspondientes. En el caso de polinomios ratexpand es más eficiciente que expand.
- r:(x^2+1)^2+(x-1)^5-2*(x-3)/(1+(x+2)^5);
- expand(r);
- expand(r,2,0);
- r: (x - 1)/(x + 1)^2 + 1/(x - 1);
- expand(r);
- ratexpand(r);
El comando expand también se puede aplicar al desarrollo de expresiones trigonométricas en las que aparecen senos y cosenos de sumas de ángulos, de productos de ángulos por un número, o del ángulo mitad.
Para mejorar el control en los desarrollos se dispone de las siguientes variables lógicas.
- trigexpandplus
Determina
si las expresiones del tipo sin(x+y), y similares, son o no desarrolladas
(valor por defecto true)
- trigexpandtimes
Determina si las expresiones del
tipo sin(3*x) y similares serán o no desarrolladas
(valor por defecto true)
- halfangles
Controla si las fórmulas con ángulo mitad
serán o no simplificadas
(valor por defecto, false),
- trigsign
Incluye identidades como sin(-x)=-sin(x) en los desarrollos
(valor por defecto true)
- triginverses
Controla la simplificación de las composiciones de funciones trigonométricas e hiperbólicas con sus funciones inversas. Se le pueden asignar los siguientes valores: all, true y false
(valor por defecto all)
- trigexpand
Controla si se aplicarán los desarrollos de sumas y productos, conforme a lo especificado en las correspondientes variables lógicas, cuando el valor es true o no se desarrollarán cuando el valor es false
(valor por defecto false)
Además de como variable lógica, trigexpand actúa también en la forma trigexpand(Expresión) cuyo efecto es el de transformar Expresión asignando sobre ella el valor true a trigexpand, con indepencia del que tenga establecido en ese momento
- trigexpandplus; trigexpandtimes; halfangles;
- expand( sin(x+y)+ cos(2*x)-sin (1/2*x) );
- trigexpand:true$ expand( sin(x+y)+ cos(2*x)-sin (x/2) );
- halfangles:true$ expand( sin(x+y)+ cos(2*x)-sin (x/2) );
- trigexpand:true$ expand( tan(x+y) );
- trigexpand:false$ trigsign:true$ trigexpand( tan(x-y) );
- expand( trigreduce( sin(x)^2+ cos(x)^2 ) );
En el caso de los logaritmos también se dispone de variable lógica para controlar el desarrollo de los mismos
- logexpand
Es una declaración que admite varias asignaciones: true desarrolla log(a^b)=b*log(a);
false, no hace desarrollos; all, desarrolla log(a*b)=log(a)+log(b); super, desarrolla log(a/b)=log(a)-log(b);
(valor por defecto true)
logexpand:super$ log(x^y); log(x*y); log(%e^1/y)
Otra herramienta útil para el cálculo manual de primitivas es la descomposición en fracciones simples
- partfrac(Expresión,Variable)
Realiza la descomposición en fracciones simples
partfrac(1/((x+1)^2*(x^2+x+1)),x);
Evaluar y sustituir
Uno de los comandos más potentes y versatiles de Maxima que permite evaluar expresiones es
- ev(Expresión,Argumento_1,Argumento_2,...,Argumento_n);
- Expresión,Argumento_1,Argumento_2,...,Argumento_n;
En el primer ítem se muestra la sintaxis general, tanto para evaluaciones globales como para otras limitadas a ciertas subexpresiones o grupos. En el segundo ítem se muestra una sintaxis alternativa aplicable en evaluaciones globales.
- f(x):=cos(x)$ ev(f(x),x=0);
- x^2 - %pi/2+ev(atan(x),x=1);
- ev(sin(1),numer);
- x**3-2*x**2-747-sqrt(y),x=54,y=2;
La siguiente secuencia de evaluaciones realizadas a partir de una primera expresión le ayudará a comprender el funcionamiento.
- EC : sin(x)+cos(y)+(w+1)**2+'diff(sin(w),w);
A la expresi&ioacute;n le asignamos el nombre EC
- ev(EC,diff);
Ejecutamos el cálculo la derivada indicada en EC.
- ev(EC,expand);
Desarrollamos la potencia indicada en EC
-
ev(EC,expand,diff);
Las dos evaluaciones anteriores a la vez
-
ev(EC,expand,diff,x=2,y=1);
Y ahora cuatro evaluaciones al mismo tiempo
El Argumento nouns en un comando ev tiene el efecto de evaluar las formas nominales (comandos no desarrollados).
-
f(x):='integrate(x^2+ 1,x)+'diff(log(1+x^2),x);
Definimos una función que contiene formas nominales, es decir, comandos que no se expanden;
en este caso, son integrales y derivadas
- ev(f(x),nouns)
Evaluamos todas las formas nominales
Pueden realizarse sustituciones formales en expresiones utilizando los siguientes comandos:
- subst(Sustituto,Original,Expresión)
- subst(Original=Sustituto,Expresión)
- subst([Ecuación_1,Ecuación_2,...Ecuación_n],Expresión)
siendo Ecuación_j lo análogo al precedente pero con más ecuaciones.
- at(Expresión,Ecuación)
- at(Expresión,[Ecuación_1, Ecuación_2,..., Ecuación_n])
- atvalue(expresión, [x_1=a_1, x_2=a_2,...x_m=a_m], valor)
Es un mecanismo análogo a los anteriores de uso frecuente en ecuaciones diferenciales para establecer los valores frontera. Con expresión nos referimos a una función f(x_1,x_2,...x_m)
o a la derivada de una tal función indicando el orden de derivación en cada variable
'diff(f(x_1,x_2,...x_m), x_1, n_1, x_2, n_2,...,x_m, m_n)
. El funcionamiento es que la expresión tiene un cierto valor cuando [x_1=a_1, x_2=a_2,...x_m=a_m]
El Original que es reemplazado por un Sustituto debe
ser un "átomo" o bien un "grupo completo" de Expresión; así, por
ejemplo, en la expresión 2*(x+y+z)/w, x+y+z constituye un grupo mientras que
x+y no.
- subst(v,x+y+z,2*(x+y+z)^(a+b));
De las tres primeras es, para mi, la menos sencilla de recordar al hacer substituciones
- subst(x+y+z=v,2*(x+y+z)^(a+b));
Esta sintaxis me resulta más fácil de recordar
- subst([x+y+z=v, a+b=w],2*(x+y+z)^(a+b));
De este modo hacemos varias sustituciones simultáneas usando una lista para las mismas
- subst(x=0,diff(sin(x),x,3));
En la tercera derivada del seno, substituimos x por 0
- at(2*(x+y+z)^w, x+y+z=v);
- at(2*(x+y+z)^w,[x+y+z=v, w=a+b]);
- kill(f)$
at('integrate(f(x),x,a,b),[a=0,b=1]);
Como se aprecia, la sintaxis de at
es diferente, pero la funcionalidad es la misma que la de subst
- atvalue (f(x,y), [x = 0, y = 1], a^2);
El comando ev
también permite realizar substituciones. Alguna de las anteriores las hacemos con ev
- ev(2*(x+y+z)^w, x+y+z=v);
- ev(2*(x+y+z)^w, x+y+z=v, w=p+q);
Si ejecuta el código que sigue obtendrá más ejemplos en la ventana de la consola (preste atención para responder a la pregunta que se le hace)
example(subst);
Factorizar
Para realizar la operación inversa de desarrollar una expresión polinómica se utiliza el comando
que factoriza la Expresión, conteniendo cualquier número de variables
o funciones, en factores irreducibles sobre los enteros.
- expand( (x-6)^5*(x+1)^3*(x^2+1) );
- factor( % );
- factor( x^4-1 );
- factor( 2^63-1 );
Pero el comando tiene sus limitaciones...
factor( x^4+1 );
Simplificar expresiones racionales
Los dos comandos que siguen sirven para ese propósito. El segundo de ellos es como un reforzamiento del primero, pues en ocasiones es necesario reiterar varias veces el primero hasta conseguir la simplificación óptima, esa es la función que automáticamente realiza el segundo.
- ratsimp(Expresión)
- fullratsimp(Expresión)
- ratsimp( (x^4-1)/(x^2 -1) );
- ratsimp( (x^(A/2)+1)^2*(x^(A/2)-1)^2/(x^A-1) );
Para ir más lejos se requiere una nueva actuación
- ratsimp( % );
- fullratsimp( (x^(A/2)+1)^2*(x^(A/2)-1)^2/(x^A-1) );
Con este comando se ha conseguido el objetivo en un s&ioacute;lo paso
En el ejemplo siguiente realizamos la derivada de una primitiva y no queda claro que se recupere el valor inicial. Pero fullratsimp zanja la cuestión
- diff(integrate(1/(x^3 + 1), x), x);
- fullratsimp(%);
Otro ejemplo
- kill(all) $ fullratsimp(sqrt(x^2));
- kill(all) $ assume (x>0) $ fullratsimp(sqrt(x^2));
División entera
El cociente y el resto de una división entera (entre números enteros o entre polinomios) puede obtenerse mediante
- divide(Entero1,Entero2)
- divide(Polinomio1,Polinomio2)
El resultado es una lista en la que el primer elemento es el cociente y el segundo el resto. Algunos ejemplos:
- divide( 7, 2 );
El cociente es 3 y el resto 1
- divide( (x^2-1), (x-1) );
El cociente es x+1 y el resto 0
- divide( x^3-1, x^2-1 );
- Resultado: divide( x^5-2*x^2+x-1, x^2+1 ); cociente:Resultado[1]; resto:Resultado[2]; divisor:x^2+1; cociente*divisor+resto; expand(%);
En este ejemplo el "Resultado" es una lista con dos elementos: a los que llamamos respectivamente "cociente" y "resto". A continuación efectuamos la comprobación de que "cociente*divisor+resto=cociente*Polinomio2+resto" coincide con "Polinomio1"
Simplificar expresiones trigonométricas
El objetivo aquí es justamente el opuesto de desarrollar (expand
) expresiones trigonométricas. Es un proceso más complicado y para tratar de llevarlo a cabo, Maxima implementa tres comandos
- trigsimp(Expresión)
Utiliza fórmulas fundamentales como sin(x)^2 + cos(x)^2 = 1 y cosh(x)^2 - sinh(x)^2 = 1 para realizar simplificaciones.
- trigreduce(Expresión, Variable)
Trata de combinar productos y potencias de funciones trigonométricas e hiperbólicas para producir expresiones con ángulos dobles y similares.
- trigrat(Expresión)
Es otro comando para racionalizar expresiones
trigonométricas.
- trigsimp(sin(x)^2 + cos(x)^2);
- (1-cos(x))*(1+cos(x)); expand(%); trigsimp(%); trigreduce(%,x);
- trigsimp(sin(y) / sqrt( (1-sin(y))*(sin(y)+1) ));
- trigsimp(cos(x)^4-sin(x)^4); trigreduce(%); trigrat(%);
- trigexpand:false$ trigreduce(cosh(x)^4-sinh(x)^4); expand(%);
Simplificar expresiones logarítmicas
Maxima también dispone de herramientas para tratar de hacer el proceso inverso al de transformar en sumas el logaritmo del producto y otros similares
- logcontract (Expresión)
Trata de "contraer" expresiones logarítmicas
- logsimp
Variable l&ioacute;gica que controla la simplificaciones del tipo log(%e^y)=y
(valor por defecto true)
2*(A*log(X) - 3*B*log(Y)); logcontract(%);
Obsérvese que únicamente los enteros 2 y 3 han sido convertidos en potencias, mientras que A y B no lo han sido. Esa es la forma de operar por defecto. Pero podemos conseguir que A y B también se conviertan en potencias declarándolos como enteros (localmente en este caso)
block( declare(A,integer), declare(B,integer),
logcontract(2*(A*log(X) - 3*B*log(Y))) );
Otros comandos para simplificar
Como hemos ido viendo hay gran variedad de comandos y variables lógicas para desarrollar, contraer o simplificar diferentes tipos de expresiones. En algunos casos no es evidente el significado de "simplificar" y el comando logcontract es un buen ejemplo de ello. A veces el resultado deseado se obtiene tras la utilización de varios comandos. Incluimos aquí un nuevo comando que también puede ser de utilidad para realizar este tipo de transformaciones algebraicas.
- rootscontract(Expresión)
Convierte productos de raíces en raíces de productos.
? rootscontract;
- radcan(Expresión)
trata de simplificar expresiones que contengan
logaritmos, exponenciales y radicales:
? radcan;
Pero el sentido que se asigna a "simplificar" no resulta trasparente, como muestran los ejemplos que siguen y en los que aparecen en la propia ayuda en línea del comando.
- kill(all)$ log(%e^2/y); radcan(log(%e^2/y));
- log(x^a/y^b); radcan(%);
- cos(x+y); radcan(%);
- cos(x)*cos(y)-sin(x)*sin(y); radcan(%);
- log(1+2*a^x+a^(2*x)) / log(1+a^x); radcan(%);
- log(1+2*a^x+a^(2*x)) / log(1+a^x); fullratsimp(%);
- diff(sqrt(cos(x)), x, 2); radcan(%);
- diff(sqrt(cos(x)), x, 2); fullratsimp(%);
- (x^(A/2)+1)^2*(x^(A/2)-1)^2/(x^A-1); radcan(%);
- Observe que comportamiento tan curioso, comparando con el precedente.
(x^(a/2)+1)^2*(x^(a/2)-1)^2/(x^a-1); radcan(%);
- (x^(A/2)+1)^2*(x^(A/2)-1)^2/(x^A-1); fullratsimp(%);
- radcan((1+x+x^2)^3);
- radcan(1+2*x+x^2);
A modo de resumen: hay varios comandos que pueden utilizarse para desarrollar, contraer o simplificar expresiones algebraicas, trigonométricas y logaritmicas, pero dependiendo del objetivo que se pretenda conseguir habrá que experimentar el resultado de la acción de los comandos sobre ellas.
Conviene no olvidar que, en algún caso, puede ocurrir que Maxima no haga lo que usted desearía que hiciera. Y los ejemplos que siguen son autoexplicativos
- sqrt(a)*sqrt(b);
expand(%);
ratexpand(%);
factor(%);
ratsimp(%);
fullratsimp(%);
El resultado siempre es el mismo: sqrt(a) sqrt(b)
- sqrt(a*b);
ratexpand(%);
Lo mismo ocurre en este caso: sqrt(a b)
- asin( sin(y) );
trigsimp(%);
trigreduce(%);
No obstante, en otras ocasiones, el comportamiento de estos comandos resulta más previsible:
(1-cos(x))*(1+cos(x));
expand(%);
trigsimp(%);
trigreduce(%,x);
La interfaz de wxMaxima tiene implementados en sus menús algunos de los comandos anteriores
Ap_DesarrollarSimplificar.wxmx