<font size = 1 color="gray">Introducción a la computación numérica y simbólica con Python</font>  



# 7. Computación simbólica

El lenguaje de las matemáticas no es numérico, sino simbólico. Los humanos somos capaces de manejar información abstracta que nos permite realizar transformaciones del siguiente tipo:

$f(x) = x^2-x-2 = (x+1)(x-2)$

${d^2 sen(3x)\over dx^2} = -9\ cos(3x)$

Existen programas como $\it{Maple}$ o $\it{Mathematica}$ que trabajan con símbolos. Son muy potentes pero tienen un precio de licencia elevado. Existe una alternativa open source basada en Python, el paquete `SymPy`.

`SymPy` puede ejecutarse online en la URL https://live.sympy.org

NOTA: En estos notebooks usamos LaTeX para construir las fórmulas en la parte descriptiva.

## Definición de símbolos

Cuando trabajamos con Python o cualquier otro lenguaje común de programación, estamos acostumbrados a usar variables
con las que operamos.


```python
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
```


```python
a = 7
b = 8
print("El resultado de la operación a + b es ",a+b)
```

    El resultado de la operación a + b es  15


Con `SymPy` podemos emplear símbolos.


```python
x = sp.symbols('x')
y = sp.symbols('y')
print('El resultado de la operación x + y en SympPy es',x+y)
```

    El resultado de la operación x + y en SympPy es x + y


Se han definido dos símbolos $x$,$y$ y el resultado es un nuevo símbolo $x+y$, no un valor numérico. Con SymPy se pueden realizar operaciones simbólicas de mayor complejidad.


```python
factor1 = x+1
factor2 = x-2
pfact = factor1*factor2
print("El producto de los factores (",factor1,")(",factor2, ") es",pfact)
```

    El producto de los factores ( x + 1 )( x - 2 ) es (x - 2)*(x + 1)


Aparentemente no ha ocurrido nada, salvo que la expresión aparece con la sintaxis propia de Python. Podemos hacer que el polinomio aparezca desarrollado.


```python
print("El producto de los factores (",factor1,")(",factor2, ") es",sp.expand(pfact))
```

    El producto de los factores ( x + 1 )( x - 2 ) es x**2 - x - 2


La función `sympyfy` convierte un texto en objetos SymPy siempre que la sintaxis sea correcta. Para que funcione correctamente los símbolos tienen que haberse definido.


```python
frac = sp.symbols('frac')
frac = sp.sympify('x**2/y')
print(frac)
```

    x**2/y


## Tipos

Aparte de los símbolos, `SymPy` puede manejar tipos de datos que no son los habituales en Python pero sí en el razonamiento matemático humano. Por ejemplo, podemos usar fracciones.


```python
# Fracciones
var1 = sp.sympify('1/6')
print("var1 =",var1)
var2 = sp.sympify('(5/8)')*var1
print("var2 =",var2)
print("Tipo de var2",type(var2))
print("Valor de var2 en punto flotante con 10 decimales de precisión",var2.evalf(10))

```

    var1 = 1/6
    var2 = 5/48
    Tipo de var2 <class 'sympy.core.numbers.Rational'>
    Valor de var2 en punto flotante con 10 decimales de precisión 0.1041666667
    var3 sqrt(2)
    Tipo de var3 <class 'sympy.core.power.Pow'>
    var2*var3 = 5*sqrt(2)/48
    Tipo de var2*var3  <class 'sympy.core.mul.Mul'> valor en punto flotante = 0.1473139127


También podemos usar potencias.


```python
# Potencias
var3= sp.sqrt(2)
print("var3 =",var3)
print("Tipo de var3",type(var3))
print("var2*var3 =",sp.Mul(var2,var3))
print("Tipo de var2*var3 ",type(var2*var3),"valor en punto flotante =",(var2*var3).evalf(10))

```

    var3 = sqrt(2)
    Tipo de var3 <class 'sympy.core.power.Pow'>
    var2*var3 = 5*sqrt(2)/48
    Tipo de var2*var3  <class 'sympy.core.mul.Mul'> valor en punto flotante = 0.1473139127


## Evaluación

Con frecuencia, necesitamos evaluar una expresión simbólica para determinado valor. Si queremos conocer el valor de $f(x) = x^3 -x -2*cos(\pi x)$ en el punto $x=0.3$, tenemos que usar el método `subs` para cambiar la incógnita por el valor y el método `evalf` para evaluar la expresión.


```python
x,f = sp.symbols('x f')
f = x**3 - x - 2*sp.cos(sp.pi * x)
print("La función es f(x)=",f)
print("Su valor para x = 3 es f(0.3) :",(f.subs(x,0.3)).evalf(8))      # El parámetro de evalf indica el número de cifras decimales
```

    La función es f(x)= x**3 - x - 2*cos(pi*x)
    Su valor para x = 3 es f(0.3) : -1.4485705


