## 10. Resolver Ecuaciones

[Playlist de Ciencia de Datos en castellano](https://www.youtube.com/playlist?list=PLjyvn6Y1kpbEmRY4-ELeRA80ZywV7Xd67)
[](https://www.youtube.com/watch?v=c40z75JnT44&list=PLLBUgWXdTBDg1Qgmwt4jKtVn9BWh5-zgy "Python Data Science")

Las ecuaciones son fundamentales en Ciencia de Datos. Permiten convertir datos en información procesable mediante el desarrollo de expresiones matemáticas que describen sistemas físicos. Algunas expresiones matemáticas son simples y pueden calcularse secuencialmente, por ejemplo:

$x=1 \quad y=x^2+2x-4$

La solución es $x=1$, $y=1+2-4=-1$. 

Considera el caso donde $x$ también depende de $y$.

$x=y \quad y=x^2+2x-4$

Hay dos soluciones que se calculan a partir de la fórmula cuadrática $y=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$

$0=y^2+(2y-y)-4$, 

$\quad y^2+y-4 = 0$,    con $a=1$, $b=1$ y $c=-4$.

$y = \frac{-1 \pm \sqrt{17}}{2} = {1.56,-2.56}$

Hay dos métodos para resolver este problema. El primero es una **solución numérica**, donde la computadora usa métodos de prueba y error para hallar la solución. Se utilizan métodos numéricos cuando hay un gran número de ecuaciones y no hay solución analítica. El segundo método es una **solución simbólica** que genera una solución exacta.



### Solución Numérica

Los problemas complejos y a gran escala utilizan una solución numérica, por ejemplo con `fsolve` o `gekko`. Se requiere una función que devuelva el error residual de la ecuación. Este residual es $f(y)=y^2+y-4$, que no es igual a cero cuando el valor de $y$ no es la solución correcta. Un valor inicial de `1` o `-2` da un resultado diferente porque se empieza cerca de uno u otro.   

#### Solución con Scipy fsolve


```python
from scipy.optimize import fsolve
def f(y):
    return y**2+y-4
z = fsolve(f,1); print(z)
z = fsolve(f,-2); print(z)
```



**Solución con Python Gekko**


```python
from gekko import GEKKO
m = GEKKO(remote=False)
#Declaración de la variable y. y=1
y = m.Var(1)
#Declaración de la ecuación
m.Equation(y**2+y-4==0)
#Resolución
m.solve(disp=False)
print(y.value)
#Valor inicial y=-2
y.value = -2
m.solve(disp=False); print(y.value)
```



### Resolver 2 Ecuaciones

Es similar tener una o dos ecuaciones

$y=x^2+2x-4$

$x=y$

La función devuelve el error residual de cada ecuación como una lista. 

Se requieren dos valores iniciales. 

Este mismo método también se aplica para más ecuaciones. Los algoritmos que resuelven ecuaciones (solvers) pueden solucionar problemas con miles o millones de variables!!

**Solución con Scipy `fsolve`**


```python
from scipy.optimize import fsolve
def f(z):
    x,y = z
    return [x-y,y-x**2-2*x+4]
z = fsolve(f,[1,1]); print(z)
z = fsolve(f,[-2,-2]); print(z)
```



**Solución con Python Gekko**


```python
m = GEKKO(remote=False)
x=m.Var(); y = m.Var(1);
m.Equations([y==x**2+2*x-4, x==y])
m.solve(disp=False)
print(x.value, y.value)

x.value=-2; y.value=-2
m.solve(disp=False)
print(x.value, y.value)
```



### Resolver 3 Ecuaciones

$x^2+y^2+z^2=1$

$x-2y+3z=0.5$

$x+y+z=0$

Resuelve el problema con 3 variables y 3 ecuaciones.

**Solución con Scipy `fsolve`**


```python

```



**Solución con Python Gekko**


```python

```



### Solución Simbólica

Es posible expresar simbólicamente la solución analítica de problemas simples. Una librería con símbolos matemáticos en Python es `sympy`. La función `display` está disponible para imprimir la ecuación en Jupyter notebook. Se requiere importar `from IPython.display import display`.     



```python
from IPython.display import display
import sympy as sym
x = sym.Symbol('x')
y = sym.Symbol('y')
ans = sym.nonlinsolve([x-y, y-x**2-2*x+4], [x,y])
display(ans)
```



### Resolver Simbólicamente 3 Ecuaciones

$x\,y\,z=0$

$x\,y=0$

$x+5\,y+z$

Resuelve el problema con 3 variables y 3 ecuaciones de forma simbólica. El problema está subespecificado, por lo que una de las variables aparecerá en la solución; es decir, hay un set infinito de soluciones.  


```python

```



### Ecuaciones Lineales

Puedes resolver ecuaciones lineales en Python. Existen métodos eficientes como `x = np.linalg.solve(A,b)` para resolver ecuaciones de tipo $A x = b$ con la matriz $A$ y los vectores $x$ y $b$.

$A = \begin{bmatrix}3 & 2\\ 1 & 2 \end{bmatrix} \quad b = \begin{bmatrix}1 \\ 0 \end{bmatrix}$


```python
import numpy as np
A = np.array([[3,2],[1,2]])
b = np.array([1,0])

x = np.linalg.solve(A,b)
print(x)
```

La solución simbólica para este set de ecuaciones lineales está disponible con la función `sympy` `linsolve`. Si el problema es lineal, se prefiere usar `linsolve` porque es más eficiente que `nonlinsolve`, pero puede resolver los dos.


```python
import sympy as sym
x, y = sym.symbols('x y')
ans = sym.linsolve([3*x + 2*y - 1, x + 2*y], (x, y))
sym.pprint(ans)
```



### Optimización

Cuando hay más variables que ecuaciones, el problema está subespecificado y no puede hallarse solución con una función como `fsolve` (para problemas lineales y no lineales) o `linalg.solve` (solo para problemas lineales). Se requiere información adicional para guiar la selección de las variables extra.

Una función objetivo $J(x)$ es una manera de especificar el problema para que exista solución única. El objetivo es minimizar  $x_1 x_4 \left(x_1 + x_2 + x_3\right) + x_3$. Las dos ecuaciones que guían la selección de dos variables son las restricciones de desigualdad $\left(x_1 x_2 x_3 x_4 \ge 25\right)$ y de igualdad $\left(x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40\right)$. Las cuatro variables deben estar entre `1` (límite inferior) y `5` (límite superior).


$\quad \min x_1 x_4 \left(x_1 + x_2 + x_3\right) + x_3$

$\quad \mathrm{s.t.:} \quad x_1 x_2 x_3 x_4 \ge 25$

$\quad x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40$

$\quad 1\le x_1, x_2, x_3, x_4 \le 5$

con valores iniciales:

$\quad x_0 = (1,5,5,1)$

Información adicional sobre optimización encontrarás en el [Curso de Diseño y Optimización en inglés](https://apmonitor.com/me575) y en el [Libro de Diseño y Optimización en inglés](https://apmonitor.com/me575/index.php/Main/BookChapters).

Referencia:
Optimization Methods for Engineering Design, Parkinson, A.R., Balling, R., and J.D. Hedengren, Second Edition, Brigham Young University, 2018.

El primer método de resolución es con `scipy.optimize.minimize`. Las funciones en esta librería trabajan bien con problemas de tamaño moderado y modelos de caja negra, donde una función objetivo está disponible a través de la llamada a una función (function call).


```python
import numpy as np
from scipy.optimize import minimize

def objective(x):
    return x[0]*x[3]*(x[0]+x[1]+x[2])+x[2]

def constraint1(x):
    return x[0]*x[1]*x[2]*x[3]-25.0

def constraint2(x):
    sum_eq = 40.0
    for i in range(4):
        sum_eq = sum_eq - x[i]**2
    return sum_eq

# condiciones iniciales
n = 4
x0 = np.zeros(n)
x0[0] = 1.0
x0[1] = 5.0
x0[2] = 5.0
x0[3] = 1.0

# optimización
b = (1.0,5.0)
bnds = (b, b, b, b)
con1 = {'type': 'ineq', 'fun': constraint1} 
con2 = {'type': 'eq', 'fun': constraint2}
cons = ([con1,con2])
solution = minimize(objective,x0,method='SLSQP',\
                    bounds=bnds,constraints=cons)
x = solution.x

# mostrar objetivo final
print('Final Objective: ' + str(objective(x)))

# imprimir solución
print('Solution')
print('x1 = ' + str(x[0]))
print('x2 = ' + str(x[1]))
print('x3 = ' + str(x[2]))
print('x4 = ' + str(x[3]))
```



### Optimización con Gekko

[Python Gekko](https://gekko.readthedocs.io/en/latest/) también resuelve problemas de optimización. Usa diferenciación automática y algoritmos (solvers) basados en gradientes como `APOPT` o `IPOPT` para hallar una solución. Este método de solución es mejor para problemas a gran escala. [Tutoriales Adicionales sobre Gekko en inglés](https://apmonitor.com/wiki/index.php/Main/GekkoPythonOptimization) muestran cómo resolver otro tipo de problemas de optimización.


```python
from gekko import GEKKO
m = GEKKO(remote=False)

# Inicializar Variables
x1,x2,x3,x4 = [m.Var(lb=1, ub=5) for i in range(4)]

# Condiciones Iniciales
x1.value = 1
x2.value = 5
x3.value = 5
x4.value = 1

# Ecuaciones
m.Equation(x1*x2*x3*x4>=25)
m.Equation(x1**2+x2**2+x3**2+x4**2==40)

# Objetivo
m.Obj(x1*x4*(x1+x2+x3)+x3)

# Resolver
m.solve(disp=False)

# Objectivo Final
print('Final Objective: ' + str(m.options.objfcnval))

# Imprimir soluciones
print('Solution')
print('x1: ' + str(x1.value))
print('x2: ' + str(x2.value))
print('x3: ' + str(x3.value))
print('x4: ' + str(x4.value))
```

### Actividad con el TCLab



### Recolección de Datos



Enciende el calentador 1 al 100% y graba $T_1$ cada 10 segundos por 3 minutos. Los datos deben incluir un total de 19 puntos para cada sensor de temperatura y el tiempo, iniciando en cero. Toma nota de los puntos de temperatura en 0, 90 y 180 segundos.


```python

```



### Ecuaciones Lineales

Se requieren tres puntos para especificar un polinomio de grado 2 de la forma $y =a_0 + a_1 \; x + a_2 \; x^2$. Crea una regresión cuadrática para $T_2$ usando solo el primer, medio y último punto. Supón que los puntos para $T_2$ son los siguientes:     

| Tiempo (sec) | Temperatura (°C)  |
|------|------|
| 0    | 23.0 |
| 90    | 33.0 |
| 180    | 43.0 |

Resuelve la regresión lineal como un set de tres ecuaciones que se derivan conectando los tres puntos a la ecuación polinómica. Crea tres ecuaciones que consideren $y=T_2$ y $x=tiempo$.

$\quad a_0 + a_1 \; 0 + a_2 \; 0^2 = 23.0$

$\quad a_0 + a_1 \; 90 + a_2 \; 90^2 = 33.0$

$\quad a_0 + a_1 \; 180 + a_2 \; 180^2 = 43.0$

En forma de matriz, el set de ecuaciones lineales es:  

$\quad \begin{bmatrix}1 & 0 & 0 \\ 1 & 90 & 90^2 \\ 1 & 180 & 180^2 \end{bmatrix}\begin{bmatrix}a_0\\a_1\\a_2\end{bmatrix} = \begin{bmatrix}23.0\\33.0\\43.0\end{bmatrix}$

Resuelve el set de ecuaciones para hallar los parámetros cuadráticos $a_0$, $a_1$ y $a_2$ con los datos recolectados al inicio de la actividad con el TCLab. Dibuja el ajuste cuadrático con los datos para asegurar que la curva pasa por los tres puntos indicados.


```python

```



### Ecuaciones No Lineales

Ajusta los datos de $T_1$ a una correlación no lineal usando solo tres puntos.

$\quad T_1 = a + b \exp{(c \, tiempo)}$

Se requieren únicamente tres puntos para especificar un modelo con tres parámetros. Cuando hay más del mínimo número de puntos requerido, usualmente se ejecuta una regresión de mínimos cuadrados para minimizar el cuadrado del error entre los valores medidos y predecidos. Para este ejercicio, usa solo tres puntos (primero, medio y último) de los datos $T_1$. Supón que los puntos para $T_1$ son los siguientes: 


| Tiempo (sec) | Temperatura (°C)  |
|------|------|
| 0    | 22.0 |
| 90    | 42.0 |
| 180    | 52.0 |

Resuelve para hallar los tres parámetros a partir de las tres ecuaciones que intersecan a los datos requeridos.   

$\quad 22.0 = a + b \exp{(c \, 0)}$

$\quad 42.0 = a + b \exp{(c \, 90.3)}$

$\quad 52.0 = a + b \exp{(c \, 180.5)}$

Resuelve este set de ecuaciones para los parámetros desconocidos $a$, $b$ y $c$ con los datos recolectados al inicio de esta actividad. Utiliza como valores iniciales $a=100$, $b=-100$ y $c=-0.01$. Grafica el ajuste no lineal con los datos para asegurar que este pasa por los tres puntos especificados. Añade las etiquetas necesarias en el gráfico.


```python

```

5fc573b427b66045e5044f8b3250b8fe41c6505f
ipynb
Jupyter Notebook
10. Resolver_ecuaciones.ipynb
APMonitor/ciencia_de_datos
4e989992a71bc59040799772af14784a83b94153
MIT
2021-08-21T15:32:07.000Z
2021-12-05T15:56:38.000Z
10. Resolver_ecuaciones.ipynb
APMonitor/ciencia_de_datos
4e989992a71bc59040799772af14784a83b94153
MIT
10. Resolver_ecuaciones.ipynb
APMonitor/ciencia_de_datos
4e989992a71bc59040799772af14784a83b94153
MIT
2021-05-27T06:08:57.000Z
2021-12-19T20:57:15.000Z
Qwen/Qwen-72B
1. YES
2. YES