

# Clase 5: 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


```python
from IPython.display import HTML
HTML('')
```








## SymPy Gamma


```python
HTML('')
```








## Creación de símbolos

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


```python
# Importación
from sympy import init_session
```


```python
init_session(use_latex=True)
```

    IPython console for SymPy 0.7.5 (Python 3.4.2-64-bit) (ground types: python)
    
    These commands were executed:
    >>> from __future__ import division
    >>> from sympy import *
    >>> x, y, z, t = symbols('x y z t')
    >>> k, m, n = symbols('k m n', integer=True)
    >>> f, g, h = symbols('f g h', cls=Function)
    
    Documentation can be found at http://www.sympy.org


    WARNING: Hook shutdown_hook is deprecated. Use the atexit module instead.


Lo primero que vemos es que el comando `init_session` ha llevado a cabo algunas acciones por nostros:

* 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
# Número pi
(a + pi) ** 2
```


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


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


```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
type(b)
```




    sympy.core.mul.Mul



¿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
a = 2.26492
a
```


```python
type(a)
```




    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
coef_traccion = symbols('c_T')
coef_traccion
```

Incluso puedo hacer cosas raras como:


```python
# Diferencia entre variable y símbolo
a = symbols('b')
a
```

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


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

y símbolos griegos:


```python
w = symbols('omega')
W = symbols('Omega')
w, W
```


_Fuente: Documentación oficial de SymPy_

__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', real=True)
```


```python
# Podemos ver las asunciones de un símbolo
x.assumptions0
```




    {'complex': True,
     'real': True,
     'hermitian': True,
     'imaginary': False,
     'commutative': True}



## Expresiones

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


```python
expr = cos(x)**2 + sin(x)**2
expr
```

### `simplify()`

Podemos pedirle que simplifique la expresión anterior:


```python
simplify(expr)
```

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
expr
```


```python
# Sustituimos x por y ** 2
expr.subs(x, y**2)
```


```python
# ¡Pero la expresión no cambia!
expr
```


```python
# Para que cambie
expr = expr.subs(x, y**2)
expr
```

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


```python
expr.subs(sin(x), exp(x))
```

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
(sin(x) + 3 * x).subs(x, pi).evalf(25)
```


```python
#ver pi con 25 decimales
pi.evalf(25)
```


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

# 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
#1
expr1 = (x ** 3 + 3 * y + 2) ** 2
expr1
```


```python
expr1_exp = expr1.expand()
expr1_exp
```


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


```python
expr2.apart()
```


```python
#3
expr3 = x ** 3 + 9 * x ** 2 + 27 * x + 27
expr3
```


```python
expr3.factor()
```


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


```python
expand(expr4)
```


```python
expand_trig(expr4)
```


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

# Derivadas e integrales

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


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

#obtenemos la derivada primera con funcion
diff(expr, x)
```


```python
#utilizando método
expr.diff(x)
```

__¿derivada tercera?__


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


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

__¿varias variables?__


```python
expr_xy = y ** 3 * sin(x) ** 2 + x ** 2 * cos(y)
expr_xy
```


```python
diff(expr_xy, x, 2, y, 2)
```

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


```python
Derivative(expr_xy, x, 2, 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 = 2 * y * exp(x)
f
```


```python
# definimos una g(f)
g = f **2 * cos(x) + f
g
```


```python
#la derivamos
diff(g,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
int1 = cos(x) ** 2
integrate(int1)
```


```python
int2 =  1 / sin(x)
integrate(int2)
```


```python
x, a = symbols('x a', real=True)

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

# 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
x = symbols('x', real=True)
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)
```

# 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 = exp(x)
expr
```


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

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
series(expr, n=10)
```

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


```python
series(expr, n=10).removeO()
```


```python
series(sin(x), n=8, x0=pi/3).removeO().subs(x, x-pi/3)
```

---

## Resolución de ecuaciones

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


```python
#creamos la ecuación
ecuacion = Eq(x ** 2 - x, 3)
ecuacion
```


```python
# También la podemos crear como
Eq(x ** 2 - x -3)
```


```python
#la resolvemos
solve(ecuacion)
```

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


```python
# Creamos los símbolos y la ecuación
a, x, t, C = symbols('a, x, t, C', real=True)
ecuacion = Eq(a * exp(x/t), C)
ecuacion
```


```python
# La resolvemos
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
x = symbols('x')
f = Function('y')
ecuacion_dif = Eq(y(x).diff(x,2) + y(x).diff(x) + y(x), cos(x))
ecuacion_dif
```


```python
#resolvemos
dsolve(ecuacion_dif, f(x))
```

# Matrices


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


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


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


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

---

