<table width="100%" border="0">
  <tr>    
  <td></td>
  <td></td>
  <td></td>
  </tr>
</table>

<br>

<h1 style="text-align: center;"> Curso de Python para Ingenieros Mecánicos </h1> 
<h3 style="text-align: center;"> Por: Eduardo Vieira</h3>
<br>
<br>
<h1 style="text-align: center;">  Sympy - Sistema de algebra simbólica </h1> 
<br>

__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. _

Puede hacer cosas como:

* 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...


```python
import sympy as sym
%matplotlib inline
```

Para que los resultados sean formateados en $\LaTeX$ podemos usar:


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

## Variables simbólicas

En SymPy podemos crear símbolos para las variables con las que deseamos trabajar. Podemos crear un nuevo símbolo usando la clase `Symbol`:


```python
x = sym.Symbol('x')
```


```python
(sym.pi + x)**2
```


```python
# forma alternativa de definir (varios) símbolos
a, b, c = sym.symbols("a, b, c")
```


```python
type(a)
```




    sympy.core.symbol.Symbol



Podemos agregar algunas propiedades a los símbolos cuando son creados:


```python
x = sym.Symbol('x', real=True)
```


```python
x.is_imaginary
```




    False




```python
x = sym.Symbol('x', positive=True)
```


```python
x > 0
```

### Números complejos

La unidad imaginaria es denotada por `I` en Sympy. 


```python
1+1*sym.I
```


```python
sym.I**2
```


```python
(x * sym.I + 1)**2
```

### Números racionales

Existen tres tipos distintos de números en SymPy: `Real`, `Rational`, `Integer`: 


```python
r1 = sym.Rational(4,5)
r2 = sym.Rational(5,4)
```


```python
r1
```


```python
r1+r2
```


```python
r1/r2
```

### Evaluación numérica

SymPy usa una librería para trabajar con números con precisión arbitraria, y tiene expresiones SymPy  predefinidas para varias constantes matemáticas, tales como: `pi`, `e` y `oo` para el infinito.

Para evaluar numéricamente una expresión podemos usar la función `evalf` (o bien `N`). Ésta usa un argumento `n` que especifíca el número de cifras significativas.


```python
sym.pi.evalf(n=50)
```


```python
y = (x + sym.pi)**2
```


```python
sym.N(y, 5) # equivalente a evalf
```

Cuando evaluamos numéricamente expresiones a menudo deseamos substituir un símbolo por un valor numérico. En SymPy hacemos esto usando la función `subs`:


```python
y.subs(x, 1.5)
```


```python
sym.N(y.subs(x, 1.5))
```

La función `subs` también puede ser usada para substituir símbolos y expresiones:


```python
y.subs(x, a+sym.pi)
```

También podemos combinar la evaluación numérica de expresiones con arreglos NumPy:


```python
import numpy as np
```


```python
x_vec = np.arange(0, 10, 0.1)
```


```python
y_vec = np.array([sym.N(((x + sym.pi)**2).subs(x, xx)) for xx in x_vec])
```


```python
import matplotlib.pyplot as plt
plt.plot(x_vec, y_vec);
```

Sin embargo, este tipo de evaluación numérica puede ser muy lenta, y existe una forma mucho más eficiente de realizar la misma tarea: Usar la función `lambdify` para "mapear" una expresión de Sympy a una función que es mucho más eficiente para la evaluación numérica:


```python
f = sym.lambdify([x], (x + sym.pi)**2, 'numpy')  # el primer argumento es una lista de variables de las que la función f dependerá: en este caso sólo x -> f(x)
```


```python
type(f)
```




    function




```python
y_vec = f(x_vec)  # ahora podemos pasar directamente un arreglo Numpy. Así f(x) es evaluado más eficientemente
```

La mayor eficiencia de usar funciones "lambdificadas" en lugar de usar evalación numérica directa puede ser significativa, a menudo de varios órdenes de magnitud. Aún en este sencillo ejemplo obtenemos un aumento de velocidad importante:


```python
%%timeit

y_vec = np.array([sym.N(((x + sym.pi)**2).subs(x, xx)) for xx in x_vec])
```

    32.5 ms ± 1.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)



