# Sympy


## Introducción

Hay dos sistemas de álgebra computarizada (CAS) notables para Python:

* [SymPy](http://sympy.org/en/index.html): un módulo de Python que se puede utilizar en cualquier programa de Python, o en una sesión de IPython, que proporciona potentes funciones de CAS.
* [Sage](http://www.sagemath.org/) - Sage es un entorno CAS muy potente y con todas las funciones que tiene como objetivo proporcionar un sistema de código abierto que compita con Mathematica y Maple. Sage no es un módulo Python normal, sino un entorno CAS que utiliza Python como lenguaje de programación.

`Sage` es en algunos aspectos más poderoso que `SymPy`, pero ambos ofrecen una funcionalidad CAS muy completa. La ventaja de SymPy es que es un módulo Python normal y se integra bien con el portátil IPython.

Para comenzar a usar SymPy en un programa o cuaderno de Python, importe el módulo `sympy`:


```python
from sympy import *
```

Para obtener una salida con formato $\LaTeX $ atractiva, ejecute:


```python
init_printing()

# or with older versions of sympy/ipython, load the IPython extension
#%load_ext sympy.interactive.ipythonprinting
# or
#%load_ext sympyprinting
```

## Variables simbólicas

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


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


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


```python
# alternative way of defining symbols
a, b, c = symbols("a, b, c")
```


```python
type(a)
```




    sympy.core.symbol.Symbol



Podemos agregar suposiciones a los símbolos cuando los creamos:


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


```python
x.is_imaginary
```




    False




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


```python
x > 0
```

### Números complejos

La unidad imaginaria se denota "I" en `Sympy`.


```python
1+1*I
```


```python
I**2
```


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

### Numeros racionales

Hay tres tipos numéricos diferentes en SymPy: `Real`,` Rational`, ʻInteger`:


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


```python
r1
```


```python
r1+r2
```


```python
r1/r2
```

## Evaluación numérica

`SymPy` usa una biblioteca para precisión artística como backend numérico, y tiene expresiones `SymPy` predefinidas para una serie de constantes matemáticas, como: `pi`, ʻe`, ʻoo` para infinito.

Para evaluar una expresión numéricamente podemos usar la función `evalf` (o `N`). Toma un argumento "n" que especifica el número de dígitos significativos.


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


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


```python
N(y, 5) # same as evalf
```

Cuando evaluamos numéricamente expresiones algebraicas, a menudo queremos sustituir un símbolo por un valor numérico. En `SymPy` lo hacemos usando la función `subs`:


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


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

Por supuesto, la función `subs` también se puede utilizar para sustituir símbolos y expresiones:


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

También podemos combinar la evolución numérica de expresiones con matrices `Numpy`:


```python
import numpy
import matplotlib.pyplot as plt

```


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


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


```python
fig, ax = plt.subplots()
ax.plot(x_vec, y_vec);
```

Sin embargo, este tipo de evolución numérica puede ser muy lenta, y hay una manera mucho más eficiente de hacerlo: use la función `lambdify` para" compilar "una expresión Sympy en una función que sea mucho más eficiente para evaluar numéricamente:


```python
f = lambdify([x], (x + pi)**2, 'numpy')  # the first argument is a list of variables that
                                         # f will be a function of: in this case only x -> f(x)
```


```python
y_vec = f(x_vec)  # now we can directly pass a numpy array and f(x) is efficiently evaluated
```

La aceleración cuando se utilizan funciones `lambdify`  en lugar de una evaluación numérica directa puede ser significativa, a menudo de varios órdenes de magnitud. Incluso en este ejemplo simple obtenemos una velocidad significativa:


```python
%%timeit

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

    16.9 ms ± 473 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)



```python
%%timeit

y_vec = f(x_vec)
```

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


## Manipulaciones algebraicas

Uno de los usos principales de un CAS es realizar manipulaciones algebraicas de expresiones. Por ejemplo, podríamos querer expandir un producto, factorizar una expresión o simplemente una expresión. Las funciones para realizar estas operaciones básicas en SymPy se muestran en esta sección.

### Expandir y factorizar

Los primeros pasos en una manipulación algebraica


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


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

La función `expand` toma un número de argumentos de palabras clave que podemos decirle a las funciones qué tipo de expansiones queremos que se realicen. Por ejemplo, para expandir expresiones trigonométricas, use el argumento de palabra clave `trig = True`:


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


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

Consulte `help (expand)` para obtener una explicación detallada de los distintos tipos de expansiones que pueden realizar las funciones de ʻexpand`.

Lo contrario, una expansión de producto es, por supuesto, factorización. El factor de una expresión en SymPy usa la función `factor`:


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

### Simplificar

El "simplificar" intenta simplificar una expresión en una expresión agradable, utilizando varias técnicas. También existen alternativas más específicas a las funciones `simplify`:` trigsimp`, `powsimp`,` logcombine`, etc.

Los usos básicos de estas funciones son los siguientes:


```python
# simplify expands a product
simplify((x+1)*(x+2)*(x+3))
```


```python
# simplify uses trigonometric identities
simplify(sin(a)**2 + cos(a)**2)
```


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

### Separados y juntos

Para manipular expresiones simbólicas de fracciones, podemos usar las funciones `apart` y `together`:

**apart**


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


```python
f1
```


```python
apart(f1)
```

**together**


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


```python
f2
```


```python
together(f2)
```

Simplificar generalmente combina fracciones pero no factoriza:


```python
simplify(f2)
```

## Cálculo

Además de las manipulaciones algebraicas, el otro uso principal de CAS es hacer cálculo, como derivadas e integrales de expresiones algebraicas.

### Diferenciación

La diferenciación suele ser sencilla. Utilice la función `diff`. El primer argumento es la expresión para tomar la derivada y el segundo argumento es el símbolo por el cual tomar la derivada:


```python
y
```


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

Para derivados de orden superior podemos hacer:


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


```python
diff(y**2, x, 2) # same as above
```

Para calcular la derivada de una expresión multivariante, podemos hacer:


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


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

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


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

### Integración

La integración se realiza de manera similar:


```python
f
```


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

Al proporcionar límites para la variable de integración, podemos evaluar integrales definidas:


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

y también integrales impropias:


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

Recuerde, `oo` es la notación SymPy para infinito.

### Sumas y productos

Podemos evaluar sumas y productos usando las funciones: 'Suma'


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


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


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


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

Los productos funcionan de la misma manera:


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

### Límites

Los límites se pueden evaluar utilizando la función `limit`. Por ejemplo,


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

Podemos usar `limit` para verificar el resultado de la derivación usando la función `diff`:


```python
f
```


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

$\displaystyle \frac{\mathrm{d}f(x,y)}{\mathrm{d}x} = \frac{f(x+h,y)-f(x,y)}{h}$


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


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

Podemos cambiar la dirección desde la que nos acercamos al punto límite usando el argumento `dir`:


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


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

### Serie

La expansión de la serie también es una de las características más útiles de un CAS. En SymPy podemos realizar una expansión en serie de una expresión usando la función `series`:


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

De forma predeterminada, expande la expresión alrededor de $x = 0$, pero podemos expandir alrededor de cualquier valor de $x$ al incluir explícitamente un valor en la llamada a la función:


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

Y podemos definir explícitamente en qué orden se debe realizar la expansión de la serie:


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

La expansión de la serie incluye el orden de la aproximación, lo cual es muy útil para realizar un seguimiento del orden de validez cuando hacemos cálculos con expansiones de la serie de diferente orden:


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


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


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

Si queremos deshacernos de la información del error, podemos usar el método `removeO`:


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

Pero tenga en cuenta que esta no es la expansión correcta de $ \cos(x) \sin(x)$ a $ 5 $ ésimo orden:


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

## Álgebra lineal

### Matrices

Las matrices se definen usando la clase `Matrix`:


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


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


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

Con las instancias de la clase `Matrix` podemos hacer las operaciones habituales de álgebra matricial:


```python
A**2
```


```python
A * b
```

Y calcular determinantes e inversas, y similares:


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


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

## Resolver ecuaciones

Para resolver ecuaciones y sistemas de ecuaciones podemos usar la función `resolver`:


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


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

Sistema de ecuaciones:


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

En cuanto a otras expresiones simbólicas:


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

## Referencias

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

0d1218a613d112294727b0b0170318c189483270
ipynb
Jupyter Notebook
lectures/data_manipulation/scientific_computing/sympy.ipynb
dannyowen1/mat281_portfolio_dannyowen1
c7dbcfc5f7724d8bef1d48d2381f9c065a6d6f20
MIT
lectures/data_manipulation/scientific_computing/sympy.ipynb
dannyowen1/mat281_portfolio_dannyowen1
c7dbcfc5f7724d8bef1d48d2381f9c065a6d6f20
MIT
lectures/data_manipulation/scientific_computing/sympy.ipynb
dannyowen1/mat281_portfolio_dannyowen1
c7dbcfc5f7724d8bef1d48d2381f9c065a6d6f20
MIT
Qwen/Qwen-72B
1. YES
2. YES