_ Esto ha sido un rápido recorrido por algunas de las posibilidades que ofrece SymPy . El cálculo simbólico es un terreno díficil y este joven paquete avanza a pasos agigantados gracias a un grupo de desarrolladores siempre dispuestos a mejorar y escuchar sugerencias. Sus posibilidades no acaban aquí. En la siguiente clase presentaremos el paquete `mechanics`, pero además cuenta con herramientas para geometría, mecánica cuántica, teoría de números, combinatoria... Puedes echar un ojo [aquí](http://docs.sympy.org/latest/modules/index.html). _

---

Clase en vídeo, parte del [Curso de Python para científicos e ingenieros](http://cacheme.org/curso-online-python-cientifico-ingenieros/) grabado en la Escuela Politécnica Superior de la Universidad de Alicante.


```python
from IPython.display import YouTubeVideo

YouTubeVideo("OGQRcYVys1Q", width=560, height=315, list="PLGBbVX_WvN7as_DnOGcpkSsUyXB1G_wqb")
```










---

Si te ha gustado esta clase:

<a href="https://twitter.com/share" class="twitter-share-button" data-url="https://github.com/AeroPython/Curso-AeroPython-UC3M/" data-text="Aprendiendo Python con" data-via="AeroPython" data-size="large" data-hashtags="AeroPython">Tweet</a>


---

#### <h4 align="right">¡Síguenos en Twitter!

###### <a href="https://twitter.com/AeroPython" class="twitter-follow-button" data-show-count="false">Follow @AeroPython</a>   

##### <a rel="license" href="http://creativecommons.org/licenses/by/4.0/deed.es"></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Curso AeroPython</span> por <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Juan Luis Cano Rodriguez y Alejandro Sáez Mollejo</span> se distribuye bajo una <a rel="license" href="http://creativecommons.org/licenses/by/4.0/deed.es">Licencia Creative Commons Atribución 4.0 Internacional</a>.

#####    

---
_Las siguientes celdas contienen configuración del Notebook_

_Para visualizar y utlizar los enlaces a Twitter el notebook debe ejecutarse como [seguro](http://ipython.org/ipython-doc/dev/notebook/security.html)_

    File > Trusted Notebook


```python
%%html
<a href="https://twitter.com/AeroPython" class="twitter-follow-button" data-show-count="false">Follow @AeroPython</a>

```


<a href="https://twitter.com/AeroPython" class="twitter-follow-button" data-show-count="false">Follow @AeroPython</a>




```python
# Esta celda da el estilo al notebook
from IPython.core.display import HTML
css_file = '../static/styles/style.css'
HTML(open(css_file, "r").read())
```




<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro|Josefin+Sans:400,700,400italic|Ubuntu+Condensed' rel='stylesheet' type='text/css'>

El estilo se ha aplicado =)

<style>



#notebook_panel { /* main background */
    background: #f7f7f7;
}

div.cell { /* set cell width */
    width: 900px;
}

div #notebook { /* centre the content */
    background: #fff; /* white background for content */
    width: 950px;
    margin: auto;
    padding-left: 0em;
}

#notebook li { /* More space between bullet points */
    margin-top:0.7em;
}

/* draw border around running cells */
div.cell.border-box-sizing.code_cell.running { 
    border: 1px solid #111;
}

/* Put a solid color box around each cell and its output, visually linking them*/
div.cell.code_cell {
    font-family: 'Source Sans Pro', sans-serif;
    background-color: rgb(256,256,256);
    font-size: 110%;
    border-radius: 0px; 
    padding: 0.5em;
    margin-left:1em;
    margin-top: 1em;
}

div.text_cell_render{
    font-family: 'Josefin Sans', serif;
    line-height: 145%;
    font-size: 125%;
    font-weight: 500;
    width:750px;
    margin-left:auto;
    margin-right:auto;
}


/* Formatting for header cells */
.text_cell_render h1, .text_cell_render h2, .text_cell_render h3,
.text_cell_render h4, .text_cell_render h5 {
    font-family: 'Ubuntu Condensed', sans-serif;
}
/*
.text_cell_render h1 {
    font-family: Flux, 'Ubuntu Condensed', serif;
    font-style:regular;
    font-weight: 400;    
    font-size: 30pt;
    text-align: center;
    line-height: 100%;
    color: #335082;
    margin-bottom: 0.5em;
    margin-top: 0.5em;
    display: block;
}
*/
.text_cell_render h1 {
    font-weight: 600;
    font-size: 35pt;
    line-height: 100%;
    color: #234765;
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    display: block;
}

.text_cell_render h2 {
    margin-top:16px;
    font-size: 27pt;
    font-weight: 550;
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    font-style: regular;
    color: #234765;
}	

.text_cell_render h3 {
    font-size: 20pt;
    font-weight: 550
    text-align: left;
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    font-style: regular;
    color:  #376f9e;
}

.text_cell_render h4 {    /*Use this for captions*/
    font-size: 18pt;
    font-weight: 450
    text-align: left;
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    font-style: regular;
    color:  #376f9e;
}

.text_cell_render h5 {  /*Use this for small titles*/
    font-size: 18pt;
    font-weight: 550;
    color: rgb(163,0,0);
    font-style: italic;
    margin-bottom: .1em;
    margin-top: 0.8em;
    display: block;
    color:  #b21c0d;
}

.text_cell_render h6 { /*use this for copyright note*/
    font-family: 'Ubuntu Condensed', sans-serif;
    font-weight: 300;
    font-size: 14pt;
    line-height: 100%;
    color: #252525;
    text-align: right;
    margin-bottom: 1px;
    margin-top: 1px;
}

.CodeMirror{
        font-family: 'Duru Sans', sans-serif;
        font-size: 100%;
}

</style>





a98f2380c96082d5d921437057cd4477ade30be1
ipynb
Jupyter Notebook
notebooks_completos/Clase5_SymPy.ipynb
karimkprr/Curso-AeroPython-UC3M
50009edc50e9e626e33bd2c4fbb240647f201167
CC-BY-4.0
2015-10-05T20:21:20.000Z
2021-02-15T03:12:53.000Z
notebooks_completos/Clase5_SymPy.ipynb
karimkprr/Curso-AeroPython-UC3M
50009edc50e9e626e33bd2c4fbb240647f201167
CC-BY-4.0
2015-10-04T17:22:10.000Z
2015-10-08T07:46:05.000Z
notebooks_completos/Clase5_SymPy.ipynb
karimkprr/Curso-AeroPython-UC3M
50009edc50e9e626e33bd2c4fbb240647f201167
CC-BY-4.0
2016-06-16T06:00:05.000Z
2021-10-31T01:44:40.000Z
Qwen/Qwen-72B
1. YES
2. YES