Operaciones Matemáticas Simbólicas con Python

Sympy (sympy.org)

Mariano Rivera

Mayo 2017

sympy es una módulo de python (en versión beta) para procesamiento simbólico

from sympy import *
init_printing()

a = Rational(1,2)
a

12\frac{1}{2}

Definición de símbolos (variables, vectores, matrices, funciones, etc)

x = Symbol('x')
y = Symbol('y')

expand((x+y)**2)

x2+2xy+y2x^{2} + 2 x y + y^{2}

Lista de símbolos

Elementos con subíndice

symbols('x5:10')

(x5,x6,x7,x8,x9)\left ( x_{5}, \quad x_{6}, \quad x_{7}, \quad x_{8}, \quad x_{9}\right )

Dos formas de símbolos con multiple indexación (p.ej., arreglos multidimensionales)

x1 = symbols('x_1:4\,1:3')    # subindices
x2 = symbols('x(1:4\,1:3)')   # parentésis
x1

(x1,1,x1,2,x2,1,x2,2,x3,1,x3,2)\left ( x_{1,1}, \quad x_{1,2}, \quad x_{2,1}, \quad x_{2,2}, \quad x_{3,1}, \quad x_{3,2}\right )

x2

(x(1,1),x(1,2),x(2,1),x(2,2),x(3,1),x(3,2))\left ( x(1,1), \quad x(1,2), \quad x(2,1), \quad x(2,2), \quad x(3,1), \quad x(3,2)\right )

Matrix(x1).reshape(3,2)

[x1,1x1,2x2,1x2,2x3,1x3,2]\left[\begin{matrix}x_{1,1} & x_{1,2}\\x_{2,1} & x_{2,2}\\x_{3,1} & x_{3,2}\end{matrix}\right]

Matrix(x2).reshape(3,2)

[x(1,1)x(1,2)x(2,1)x(2,2)x(3,1)x(3,2)]\left[\begin{matrix}x(1,1) & x(1,2)\\x(2,1) & x(2,2)\\x(3,1) & x(3,2)\end{matrix}\right]

Números complejos

expand(x+y, complex=True)

(x)+(y)+ix+iy\Re{\left(x\right)} + \Re{\left(y\right)} + i \Im{x} + i \Im{y}

Expansión usaindo identidades trigonométricas

expand(cos(x+y), trig=True)

sin(x)sin(y)+cos(x)cos(y)- \sin{\left (x \right )} \sin{\left (y \right )} + \cos{\left (x \right )} \cos{\left (y \right )}

Simplificación de expresiones algebraicas

simplify((x+x*y)/x**2)

1x(y+1)\frac{1}{x} \left(y + 1\right)

Factorización de expresiones algebraicas

factor(x**2+2*x*y+y**2)

(x+y)2\left(x + y\right)^{2}

Del help(factor) vemos los sigi¡uientes ejemplos

from sympy import factor, sqrt
# evitamos definir los simbolos, importandolos
from sympy.abc import x, y
    
factor(2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y)

2(x+y)(x2+1)22 \left(x + y\right) \left(x^{2} + 1\right)^{2}

factor((x**2 + 4*x + 4)**10000000*(x**2 + 1))

(x+2)20000000(x2+1)\left(x + 2\right)^{20000000} \left(x^{2} + 1\right)

factor(x**2 + 1)

x2+1x^{2} + 1

Definiendo el dominio en el cual se usará la factorización, si asumimos que estamos inteseados solo en el modulo 22 de lo resulta de avaluar x2+1x^2+1, notamos que

(x+1)2%2=(x2+2x+1)%2=(x2+1)%2 (x+1)^2 \% 2 = (x^2+2x+1) \% 2 = (x^2+1) \%2

con sympy esta factorización se obtiene:

factor(x**2 + 1, modulus=2)

(x+1)2\left(x + 1\right)^{2}

Con gaussian=True se factoriza sobre las rotaciones Gaussianas

factor(x**2 + 1, gaussian=True)

(xi)(x+i)\left(x - i\right) \left(x + i\right)

o equivalentemente, agregando una extension=[I] para factorizar usando raices complejas

factor(x**2 + 1, extension=[I])

(xi)(x+i)\left(x - i\right) \left(x + i\right)

extendiendo usando 2\sqrt{2}

factor(x**2 - 2, extension=sqrt(2))

(x2)(x+2)\left(x - \sqrt{2}\right) \left(x + \sqrt{2}\right)

Límites