```python
%%timeit

y_vec = f(x_vec)
```

    7.26 µs ± 30.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)


## Manipulaciones algebráicas

Uno de los usos principales de un sistema de cálculo simbólico es que realiza manipulaciones algebráicas de expresiones. Por ejemplo, si queremos expandir un producto, factorizar una expresión, o simplificar un resultado. En esta sección presentamos las funciones para realizar estas operaciones básicas en SymPy.

### Expand and factor

Primeros pasos en la manipulación algebráica


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


```python
sym.expand((x+1)*(x+2)*(x+3))
```

La función `expand` acepta varias argumentos clave con los que se puede indicar qué tipo de expansión deseamos realizar. Por ejemplo, para expandir expresiones trigonométricas, usamos el argumento clave `trig=True`:


```python
sym.sin(a+b)
```


```python
sym.expand(sym.sin(a+b), trig=True)
```

Ver `help(expand)` para una descripción detallada de los distintos tipos de expansiones que la función `expand` puede realizar.

También podemos factorizar expresiones, usando la función `factor` de SymPy: 


```python
sym.factor(x**3 + 6 * x**2 + 11*x + 6)
```

### Simplify

La función `simplify` intenta simplificar una expresión usando distinta técnicas. Existen también alternativas más específicas a la función `simplify`: `trigsimp`, `powsimp`, `logcombine`, etc. 

El uso básico de estas funciones en el siguiente:


```python
# simplify expande un producto
sym.simplify((x+1)*(x+2)*(x+3))
```


```python
# simplify usa identidades trigonometricas
sym.simplify(sym.sin(a)**2 + sym.cos(a)**2)
```


```python
sym.simplify(sym.cos(x)/sym.sin(x))
```

## apart and together

Podemos también manipular expresiones simbólicas que involucran fracciones usando las funciones `apart` y `together`. La primera de estas funciones separa una fracción en sus correspondientes fracciones parciales; la segunda hace todo lo contrario.


```python
f1 = 1/((a+1)*(a+2))
```


```python
f1
```


```python
sym.apart(f1)
```


```python
f2 = 1/(a+2) + 1/(a+3)
```


```python
f2
```


```python
sym.together(f2)
```

Podemos usar también `Simplify`:


```python
sym.simplify(f2)
```

## Cálculo

Además de realizar manipulaciones algebráicas, SimPy puede realizar operaciones de cálculo, tales como derivar y derivar expresiones.

### Derivación

Derviar es usualmente algo simple. Usamos la función `diff`. El primer argumento es una expresión que será derivada, y el segundo argumento es el símbolo respecto al cual se realizará la derivada:


```python
y
```


```python
sym.diff(y**2, x)
```

Para calcular derivadas de orden superior podemos usar:


```python
sym.diff(y**2, x, x)
```

o bien


```python
sym.diff(y**2, x, 2) # hace lo mismo
```

Calculando la derivada de una función de varias variables:


```python
x, y, z = sym.symbols("x,y,z")
```


```python
f = sym.sin(x*y) + sym.cos(y*z)
```

$\frac{d^3f}{dxdy^2}$


```python
sym.diff(f, x, 1, y, 2)
```

### Integracion

La integración se realiza de la misma forma:


```python
f
```


```python
sym.integrate(f, x)
```

Si le damos los límites de integración calculamos la integral definida


```python
sym.integrate(f, (x, -1, 1))
```

Tambien podemos calcular integrales impropias


```python
from sympy import oo
# oo es el infinito
```


```python
sym.integrate(sym.exp(-x**2), (x, -oo, oo))
```

### Sumatoria y productos

Podemos evaluar sumatorias usando: 'Sum'


```python
n = sym.Symbol("n")
```


```python
sym.Sum(1/n**2, (n, 1, 10))
```


```python
sym.Sum(1/n**2, (n,1, 10)).evalf()
```


```python
sym.Sum(1/n**2, (n, 1, oo)).evalf()
```

Lo mismo con productos


```python
sym.Product(n, (n, 1, 10)) # 10!
```

### Límites

Los límites se evalúan con la función `limit`


```python
sym.limit(sym.sin(x)/x, x, 0)
```

Se puede usar el límite para verificar una derivada


