<a href="https://colab.research.google.com/github/lsantiago/PythonIntermedio/blob/master/Clases/Semana7_SYMPY/Clase7_SymPy_vacia.ipynb" target="_parent"></a>

# CLASE 7: SymPy



_ __SymPy es una biblioteca de Python para matemática simbólica__. Apunta a convertirse en un sistema de algebra computacional (__CAS__) con todas sus prestaciones manteniendo el código tan simple como sea posible para manterlo comprensible y fácilmente extensible. SymPy está __escrito totalmente en Python y no requiere bibliotecas adicionales__. _Este proyecto comenzó en 2005, fue lanzado al público en 2007 y a él han contribuido durante estos años cientos de personas._

_ Otros CAS conocidos son Mathematica y Maple, sin embargo ambos son software privativo y de pago. [Aquí](https://github.com/sympy/sympy/wiki/SymPy-vs.-Maple) puedes encontrar una comparativa de SymPy con Maple. _

Hoy veremos cómo:

* Crear símbolos y expresiones.
* Manipular expresiones (simplificación, expansión...)
* Calcular derivadas e integrales.
* Límites y desarrollos en serie.
* Resolución de ecuaciones.
* Resolción de EDOs.
* Matrices

Sin embargo, SymPy no acaba aquí ni mucho menos...

## Documentación & SymPy Live Shell

[Documentacion](http://docs.sympy.org/latest/index.html)


[SympyGamma](http://www.sympygamma.com/input/?i=integrate%281+%2F+%281+%2B+x^2%29%29)

## Creación de símbolos

Lo primero, como siempre, es importar aquello que vayamos a necesitar:


```python
!pip install sympy
```


```python
#import sympy as sp
from sympy import *
```


```python
init_printing(use_latex=True)
```



* Gracias a `use_latex=True` obtenemos la salida en $\LaTeX$.
* __Ha creado una serie de variables__ para que podamos ponernos a trabajar en el momento.

<div class="alert warning-info"><strong>Nota:</strong> 
En Python, no se declaran las variables, sin embargo, no puedes usar una hasta que no le hayas asignado un valor. Si ahora intentamos crear una variable `a` que sea `a = 2 * b`, veamos qué ocurre:
</div>


```python
# Intentamos usar un símbolo que no hemos creado
a = 2 * b
```

Como en `b` no había sido creada, Python no sabe qué es `b`.

Esto mismo nos ocurre con los símbolos de SymPy. __Antes de usar una variable, debo decir que es un símbolo y asignárselo:__


```python
# Creamos el símbolo a
a = symbols("a")
a
```


```python

```


```python
# Número pi
(a + pi)**2
```


```python
# Unidad imaginaria
1 + 2*I
```


```python
# Número e
E ** 2
```


```python
# Vemos qué tipo de variable es a
type(a)
```




    sympy.core.symbol.Symbol



Ahora ya podría crear `b = 2 * a`:


```python
b = 2 * a
b
```


```python

```

¿Qué está ocurriendo? Python detecta que a es una variable de tipo `Symbol` y al multiplicarla por `2` devuelve una variable de Sympy.

Como Python permite que el tipo de una variable cambie, __si ahora le asigno a `a` un valor float deja de ser un símbolo.__


```python
b = 2.0
```


```python
type(b)
```




    float



---
__Las conclusiones son:__

* __Si quiero usar una variable como símbolo debo crearla previamente.__
* Las operaciones con símbolos devuelven símbolos.
* Si una varibale que almacenaba un símbolo recibe otra asignación, cambia de tipo.

---

__Las variables de tipo `Symbol` actúan como contenedores en los que no sabemos qué hay (un real, un complejo, una lista...)__. Hay que tener en cuenta que: __una cosa es el nombre de la variable y otra el símbolo con el que se representa__.


```python
#creación de símbolos
alpha, beta = symbols("alpha beta")
alpha, beta
```


```python
c_T = symbols("c_T")
c_T
```

Incluso puedo hacer cosas raras como:


```python
# Diferencia entre variable y símbolo
b = symbols("d")
b
```

Además, se pueden crear varos símbolos a la vez:


```python
x, y, z, t = symbols("x, y, z, t")
x, y, z, t
```

y símbolos griegos:


```python

```

__Por defecto, SymPy entiende que los símbolos son números complejos__. Esto puede producir resultados inesperados ante determinadas operaciones como, por ejemplo, lo logaritmos. __Podemos indicar que la variable es real, entera... en el momento de la creación__:


```python
# Creamos símbolos reales
x, y, z, t = symbols("x, y, z, t")
```


```python
# restricciones sobre el simbolo
x.assumptions0
```




    {'commutative': True}




```python
# Podemos ver las asunciones de un símbolo
x = symbols("x", real=True, positive=True)
```


```python
x.assumptions0

```




    {'real': True,
     'commutative': True,
     'imaginary': False,
     'finite': True,
     'hermitian': True,
     'complex': True,
     'extended_real': True,
     'infinite': False,
     'positive': True,
     'nonpositive': False,
     'negative': False,
     'extended_positive': True,
     'extended_nonnegative': True,
     'nonnegative': True,
     'extended_negative': False,
     'extended_nonpositive': False,
     'extended_nonzero': True,
     'nonzero': True,
     'zero': False}



## Expresiones

Comencemos por crear una expresión como: $\cos(x)^2+\sin(x)^2$


```python
cos(z) ** 2 + sin(z) ** 2
```

### `simplify()`

Podemos pedirle que simplifique la expresión anterior:


```python
simplify(_25)
```


```python
sqrt(z**2)
```


```python
simplify(_27)
```


```python
y = symbols("y", real=True)
```


```python
simplify(sqrt(y**2))
```


```python
simplify(sqrt(x**2))
```

En este caso parece estar claro lo que quiere decir más simple, pero como en cualquier _CAS_ el comando `simplify` puede no devolvernos la expresión que nosotros queremos. Cuando esto ocurra necesitaremos usar otras instrucciones.

### `.subs()`

En algunas ocasiones necesitaremos sustituir una variable por otra, por otra expresión o por un valor.


```python
_25.subs(z, 1+x**2)
```


```python
(sin(x)**2 + cos(y)**2).subs({x: 1+ z, y: 1-z})
```


```python

```


```python


```

Cambia el `sin(x)` por `exp(x)`


```python
sin(x).replace(sin, exp)
```

Particulariza la expresión $sin(x) + 3 x $ en $x = \pi$


```python
(sin(x)+3*x).subs(x, pi)
```

__Aunque si lo que queremos es obtener el valor numérico lo mejor es `.evalf()`__


```python
_36.evalf()
```


```python
_36.evalf(n=27)
```


```python
#ver pi con 25 decimales

```


```python
#el mismo resultado se obtiene ocn la función N()
N(_36)
```

# Simplificación

SymPy ofrece numerosas funciones para __simplificar y manipular expresiones__. Entre otras, destacan:

* `expand()`
* `factor()`
* `collect()`
* `apart()`
* `cancel()`

Puedes consultar en la documentación de SymPy lo que hace cada una y algunos ejemplos. __Existen también funciones específicas de simplificación para funciones trigonométricas, potencias y logaritmos.__ Abre [esta documentación](http://docs.sympy.org/latest/tutorial/simplification.html) si lo necesitas.

##### ¡Te toca!

Pasaremos rápidamente por esta parte, para hacer cosas "más interesantes". Te proponemos algunos ejemplos para que te familiarices con el manejor de expresiones:

__Crea las expresiones de la izquierda y averigua qué función te hace obtener la de la derecha:__

expresión 1| expresión 2
:------:|:------:
$\left(x^{3} + 3 y + 2\right)^{2}$    |    $x^{6} + 6 x^{3} y + 4 x^{3} + 9 y^{2} + 12 y + 4$
$\frac{\left(3 x^{2} - 2 x + 1\right)}{\left(x - 1\right)^{2}} $ | $3 + \frac{4}{x - 1} + \frac{2}{\left(x - 1\right)^{2}}$
$x^{3} + 9 x^{2} + 27 x + 27$         |    $\left(x + 3\right)^{3}$
$\sin(x+2y)$                          |    $\left(2 \cos^{2}{\left (y \right )} - 1\right) \sin{\left (x \right )} + 2 \sin{\left (y \right )} \cos{\left (x \right )} \cos{\left (y \right )}$



```python
x, y = symbols("x y")
```


```python
#1
(x**3 + 3*y+2)**2
```


```python
expand(_43)
```


```python

```


```python
#2
(3*x**2-2*x+1)/(x-1)**2
```


```python
apart(_46)
```


```python

```


```python
#3

```


```python
(x**3 + 9*x**2 + 27*x + 27).factor()
```


```python

```


```python
#4
sin(x+2*y)
```


```python
expand(_, trig=True)
```


```python
expand_trig(_50)
```


```python

```


```python

```

# Derivadas e integrales

Puedes derivar una expresion usando el método `.diff()` y la función `diff()`


```python
#creamos una expresión
expresion = cos(x)

#obtenemos la derivada primera con funcion
expresion.diff(x)
```


```python
#utilizando método
diff(expresion)
```

__¿derivada tercera?__


```python
expresion.diff(x, x, x)
```


```python
expresion.diff(x, 3)
```

__¿varias variables?__


```python
expr = y * exp(2*x) + x / (x**2 + y**3)
expr
```


```python
expr.diff(x, 2, y, 3)
```

__Queremos que la deje indicada__, usamos `Derivative()`


```python
Derivative(expr, y)
```

__¿Será capaz SymPy de aplicar la regla de la cadena?__


```python
# Creamos una función F
F = Function("F")
F(x)
```


```python
# Creamos una función G
G = Function("G")
G(x)
```

$$\frac{d}{d x} F{\left (G(x) \right )} $$


```python
# Derivamos la función compuesta F(G(x))
F(G(x)).diff(x)
```

En un caso en el que conocemos las funciones:


```python
# definimos una f
f = 3 * x + cos(y)
```


```python
# definimos una g(f)
g = 1 / f
g
```


```python
#la derivamos
g.diff(x)
```

##### Te toca integrar

__Si te digo que se integra usando el método `.integrate()` o la función `integrate()`__. ¿Te atreves a integrar estas casi inmediatas...?:

$$\int{\cos(x)^2}dx$$
$$\int{\frac{dx}{\sin(x)}}$$
$$\int{\frac{dx}{(x^2+a^2)^2}}$$




```python
#integrate?
```


```python
cos(x)**2
```


```python
integrate(cos(x)**2)
```


```python
integrate(cos(x)**2, (x, 0, 1))
```


```python
(1/sin(x)).integrate()
```


```python
integrate(1/(x**2+a**2)**2, x)
```


```python


```

# Límites

Calculemos este límite sacado del libro _Cálculo: definiciones, teoremas y resultados_, de Juan de Burgos:

$$\lim_{x \to 0} \left(\frac{x}{\tan{\left (x \right )}}\right)^{\frac{1}{x^{2}}}$$

Primero creamos la expresión:


```python
expr = (x/tan(x))**(1/x**2)
expr
```

Obtenemos el límite con la función `limit()` y si queremos dejarlo indicado, podemos usar `Limit()`:


```python
limit(expr, x, 0)
```


```python
oo
```


```python
limit(expr, x, oo)
```


```python
# para dejar indicado
Limit(expr, x, 0)
```

# Series

Los desarrollos en serie se pueden llevar a cabo con el método `.series()` o la función `series()`


```python
#creamos la expresión
expr = cos(x)
```


```python
#la desarrollamos en serie
expr.series(x)
```

Se puede especificar el número de términos pasándole un argumento `n=...`. El número que le pasemos será el primer término que desprecie.


```python
# Indicando el número de términos
expr.series(x, n=10)
```

Si nos molesta el $\mathcal{O}(x^{10})$ lo podemos quitar con `removeO()`:


```python
_.removeO()
```


```python
expr.series(x, n=10, x0=pi/2)
```

---

## Resolución de ecuaciones

Como se ha mencionado anteriormente las ecuaciones no se pueden crear con el `=`


```python
#creamos la ecuación
a + x = cos(x)
```


```python
Eq(1+x, x**2)

```


```python
Eq(1+x - x**2, 0)
```


```python
# También la podemos crear como
ecuacion = Eq(1+x-sin(x), 0)
ecuacion
```


```python
ecuacion2 = Eq(x**2+1, 0)
```


```python
#la resolvemos
sol = solve(ecuacion2, x)
sol
```


```python

```

Pero la gracia es resolver con símbolos, ¿no?
$$a e^{\frac{x}{t}} = C$$


```python
# Creamos los símbolos y la ecuación
C = symbols("C")
C
```


```python
# La resolvemos
ecuacion = Eq(a*exp(x/t), C)
ecuacion
```


```python
solve(ecuacion, x)
```

Si consultamos la ayuda, vemos que las posibilidades y el número de parámetros son muchos, no vamos a entrar ahora en ellos, pero ¿se ve la potencia?

## Ecuaciones diferenciales



Tratemos de resolver, por ejemplo:

$$y{\left (x \right )} + \frac{d}{d x} y{\left (x \right )} + \frac{d^{2}}{d x^{2}}  y{\left (x \right )} = \cos{\left (x \right )}$$


```python
# solo sirve para ejemplos acádemicos sencillos 

y = Function('y')
y
```




    y




```python
edo = Eq(y(x) + y(x).diff(x) + y(x).diff(x, 2), cos(x))
edo
```


```python
#resolvemos
dsolve(edo,y(x))
```

# Matrices


```python
#creamos una matriz llena de símbolos
a, b, c, d = symbols('a, b, c, d')
a, b, c, d

A = Matrix([
            [a, b],
            [c, d]
])
A
```


```python
#sacamos autovalores
A.eigenvals()

```


```python
A.eigenvects()
```


```python
#inversa
A.inv()
```


```python
#elevamos al cuadrado la matriz
A ** 2
```

1b884c6c123dcbf1d87a12cf637c24e5f44d25b9
ipynb
Jupyter Notebook
Clases/Semana7_SYMPY/Clase7_SymPy_vacia.ipynb
iaastudillo/PythonIntermedio
2b1393761445e7ee521d82c1dbb33826a9dd475e
MIT
Clases/Semana7_SYMPY/Clase7_SymPy_vacia.ipynb
iaastudillo/PythonIntermedio
2b1393761445e7ee521d82c1dbb33826a9dd475e
MIT
Clases/Semana7_SYMPY/Clase7_SymPy_vacia.ipynb
iaastudillo/PythonIntermedio
2b1393761445e7ee521d82c1dbb33826a9dd475e
MIT
2021-02-02T03:33:44.000Z
2021-02-02T03:34:20.000Z
Qwen/Qwen-72B
1. YES
2. YES