limit(sin(x)/x, x, 0)

11

Diferenciación

z = diff(1/(1+exp(-x)), x)
z

ex(1+ex)2\frac{e^{- x}}{\left(1 + e^{- x}\right)^{2}}

Impresión de código python

print_python(z)
x = Symbol('x')
e = exp(-x)/(1 + exp(-x))**2

Expansión en series

series(cos(x), x, 8)

cos(8)(x8)sin(8)12(x8)2cos(8)+16(x8)3sin(8)+124(x8)4cos(8)1120(x8)5sin(8)+O((x8)6;x8)\cos{\left (8 \right )} - \left(x - 8\right) \sin{\left (8 \right )} - \frac{1}{2} \left(x - 8\right)^{2} \cos{\left (8 \right )} + \frac{1}{6} \left(x - 8\right)^{3} \sin{\left (8 \right )} + \frac{1}{24} \left(x - 8\right)^{4} \cos{\left (8 \right )} - \frac{1}{120} \left(x - 8\right)^{5} \sin{\left (8 \right )} + \mathcal{O}\left(\left(x - 8\right)^{6}; x\rightarrow 8\right)

series(exp(x),x,5)

e5+(x5)e5+e52(x5)2+e56(x5)3+e524(x5)4+e5120(x5)5+O((x5)6;x5)e^{5} + \left(x - 5\right) e^{5} + \frac{e^{5}}{2} \left(x - 5\right)^{2} + \frac{e^{5}}{6} \left(x - 5\right)^{3} + \frac{e^{5}}{24} \left(x - 5\right)^{4} + \frac{e^{5}}{120} \left(x - 5\right)^{5} + \mathcal{O}\left(\left(x - 5\right)^{6}; x\rightarrow 5\right)

Integración indefinida

integrate(2*x + sinh(x), x)

x2+cosh(x)x^{2} + \cosh{\left (x \right )}

Integración definida

integrate(sin(x)**2, (x, 0, pi/2))

π4\frac{\pi}{4}

Solución de ecuaciones

solve(x**4 - 1, x)

[1,1,i,i]\left [ -1, \quad 1, \quad - i, \quad i\right ]

solve([x + 5*y - 2, -3*x + 6*y - 15], [x, y])

{x:3,y:1}\left \{ x : -3, \quad y : 1\right \}

Algebra Lineal

from sympy import Matrix, latex
A = Matrix([[1,0], [0,1]])
A

[1001]\left[\begin{matrix}1 & 0\\0 & 1\end{matrix}\right]

Impresión de código látex

latex(A)
'\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]'

Matrices

x = Symbol('x')
y = Symbol('y')
A = Matrix([[1,x], [y,1]])
A.T

[1yx1]\left[\begin{matrix}1 & y\\x & 1\end{matrix}\right]

A**2

[xy+12x2yxy+1]\left[\begin{matrix}x y + 1 & 2 x\\2 y & x y + 1\end{matrix}\right]

Cálculo de eigenvalores

A = Matrix(2,2,symbols('a_{{1:3}{1:3}}'))
A

[a11a12a21a22]\left[\begin{matrix}a_{{1}{1}} & a_{{1}{2}}\\a_{{2}{1}} & a_{{2}{2}}\end{matrix}\right]

l1 = Symbol('l_1')
d=det((A-l1*Matrix([[1,0], [0,1]])))
solve(d,l1)

[a112+a22212a1122a11a22+4a12a21+a222,a112+a222+12a1122a11a22+4a12a21+a222]\left [ \frac{a_{{1}{1}}}{2} + \frac{a_{{2}{2}}}{2} - \frac{1}{2} \sqrt{a_{{1}{1}}^{2} - 2 a_{{1}{1}} a_{{2}{2}} + 4 a_{{1}{2}} a_{{2}{1}} + a_{{2}{2}}^{2}}, \quad \frac{a_{{1}{1}}}{2} + \frac{a_{{2}{2}}}{2} + \frac{1}{2} \sqrt{a_{{1}{1}}^{2} - 2 a_{{1}{1}} a_{{2}{2}} + 4 a_{{1}{2}} a_{{2}{1}} + a_{{2}{2}}^{2}}\right ]

Producto vectorial (dot) con Python 3.4+

En python 3.4+ se introdujo el operador @ para mejorar la legibilidad en operaciones que impliquen el calculo del producto vectorial

antes: np.lingalg.dot(x,x)
ahora x@x