```python
f
```


```python
sym.diff(f, x)
```

La derivada por definicion es 
$$\frac{d}{{dx}}f\left( x \right) = \mathop {\lim }\limits_{h \to 0} \frac{{f\left( {x + h } \right) - f\left( x \right)}}{h }$$


```python
h = sym.Symbol("h")
```


```python
sym.limit((f.subs(x, x+h) - f)/h, h, 0)
```

OK!

Podemos calcular los limites laterales usando el argumento `dir`:


```python
sym.limit(1/x, x, 0, dir="+")
```


```python
sym.limit(1/x, x, 0, dir="-")
```

### Series

Las series tambien son una de las funciones mas útiles de un CAS. En SymPy se puede calcular la serie de una funcion usando `series`


```python
sym.series(sym.exp(x), x)
```

Por defecto, se calcula la expansión alrededor de $x=0$ (serie de Taylor), pero podemos expandir la serie al rededor de otro punto


```python
sym.series(sym.exp(x), x, 1)
```

Tambien podemos especificar el orden


```python
sym.series(sym.exp(x), x, 1, 10)
```

La expansion en serie incluye la aproximación de orden. Lo cual es útil para trabajar con series de diferente orden


```python
s1 = sym.cos(x).series(x, 0, 5)
s1
```


```python
s2 = sym.sin(x).series(x, 0, 2)
s2
```


```python
sym.expand(s1 * s2)
```

Si queremos eliminar la aproximación de orden usamos el método `removeO`


```python
sym.expand(s1.removeO() * s2.removeO())
```

Pero hay que tener en cuenta que esta no es la expansión correcta de $\cos(x)\sin(x)$ al $5$to orden:


```python
(sym.cos(x)*sym.sin(x)).series(x, 0, 6)
```

## Álgebra Lineal

### Matrices

Las matrices se definen usando la clase `Matrix`:


```python
m11, m12, m21, m22 = sym.symbols("m11, m12, m21, m22")
b1, b2 = sym.symbols("b1, b2")
```


```python
A = sym.Matrix([[m11, m12],[m21, m22]])
A
```


```python
b = sym.Matrix([[b1], [b2]])
b
```

Con la clase `Matrix` podemos realizar las operaciones matriciales típicas


```python
A**2
```


```python
A * b
```

Y tambien determinantes e inversas:


```python
A.det()
```


```python
A.inv()
```

## resolviendo ecuaciones

Para resolver ecuaciones podemos utilizar la función `solve`


```python
sym.solve(x**2 - 1, x)
```


```python
sym.solve(x**4 - x**2 - 1, x)
```

Sistemas de ecuaciones


```python
sym.solve([x + y - 1, x - y - 1], [x,y])
```

La ecuacion puede estar en términos de otras variables simbólicas


```python
sym.solve([x + y - a, x - y - c], [x,y])
```

## Lecturas complementarias

* http://sympy.org/en/index.html - The SymPy projects web page.
* https://github.com/sympy/sympy - The source code of SymPy.
* http://live.sympy.org - Online version of SymPy for testing and demonstrations.



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




/* This template is inspired in the one used by Lorena Barba
in the numerical-mooc repository: https://github.com/numerical-mooc/numerical-mooc
We thank her work and hope you also enjoy the look of the notobooks with this style */

<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: #000000;
    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: #2c6391;
}	

.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:  #387eb8;
}

.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:  #5797cc;
}

.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>






```python

```

8245b0ee573d74035d1923fd234745ae12ac6220
ipynb
Jupyter Notebook
5-sympy.ipynb
eduardojvieira/Curso-Python-MEC-UCV
3211a7a7ee655dee2709e7fdc04f6a57aac6d92e
MIT
2020-12-05T11:40:53.000Z
2020-12-05T11:40:53.000Z
5-sympy.ipynb
eduardojvieira/Curso-Python-MEC-UCV
3211a7a7ee655dee2709e7fdc04f6a57aac6d92e
MIT
5-sympy.ipynb
eduardojvieira/Curso-Python-MEC-UCV
3211a7a7ee655dee2709e7fdc04f6a57aac6d92e
MIT
Qwen/Qwen-72B
1. YES
2. YES