Cuando usamos `SymPy` tenemos que tener mucho cuidado con las comparaciones. El operador `==` compara si dos expresiones son iguales.


```python
x,y,z = sp.symbols('x y z')
y = sp.sin(x)
z = sp.sin(x)
# los símbolos y,z son estructuralmente idénticos
print(y,'==',z,y == z)
```

    sin(x) == sin(x) True


Sin embargo `SymPy` no es capaz de detectar por defecto que $cos(2x) == cos^2(x)-sin^2(x)$ con el operador `==`, para eso hay que usar el método `equals`



```python
a,b = sp.symbols('a b')
a = sp.cos(x)**2 - sp.sin(x)**2
b = sp.cos(2*x)
print(b,'==',a,b==a)

# Pero sí es capaz de hacerlo con el método equals
print(b,"equals",a,a.equals(b))

```

    cos(2*x) == -sin(x)**2 + cos(x)**2 False
    cos(2*x) equals -sin(x)**2 + cos(x)**2 True


Podemos dibujar la gráfica de la función usando este mismo procedimiento.

## SymPy para gráficas

Podemos usar el método `evalf` para calcular punto a punto el valor de una expresión que queremos representar gráficamente.


```python
f = x**3 - x - 2*sp.cos(sp.pi * x)
print("La función es f(x)=",f)
# Vector de valores x
xpuntos = np.linspace(0,2,100)
ypuntos = []
for i in xpuntos:
    ypuntos.append((f.subs(x,i)).evalf(8)) # Evaluación de f(x) en cada punto
plt.figure(figsize=(8,5)) # tamaño de la gráfica en pulgadas
plt.plot(xpuntos,ypuntos)
plt.title('$x^3-x-2cos(\pi x)$')
plt.xlabel('$x$') # título del eje horizontal
plt.ylabel('$y$') # título del eje  vertical
plt.show()
```

Hay una manera más eficiente de evaluar en múltiples puntos, la función `lambdify`.


```python
expresionmat = sp.symbols('expresionmat')
a = np.linspace(0,2*np.pi,1000) 
expresionmat = sp.sin(x)**(3)-2*sp.cos(3*x)+sp.log(1+x)*0.1
f = sp.lambdify(x, expresionmat, "numpy")  # Convierte la expresión simbólica a la funciones equivalentes de de NumPy
plt.plot(a,f(a)) 
plt.title(expresionmat)
plt.show()
```

## Presentación

Una de las características más interesantes de `SymPy` es su capacidad de formatear la salida como en un texto matemático convencional.


```python
# La función f del ejemplo anterior está escrita con sintaxis Python que es la que entiende el lenguaje
print(expresionmat)
```

    0.1*log(x + 1) + sin(x)**3 - 2*cos(3*x)



```python
# SymPy permite presentar la misma expresión

sp.init_printing() 
sp.pprint(expresionmat)
expresionmat
```


```python
# Si el equipo tiene instalado LaTeX, la salida será aun más legible

from sympy import init_session
init_session(use_latex=True)
expresionmat

```


```python
x = sp.sqrt(3)
pprint(Mul(x,  x, evaluate=False))
print('es igual a',x*x)
```

    √3⋅√3
    es igual a 3



```python
a11,a12,a21,a22 = symbols('a11 a12 a21 a22')
A = sp.Matrix([
            [a11, a12],
            [a21, a22]
    ])
A
```


```python
b11,b21 = symbols('b11 b21')
B = sp.Matrix([[b11, b21]])
B.T
```


```python
C=A*B.T
C
```

---

<font size="1" color="grey">
    (c) 2020 Javier García Algarra. <a href='https://www.u-tad.com'>www.u-tad.com</a> <br>
Licensed under a Creative Commons Reconocimiento 4.0 Internacional License
</font> 

6e3c111388bbfb2e2bc86a089a0a7f473c0641bb
ipynb
Jupyter Notebook
notebooks/.ipynb_checkpoints/07_sympy_introduccion-checkpoint.ipynb
jgalgarra/PythonMatematicas
8f3a294f134a949403919d38eb15e7144237cdfb
MIT
2022-03-09T12:22:31.000Z
2022-03-09T12:22:31.000Z
notebooks/.ipynb_checkpoints/07_sympy_introduccion-checkpoint.ipynb
jgalgarra/PythonMatematicas
8f3a294f134a949403919d38eb15e7144237cdfb
MIT
notebooks/.ipynb_checkpoints/07_sympy_introduccion-checkpoint.ipynb
jgalgarra/PythonMatematicas
8f3a294f134a949403919d38eb15e7144237cdfb
MIT
2020-10-29T09:18:34.000Z
2020-10-29T09:18:34.000Z
Qwen/Qwen-72B
1. YES
2. YES