import numpy as np
xn=np.arange(1,3)
print('xn=', xn)
print(r'<xn,xn> =', xn@xn)
xn= [1 2]
<xn,xn> = 5

Usando este operador con operaciones simbólicas (aqui es importante cuidar que las dimensiones de las “Matrices” sean válidas)

x = Symbol('x')
y = Symbol('y')
v = Matrix([x,y])
v

[xy]\left[\begin{matrix}x\\y\end{matrix}\right]

v.T@v

[x2+y2]\left[\begin{matrix}x^{2} + y^{2}\end{matrix}\right]

v@v.T

[x2xyxyy2]\left[\begin{matrix}x^{2} & x y\\x y & y^{2}\end{matrix}\right]

from sympy import Matrix, latex, symbols

X = Matrix(symbols('x(1:5\,1:5)')).reshape(4,4)
Y = X.T*X
Y.trace()

x(1,1)2+x(1,2)2+x(1,3)2+x(1,4)2+x(2,1)2+x(2,2)2+x(2,3)2+x(2,4)2+x(3,1)2+x(3,2)2+x(3,3)2+x(3,4)2+x(4,1)2+x(4,2)2+x(4,3)2+x(4,4)2x(1,1)^{2} + x(1,2)^{2} + x(1,3)^{2} + x(1,4)^{2} + x(2,1)^{2} + x(2,2)^{2} + x(2,3)^{2} + x(2,4)^{2} + x(3,1)^{2} + x(3,2)^{2} + x(3,3)^{2} + x(3,4)^{2} + x(4,1)^{2} + x(4,2)^{2} + x(4,3)^{2} + x(4,4)^{2}

Cálculo de Gradiente y Hessiano de una función

from sympy import *
init_printing()

x = Symbol('x')
y = Symbol('y')
z = Symbol('z')

sbl = Matrix(symbols('x,y,z'))

f = x**2 + 2*y**2 + 3*z**2 - 6*x**2*z + 4*y*x + 5*y*z**2 - 3*x*y*z
f = x**2 + 2*y**2 + 3*z**2
f

x2+2y2+3z2x^{2} + 2 y^{2} + 3 z^{2}

Gradiente de la función ff
f(x)=[f(x)x1f(x)x2f(x)x3f(x)xn] \nabla f(x) = \begin{bmatrix} \frac{\partial f(x) }{ \partial x_1} \\ \frac{\partial f(x) }{ \partial x_2} \\ \frac{\partial f(x) }{ \partial x_3} \\ \vdots \\ \frac{\partial f(x) }{ \partial x_n} \\ \end{bmatrix}
Matriz Jacobiana o Jacobiano de la función ff:

Jf=[f(x)x1,f(x)x2,f(x)x3,,f(x)xn] J_f = \begin{bmatrix} \frac{\partial f(x) }{ \partial x_1}, & \frac{\partial f(x) }{ \partial x_2}, & \frac{\partial f(x) }{ \partial x_3}, & \ldots, & \frac{\partial f(x) }{ \partial x_n} \end{bmatrix}
=[f1(x)x1,f1(x)x2,f1(x)x3,,f1(x)xnf2(x)x1,f2(x)x2,f2(x)x3,,f2(x)xnf3(x)x1,f3(x)x2,f3(x)x3,,f3(x)xn,fm(x)x1,fm(x)x2,fm(x)x3,,fm(x)xn] = \begin{bmatrix} \frac{\partial f_1(x) }{ \partial x_1} &, \frac{\partial f_1(x) }{ \partial x_2}, & \frac{\partial f_1(x) }{ \partial x_3}, &\ldots, &\frac{\partial f_1(x) }{ \partial x_n} \\ \frac{\partial f_2(x) }{ \partial x_1}, &\frac{\partial f_2(x) }{ \partial x_2}, & \frac{\partial f_2(x) }{ \partial x_3},& \ldots, &\frac{\partial f_2(x) }{ \partial x_n} \\ \frac{\partial f_3(x) }{ \partial x_1}, &\frac{\partial f_3(x) }{ \partial x_2}, & \frac{\partial f_3(x) }{ \partial x_3}, &\ldots, & \frac{\partial f_3(x) }{ \partial x_n} \\ \vdots, & \vdots& \vdots & \ddots & \vdots \\ \frac{\partial f_m(x) }{ \partial x_1}, &\frac{\partial f_m(x) }{ \partial x_2}, & \frac{\partial f_m(x) }{ \partial x_3}, &\ldots, & \frac{\partial f_m(x) }{ \partial x_n} \end{bmatrix}

Podemos ver intuitivamente el Jacobiano como un operador que “expande” cada renglón de la función vectorial ff en sus derivadas parciales.

Luego si ff1f \equiv f_1:
f=Jf \nabla f = J_f^\top

f = Matrix([f]) # función vectorial de un solo elemento
f

[x2+2y2+3z2]\left[\begin{matrix}x^{2} + 2 y^{2} + 3 z^{2}\end{matrix}\right]

A vectores les podemos calcular el Jacobiano (no a escalares)

G=f.jacobian(sbl).T
G

[2x4y6z]\left[\begin{matrix}2 x\\4 y\\6 z\end{matrix}\right]

Gradiente de ff

f(x)=[f(x)x1f(x)x2f(x)x3f(x)xn] \nabla f(x) = \begin{bmatrix} \frac{\partial f(x) }{ \partial x_1} \\ \frac{\partial f(x) }{ \partial x_2} \\ \frac{\partial f(x) }{ \partial x_3} \\ \vdots \\ \frac{\partial f(x) }{ \partial x_n} \\ \end{bmatrix}

Matrix Hessiana o Hessiano de ff:

Hf=def[2f(x)x12,2f(x)x1x2,2f(x)x1x3,,2f(x)x1xn2f(x)x2x1,2f(x)x22,2f(x)x2x3,,2f(x)x2xn2f(x)x3x1,2f(x)x3x2,2f(x)x33,,2f(x)x3xn,2f(x)xnx1,2f(x)xnx2,2f(x)xnx3,,2f(x)xn2] H_f \overset{def}{=} \begin{bmatrix} \frac{\partial^2 f(x) }{ \partial x_1^2} &, \frac{\partial^2 f(x) }{\partial x_1 x_2}, & \frac{\partial^2 f (x) }{\partial x_1 x_3}, &\ldots, &\frac{\partial^2 f(x) }{ \partial x_1 x_n} \\ \frac{\partial^2 f(x) }{ \partial x_2 x_1} &, \frac{\partial^2 f(x) }{\partial x_2^2}, & \frac{\partial^2 f (x) }{\partial x_2 x_3}, &\ldots, &\frac{\partial^2 f(x) }{ \partial x_2 x_n} \\ \frac{\partial^2 f(x) }{ \partial x_3 x_1} &, \frac{\partial^2 f(x) }{\partial x_3 x_2},& \frac{\partial^2 f (x) }{\partial x_3^3}, &\ldots, &\frac{\partial^2 f(x) }{ \partial x_3 x_n} \\ \vdots, & \vdots& \vdots & \ddots & \vdots \\ \frac{\partial^2 f(x) }{ \partial x_n x_1} &, \frac{\partial^2 f(x) }{\partial x_n x_2},& \frac{\partial^2 f (x) }{\partial x_n x_3}, &\ldots, &\frac{\partial^2 f(x) }{ \partial x_n^2} \end{bmatrix}

Note que el Hessiano, se puede ver como aplicar calcular el Jacobiano al Gradiente:
Hf=J{f}=J{Jf} H_f = J \{ \nabla f\} = J\{ J_f^\top\}

Sobre la Notación:

J{}J\{ \cdot \} se refiere al operador

JfJ_f se refiere a la Matrix

H = G.jacobian(sbl)
H

[200040006]\left[\begin{matrix}2 & 0 & 0\\0 & 4 & 0\\0 & 0 & 6\end{matrix}\right]

det(H)

4848

Ecuaciones diferenciales

x = Symbol("x")
f = Function("f")
eq = Eq(f(x).diff(x), f(x))
eq

ddxf(x)=f(x)\frac{d}{d x} f{\left (x \right )} = f{\left (x \right )}

latex(eq)
'\\frac{d}{d x} f{\\left (x \\right )} = f{\\left (x \\right )}'
dsolve(eq, f(x))

f(x)=C1exf{\left (x \right )} = C_{1} e^{x}

eq = Eq(x**2*f(x).diff(x), -3*x*f(x) + sin(x)/x)
eq

x2ddxf(x)=3xf(x)+1xsin(x)x^{2} \frac{d}{d x} f{\left (x \right )} = - 3 x f{\left (x \right )} + \frac{1}{x} \sin{\left (x \right )}

dsolve(eq, f(x))

f(x)=1x3(C1cos(x))f{\left (x \right )} = \frac{1}{x^{3}} \left(C_{1} - \cos{\left (x \right )}\right)