```python
!start .
```

#  Examen

Lea cuidadosamente las siguientes indicaciones antes de comenzar el examen:

- Para resolver el examen edite este mismo archivo y renómbrelo de la siguiente manera: *Examen1_ApellidoNombre*, donde *ApellidoNombre* corresponde a su apellido paterno con la inicial en mayúscula, seguido de su primer nombre con la inicial en mayúscula **sin acentos**. Por ejemplo, en mi caso el nombre del archivo sería Examen1_LopezMichel.
- Resuelva los puntos en el espacio provisto. Si requiere agregar más celdas para código o escritura, hágalo.
- Recuerde que también se está evaluando su capacidad de interpretar los resultados. Escriba sus interpretaciones/conclusiones en celdas utilizando *Markdown*.
- No se resuelven dudas de ningún tipo por los profesores de la asignatura. Por favor, absténgase de preguntar.

 - El formato de presentación de todo el examen en general debe ser adecuado. Use tamaños de letra, colores, etiquetas, etcétera.

# Primer punto.

## Introducción al problema.

### Ley de Newton del enfriamiento

La ley empírica de Newton, relativa al enfriamiento de un objeto, se expresa con la ecuación diferencial lineal de primer orden

$$\frac{dT}{dt} = k(T - Tm) $$

donde $k$ es una constante de proporcionalidad, $T(t)$ es la temperatura del objeto cuando $t > 0$
y $T_m$ es la temperatura ambiente; o sea, la temperatura del medio que rodea al objeto.

Supondremos que $T_m$ es constante.

```python
%matplotlib inline

import sympy as sym
import numpy as np
import matplotlib.pylab as plt

from sympy import init_printing; init_printing(use_latex='mathjax')
from IPython.display import display
from IPython.display import HTML
from scipy.integrate import odeint

from sympy import *
from scipy.optimize import linprog

from ipywidgets import *

Ley_Newton_enfriamiento=''
Torricelli=''
Caidalibre =''

sym.var('k t x')

T = sym.Function('T')
```

```python
%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import sympy
from scipy import integrate
from scipy.optimize import minimize
from sympy.utilities import lambdify
from scipy.integrate import odeint
```

### Para más información revise la siguiente pagina.

```python
HTML(Ley_Newton_enfriamiento)
```

    HTML(value='<iframe src=https://es.wikipedia.org/wiki/Ley_del_enfriamiento_de_Newton?useformat=mobile width=70…

##  Problema 1

### ¿Cuánto esperar para tomar el café?

Primero calentamos el agua a $80°C$. Posteriormente agregamos café al vaso con el agua caliente. Después realizamos la medición de la temperatura ambiente, la cual fue de $24°C$. Realiza las siguientes actividades:
]
1. (20 puntos) Simula el sistema en un tiempo de $0$ a $120$ unidades de tiempo  con una constante de proporcionalidad $k=-0.0565$,
2. (15 puntos)
    - (10 puntos) Grafique la solución.
    - (5 puntos) Supoga que cada unidad de tiempo corresponde a un minuto. ¿En que tiempo aproximadamente la temperatura es menor a $30°C$?
3. (15 puntos)
    - (10 puntos) ¿Qué interpretación puedes decir para valores de $k >0$?
    - (5  puntos) Busca una constante de proporcionalidad $k$ en un rango ( de $-0.2$ a $0.2$ con incremento de 0.01), para la cual el cafe tiene una temperatura menor de $30°C$ en un tiempo a 20 minutos.

```python

k=-0.0565
Tm=24

# defino las incognitas
t = sympy.Symbol('t')
T = sympy.Function('T')
# Condición inicial
Ci = {T(0): 80}
# expreso la ecuacion
f = k*(T(t)-Tm)
# Resolviendo ecuación diferencial
sol  = sympy.dsolve(T(t).diff(t) - f,ics=Ci)

```

```python
sol
```

$\displaystyle T{\left(t \right)} = 24.0 + 56.0 e^{- 0.0565 t}$

```python
#convertimos la ecuacion en una funcion
func = lambdify(t, sol.rhs,'numpy')
tvals = np.arange(0,120,1)
Tvals = func(tvals)
```

##  RESPUESTA A INCISO 1 y 2

```python
#graficamos la funcion
plt.plot(tvals,Tvals)
plt.show()
for Tmp in Tvals:
    if(Tmp<=30):
        print("Apartir del minuto", np.where(Tvals==Tmp)[0][0],"la temperatura es menor a 30 °C")
        break
```

##  RESPUESTA A INCISO 3.1

3.1 Si el valor de k es mayor a 0 entonces la tempertura incrementa con el tiempo ya que del signo de este parámetro depende el signo de la exponencial de la funcion de temperatura. Ademas cuando el valor de k determina la rapidez de enfriamiento. Si k tiene a -infinito, la temperatura llega a cero instantaneamente.

##   respuesta inciso 3.2

```python

#T=30°c t=20min
for k in list(np.arange(-0.2,0.2,0.01)):
    f=24.0+(56.0*np.exp(k*20))
    if(f>=30):
        print("k=",value)
        break
    value=k

```

    k= -0.11999999999999994

##  Problema 2

### ¿Cuánto esperar para comenzar a comer pastel?

Al sacar un pastel del horno, su temperatura es $280°C$. Después de $3$ minutos, $2OO°C$. ¿En cuanto tiempo se enfriará hasta la temperatura ambiente de $28°C$? Realiza las siguientes actividades:

1. (20 puntos) Simula el sistema en un tiempo de $0$ a $60$ unidades de tiempo  con una constante de proporcionalidad $k=-0.14518$,
2. (15 puntos)
    - (10 puntos) Grafique la solución.
    - (5 puntos) Supoga que cada unidad de tiempo corresponde a un minuto. ¿En que tiempo aproximadamente la temperatura es menor a $150°C$?
3. (15 puntos)
    - (10 puntos) ¿Qué interpretación puedes decir para valores de $k >0$?
    - (5  puntos) Busca una constante de proporcionalidad $k$ en un rango ( de $-0.2$ a $0.2$ con incremento de 0.01), para la cual el pastel se puede comer a una temperatura menor a $50°C$ en un tiempo a 10 minutos.

```python
k2=-0.14518
Tm2=28

# defino las incognitas
t2 = sympy.Symbol('t')
T2 = sympy.Function('T')
# Condición inicial
Ci2 = {T2(3): 200}
# expreso la ecuacion
f2 = k2*(T2(t2)-Tm2)
# Resolviendo ecuación diferencial
sol2  = sympy.dsolve(T2(t2).diff(t2) - f2,ics=Ci2)
```

```python
sol2
```

$\displaystyle T{\left(t \right)} = 28.0 + 265.877181059486 e^{- 0.14518 t}$

```python
#convertimos la ecuacion en una funcion
func2 = lambdify(t2, sol2.rhs,'numpy')
tvals2 = np.arange(0,60,1)
Tvals2 = func(tvals2)
```

##  RESPUESTA A INCISO 1 y 2

```python
#graficamos la funcion
plt.plot(tvals2,Tvals2)
plt.show()
for Tmp in Tvals2:
    if(Tmp<=150):
        print("Apartir del minuto", np.where(Tvals2==Tmp)[0][0],"la temperatura es menor a 150 °C")
        break
```

## RESPUESTA A INCISO 3.1:

### Si el valor de k es mayor a 0 entonces la tempertura incrementa con el tiempo ya que del signo de este parámetro depende el signo de la exponencial de la funcion de temperatura. Ademas cuando el valor de k determina la rapidez de enfriamiento. Si k tiene a -infinito, la temperatura llega a cero instantaneamente.

##  respuesta inciso 3.2

```python
# respuesta inciso 3.2
#T=50°c t=10min
val=None
for k2 in list(np.arange(-0.2,0.2,0.01)):
    f2=28.0+(265.877181059486*np.exp(k2*10))
    if(f2>50):
        print("k=",val)
        break
    val=k2
if(val==None):
    print("No existe un valor de k entre -0.2 y 0.2 que permita que la temperatura del pastel sea menor a 50 en 10 min")

```

    k= None
    No existe un valor de k entre -0.2 y 0.2 que permita que la temperatura del pastel sea menor a 50 en 10 min

# Segundo punto.

## Introducción al problema.

### Caída libre

En la caída libre ideal, se desprecia la resistencia aerodinámica que presenta el aire al movimiento del cuerpo, analizando lo que pasaría en el vacío. En esas condiciones, la aceleración que adquiriría el cuerpo sería debida exclusivamente a la gravedad, siendo independiente de su masa.

$$
\begin{eqnarray}
\frac{ds}{dt} &=& v \\
\frac{dv}{dt} &=& -g
\end{eqnarray}
$$

O visto el sistema en forma canónica

$$
\begin{eqnarray}
\dot{x}_1 &=& x_2 \\
\dot{x}_2 &=& -g
\end{eqnarray}
$$

### Para más información revise la siguiente pagina.

```python
HTML(Caidalibre)
```

    HTML(value='<…

##  Problema 3

### Deja caer una pelota

Desde un edificio de altura de $314$ metros se deja caer una pelota, que tarda 8 segundos en llegar al piso. ¿con que velocidad impacta la pelota contra el piso?

1. (20 puntos) Simula el sistema en un tiempo de $0$ a $8$ unidades de tiempo  con una constante de gravedad $g=-9.8$,
2. (15 puntos)
    - (10 puntos) Grafique la solución.
    - (5 puntos) Supoga que cada unidad de tiempo corresponde a un segundo. ¿En que tiempo aproximadamente la pelota esta a la mitad del edificio?
3. (15 puntos)
    - (10 puntos) ¿Qué interpretación puedes decir para una posicion inicial de $314 m$ y una velocidad de $30 m/s$ ?
    - (5  puntos) ¿Que altura aproximadamente tendra en $10s$ para el incisio anterior?

```python
g=-9.8
d = np.arange(start=314, stop=-1, step=-1)
t= np.arange(0,9)

vf = g*t
plt.title("Vi=0 m/s")
plt.xlabel("Tiempo")
plt.ylabel("Velocidad")
plt.plot(t,vf)
plt.grid()
plt.show()
print("la pelota impacta contra el piso a una velocidad de: ",vf[8], "m/s")

dd=(vf)*t/2
plt.xlabel("Tiempo")
plt.ylabel("Posición")
plt.grid()
dt=d[0]/2
td=np.sqrt(2*(d[0]/2)/-g)
plt.plot(td,-dt,"bo")
plt.plot(t,dd)
plt.show()

print("La pelota está a la mitad del edificio en el tiempo: ", td , "segundos")

```

```python
g=-9.8
vi=30
d = np.arange(start=314, stop=-1, step=-1)
vf=-np.sqrt(abs(vi**2+2*-g*d[0]))
tf=abs(2*d[0]/(vi+vf))
t= np.arange(0,tf+1)

vf=vi+g*t

plt.title("Vi=30 m/s")
plt.xlabel("Tiempo")
plt.ylabel("Velocidad")
plt.plot(t,vf)
plt.grid()
plt.show()
print("INTERPRETACIÓN: La pelota tarda más tiempo en caer e impacta con una velocidad mayor")

dd=vi*t+(g*t**2)/2
plt.xlabel("Tiempo")
plt.ylabel("Posición")
plt.grid()
plt.plot(t,dd)

t2=10
d2= vi*t2+(g*t2**2)/2
plt.plot(t2,d2,"bo")
plt.show()

print("La pelota ha recorrido", -d2 , "metros en ", t2, "segundos")

```

```python
# Solucion opcion 3
```

# Tercer punto.

## Introducción al problema.

## Drenado de un tanque (Ley de Torricelli)

En hidrodinámica, la ley de Torricelli establece que la velocidad
$v$ de flujo de salida de agua a través de un orificio plano ubicado en la parte inferior
de un tanque lleno hasta una altura $h$ será igual a la velocidad que un cuerpo (en este caso
una gota de agua) adquiriría en caída libre desde una altura $h$; es decir, $v = \sqrt{2gh}$, donde $g$ es la aceleración debida a la gravedad.

Suponga que un tanque lleno de agua puede drenar mediante un orificio bajo la influencia de la gravedad. Deseamos encontrar la altura $h$ del agua restante en el tanque en el tiempo $t$.

Si el área del orificio es $A_h$ (en $m^2$) y la velocidad del agua que sale del tanque es $v = \sqrt{2gh}$ (en m/s), entonces el volumen del agua que abandona el tanque por segundo es $A_h \sqrt{2gh}$ (en $m^3$/s). De este modo, si $V(t)$ indica el volumen del agua que hay en el tanque en el tiempo $t$, la ecuación diferencial deseada para la altura del agua en el tiempo t:

$$\frac{dh}{dt} = - \frac{A_h}{A_w} \sqrt{2gh} $$

Donde $A_w$ (en $m^2$) representa el área constante de la superficie superior del agua.

Observe que aquí ignoramos la posibilidad de fricción en el orificio, la cual puede ocasionar una reducción en la velocidad del flujo en
dicho lugar

### Para más información revise la siguiente pagina.

```python
HTML(Torricelli)
```

    HTML(value='<iframe src=https://en.wikipedia.org/wiki/Torricelli%27s_law?useformat=mobile width=700 height=350…

```python

```

##  Problema 4

### Drenado de un tanque

Concidere un cilindro circular con un área constante de $A_w = 5 m^2$, en la parte inferior contiene un orificio de área $A_h = 1 m^2$ el cual podemos estar regulando la salida del liquido. En el interior del tanque se encuentra un liquido el cual tiene una altura inicial en el tiempo $0$ de $h(0)= 10 m$. Realiza las siguientes actividades:

1. (20 puntos) Simula el sistema en un tiempo de $0$ a $6.5$ unidades de tiempo,
2. (15 puntos)
    - (10 puntos) Grafique la solución.
    - (5 puntos) Supoga que cada unidad de tiempo corresponde a un minuto. ¿En que tiempo aproximadamente la altura del liquido alcanza una altura de $h=2 m$?
3. (15 puntos)
    - (10 puntos) ¿Qué interpretación puedes decir si el signo de la ecuación fuera positivo?
    - (5  puntos)  ¿Si el área del orificio $A_h$ es menor a $1 m^2$ que implicaria? Realiza una simulacion y grafica la solución para un orificio de $A_h = .5 m$

```python
#Unidades
g=9.81#m/s^2
Aw=5#m^2
Ah=1#m^2
h0=10#m
```

```python
t = np.linspace(0,6.5)#valores a evaluar
```

```python
def tank(h,t):#Modelado del tanque
    dhdt=(-(Ah/Aw)*np.sqrt(np.abs(2*g*h)))
    return dhdt
```

##  Solución ejercicio 4.1

```python
h = odeint(tank,h0,t)
```

## Solucion ejercicio 4.2.a

```python
plt.figure(1)
plt.plot(t,h)
plt.xlabel('Time (s)')
plt.ylabel('Height (m)')
plt.grid()
plt.show()
```

## Solucion ejercicio 4.2.b

```python
def findh(n,h,t):
    hmin=1
    for ti,hi in zip(t,h):
      if(hi!=np.nan):
        if(np.abs(hi-n)<hmin):
            tmin=ti
            hmin=hi-n
    return tmin
print(findh(2,h,t))
```

    3.979591836734694

##  Solución ejercicio 4.3.a

### Que el tanque se está llenando pero cada vez lo hace más rápido

##  Solución ejercicio 4.3.b

```python
Ah=0.5#m^2
h = odeint(tank,h0,t)
plt.figure(1)
plt.plot(t,h)
plt.xlabel('Time (s)')
plt.ylabel('Height (m)')
plt.grid()
plt.show()
```

##  Problema 5

### Modelo poblacional

Simula la siguiente ecuación, y supoga que cada unidad de tiempo corresponde a un minuto.

$$\frac{ds}{dt} = 0.05s(\frac{s}{20}-1)(1-\frac{s}{100}) $$

1. (20 puntos) Simula el sistema en un tiempo de $0$ a $200$ unidades de tiempo, con la condición inicial $s(0) = 21$
2. (15 puntos)
    - (10 puntos) Grafique la solución.
    - (5 puntos) ¿En que tiempo aproximadamente la poblacion alcanza su maxima capacidad?
3. (15 puntos)
    - (5 puntos) ¿Cual es la capacidad de soporte de este modelo poblacional?
    - (10  puntos) ¿Que pasa con una condición inicial menor (s(0)=21) ? ¿Y con una condición mayor a la capacidad de soporte?

```python
s0=21
t = np.linspace(0,200)#valores a evaluar
```

```python
def population(s,t):#Modelado
    dsdt=(0.05*s*(s/20-1)*(1-s/100))
    return dsdt
```

##  Solución ejercicio 5.1

```python
s = odeint(population,s0,t)
```

##  Solución ejercicio 5.2.a

```python
plt.figure(1)
plt.plot(t,s)
plt.xlabel('Time (s)')
plt.ylabel('population')
plt.grid()
plt.show()
```

##  Solución ejercicio 5.2.b

```python
def finds(n,margin,s,t):
    smin=100
    tmin=0
    for ti,si in zip(t,s):
        if(np.abs(1-(np.abs(si/n)-margin))<smin):
            tmin=ti
            smin=np.abs(1-(np.abs(si/n)-margin))
    return tmin
print(finds(100,-0.01,s,t))#Llegando al 1%
```

    102.04081632653062

##  Solución ejercicio 5.3.a

### el sistema al paso del tiempo se estabiliza al rededor de 100

##  Solución ejercicio 5.3.b

```python
s1 = odeint(population,20,t)
s2 = odeint(population,19,t)
s3 = odeint(population,110,t)
plt.figure(1)
plt.plot(t,s1,label='s=20')
plt.plot(t,s2,label='s=19')
plt.plot(t,s3,label='s=110')
plt.legend(framealpha=1, frameon=True);
plt.xlabel('Time (s)')
plt.ylabel('population')
plt.grid()
plt.show()
```

##  Problema 6 (estabilizar el sistema)

Diseña una función $u$ diferente de 0, para que el siguiente sistema no crezca, y se aproxime a 0 cuando t -> $\infty$.

$$\frac{ds}{dt} = 0.06u $$

1. (20 puntos) Simula el sistema en un tiempo de $0$ a $800$ unidades de tiempo, con la condición inicial $s(0) = 10$
2. (15 puntos)
    - (15 puntos) Grafique la solución.
3. (15 puntos)
    - (15 puntos) Escriba la ecuación de $u$ utilizada

```python
def model(y,t):
    k = 0.06
    u = -0.9*y
    dydt = k * u
    return dydt

s0 = 10

t = np.linspace(0,800)

s = odeint(model,s0,t)

```

```python
plt.plot(t,s)
plt.xlabel('time')
plt.ylabel('s(t)')
plt.show()
```

### SOLUCIÓN:

$$u(t) = -0.4s(t) $$
$$\frac{ds}{dt} = 0.06(-0.4s(t)) $$

```python

```

##  Problema 7

Diseña una función $u$ diferente de 0, para que el siguiente sistema no crezca, y se aproxime a 0 cuando t -> $\infty$.

$$\frac{dx}{dt} = 2x^2 + 0.06u $$

1. (20 puntos) Simula el sistema con la condición inicial $x(0) = 10$
2. (15 puntos)
    - (15 puntos) Grafique la solución.
3. (15 puntos)
    - (15 puntos) Escriba la ecuación de $u$ utilizada

```python

```

```python
def model(y,t):
    k = 0.06
    u = -2/0.06 * (y**2) + -0.4*y
    dydt = 2*(y**2) + k*u
    return dydt

x0 = 10

t = np.linspace(0,800)

x = odeint(model,x0,t)
```

```python
plt.plot(t,x)
plt.xlabel('time')
plt.ylabel('x(t)')
plt.show()
```

### SOLUCIÓN:

$$u(t) = -( \frac{2}{0.6}x^2 + x )$$
$$\frac{dx}{dt} = 2x^2 + 0.06u $$

##  Problema 8 (seguimiento de trayectorias)

Diseña una función $u$ diferente de 0, para que el siguiente sistema siga una trayectoria.

$$\frac{dx}{dt} = 2x^2 + 0.06u $$

1. (20 puntos) Simula el sistema con la condición inicial $x(0) = 10$
2. (15 puntos)
    - (15 puntos) Grafique la solución siguiendo la funcion de referencia $ x_{ref} = sin(t) $
3. (15 puntos)
    - (15 puntos) Escriba la ecuación de $u$ utilizada

```python

```

```python
# function that returns dy/dt
def model(y,t):
    dydt =  -y + 0.6*np.sin(t*np.pi/4)
    return dydt

# initial condition
y0 = 10

# time points

x=0.6*np.sin(t*np.pi/4)
# solve ODE
y = odeint(model,y0,t)
plt.plot(t,x)# plot results
plt.plot(t,y)
plt.xlabel('time')
plt.ylabel('y(t)')
plt.show()
```

##  Problema 9

Una empresa de transportes gestiona una flota de 60 carros de tres modelos diferentes.

- Los tipo X generan una media diaria de $ \$15,000$  pesos. y recorren diariamente una media de $400$ kilómetros.

- Los tipo Black generan diariamente una media de $\$10,000$ pesos y recorren $300$ kilómetros.

- Los tipo SUV generan diariamente $\$5,000$ pesos y recorren $100$ km. de media.

Diariamente los carros de la empresa transportan un total de $ \$475$ mil pesos y recorren $12500$ km. entre todos.

¿Cuántos carros gestiona la empresa de cada modelo?

```python

```

    array([ 5., 25., 30.])

```python

A=np.array([[15000,10000,5000],[400,300,100],[1,1,1]])
b=np.array([475000,12500,60])

z=np.linalg.solve(A,b)
print("La empresa gestiona:", np.round(z[0]), "vehículos del tipo X, " ,np.round(z[1]), "del tipo Black y ",np.round(z[2]), "del tipo SUV")
```

    La empresa gestiona: 5.0 vehículos del tipo X,  25.0 del tipo Black y  30.0 del tipo SUV

##  Problema 10

Ace Novelty recibió un pedido del Magic World Amusement Park de **900 pandas gigantes, 1200 perros San Bernardo y 2000 pájaros grandes.** La dirección Ace decidió que **500 pandas, 800 perros y 1300 pájaros** pueden ser fabricados **en su planta de Los Ángeles**, y el **resto** del pedido podría realizarse **en la planta de Seattle.**

Cada **panda** requiere **1.5** metros cuadradas de felpa, **30** metros cúbicos de relleno y **5** piezas de adorno; cada **perro** requiere **2** metros cuadradas de felpa, **35** metros cúbicos de relleno y **8** piezas de adorno, y cada **pájaro** requiere **2.5** metros cuadrados de felpa, **25** metros cúbicos de relleno y **15** piezas de adorno. La felpa cuesta **\$4.50** por metro cuadrado, el relleno cuesta **\$0.20** por metros cúbico y las piezas de adorno cuestan **\$0.25** por unidad.

a. Calcule la cantidad de cada tipo de material que se debe comprar para cada planta.

b. ¿Cuál es el costo total de materiales empleados en cada planta y el costo total de los materiales usados por Ace Novelty para cubrir el pedido?

| |Felpa|Relleno|Adorno|
|---|---|---|---|
|Pandas|1.50|  30.00|  5.00|
|Perros|2.00|  35.00|  8.00|
|Pájaros|2.50|  25.00|  15.00|

| |Pandas|Perros|Pájaros|
|---|---|---|---|
|L.A|500|800|1300|
|Seattle|400|400|700|

| | |
|---|---|
|Felpa|4.50|
|Relleno|0.20|
|Adorno|0.25|

A=$\left[
 \begin{array}{ccc}
 1.50 & 30.00 & 5.00  \\
 2.00 & 35.00 & 8.00  \\
 2.50 & 25.00 & 15.00 \\
\end{array}
\right]$,
P=
$\left[
 \begin{array}{ccc}
 500.00 & 800.00 & 1300.00 \\
 400.00 & 400.00 & 700.00  \\
\end{array}
\right]$,
C=
$\left[
 \begin{array}{c}
 4.5  \\
 0.2  \\
 0.25
\end{array}
\right]$

```python

A = np.array([[1.5, 30, 5],[2, 35, 8],[2.5, 25, 15]])
P = np.array([[500, 800, 1300],[400,400,700]])
C = np.array([[4.5],[0.2],[0.25]])
```

## a:La cantidad de cada tipo de material para cada planta,

```python
material_planta = np.dot(P,A)

print("Cantidad de cada tipo de material en Los Angeles:")
print("Felpa:",material_planta[0][0], "m2")
print("Relleno:",material_planta[0][1], "m3")
print("Adorno:",material_planta[0][2], "pieza(s)\n")

print("Cantidad de cada tipo de material en Seattle:")
print("Felpa:",material_planta[1][0], "m2")
print("Relleno:",material_planta[1][1], "m3")
print("Adorno:",material_planta[1][2], "pieza(s)\n")
```

    Cantidad de cada tipo de material en Los Angeles:
    Felpa: 5600.0 m2
    Relleno: 75500.0 m3
    Adorno: 28400.0 pieza(s)

    Cantidad de cada tipo de material en Seattle:
    Felpa: 3150.0 m2
    Relleno: 43500.0 m3
    Adorno: 15700.0 pieza(s)

## b:El costo total de los materiales para cada planta está dada por

```python
costo_planta = np.dot(material_planta,C)

print("Costo total de materiales en Los Angeles:")
print("$", costo_planta[0][0],"\n")
print("Costo total de materiales en Seattle:")
print("$", costo_planta[1][0],"\n")
```

    Costo total de materiales en Los Angeles:
    $ 47400.0

    Costo total de materiales en Seattle:
    $ 26800.0

## Costo total

```python
costo_total = costo_planta[0]+costo_planta[1]

print("Costo total para cubrir pedido:")
print("$", int(costo_total))
```

    Costo total para cubrir pedido:
    $ 74200

##  Problema 10

Aproxima la función exponencial con n=20

$$e^x =\sum_{n=0}^{20} \frac{x^n}{n!}$$

```python
def fact(a):
    if(a==0):
        return 1
    f=1
    for i in range(1,a+1):
        f *= i
    return f
def exp(x,n=20):
    sum=float()
    for i in range(n):
        sum += (x**i)/(fact(i))
    return sum
```

```python
exp(5)
```

$\displaystyle 148.4131078683383$

##  Problema 11

### Construir una cisterna rectangular

Se va a construir una cisterna rectangular con base y tapa cuadradas para almacenar **$12000pies^3$** de agua. Si el concreto para construir la base y los lados tiene un costo de **$100$ por $pie^2$** y el material para construir la **tapa** cuesta **$200$ por $pie^2$**

¿cuáles son las dimensiones de la cisterna que minimizan el costo de su construcción?

¿Qué se quiere en el problema?

Determinar las dimensiones de la cisterna que minimizan el costo de su construcción.
Suponiendo que las dimensiones de la cisterna son:
$x$ pies el lado de la base cuadrada y $h$ pies su altura.

¿Cuál es el costo de su construcción?

Para encontrar las dimensiones ($x$ & $h$) que minimizan el costo de su construcción se necesita la expresión del costo de la cisterna. Usamos la tabla siguiente:

El costo total de la contrucción de la cisterna es:

$$ C = 300x^2 + 400xh \text{   pesos}$$

En el problema aparece la siguiente restricción: **el volumen de la cisterna debe ser igual a $12 000 pies^3$, es decir, que $x^2h = 12000$.**

Tenemos pues:

Una función $C = 300x^2 + 400xh$ y una ecuación $x^2h = 12 000$.
De la ecuación despejamos una de las variables (la que más convenga) para sustituirla en la función. Conviene despejar $h$.

```python
#función objetivo
def Total_Cost(Dimensions):
    C = (300*Dimensions[0]**2)+(400*Dimensions[0]*Dimensions[1])
    return C

#restricción de volumen
def Volume(Dimensions):
    V = 12000
    V = V - (Dimensions[0]**2 * Dimensions[1])
    return V

initial_guess = [12,18]
Total_Cost(initial_guess)
```

$\displaystyle 129600$

```python
con_1 = {'type': 'ineq', 'fun':Total_Cost}
con_2 = {'type': 'eq', 'fun':Volume}
cons = [con_1,con_2]
bounds = (1.0,500.0)
bnds = [bounds,bounds]
solution = minimize(Total_Cost,initial_guess,method='SLSQP',\
                   bounds=bnds,constraints=cons)
solution
```

         fun: 359999.9999996771
         jac: array([24000.        ,  8000.00390625])
     message: 'Optimization terminated successfully.'
        nfev: 53
         nit: 12
        njev: 12
      status: 0
     success: True
           x: array([20.00000212, 29.99999365])

```python
solution.fun, solution.x
```

    (359999.9999996771, array([20.00000212, 29.99999365]))

```python
xdata = np.linspace(1,300,100)
hdata = 12000/xdata**2
Dimensions = [xdata,hdata]
C = Total_Cost(Dimensions)
Cost_Solution = Total_Cost(solution.x)
C_solution=[Cost_Solution]*len(xdata)

x_sol=[solution.x[0]]*len(xdata)
h_sol=[solution.x[1]]*len(xdata)

plt.figure()
plt.plot(xdata,C,'k', xdata,C_solution,'r',x_sol,C,'b')
plt.axis([0, 60, 0, 1e6])
```

```python
plt.figure()
plt.plot(hdata,C,'k', hdata,C_solution,'r',h_sol,C,'b')
plt.axis([0, 60, 0, 1e6])
```

##  Problema 12

Con el comienzo del curso se va a lanzar unas ofertas de material escolar. Unos almacenes quieren ofrecer 600 cuadernos, 500 carpetas y 400 bolígrafos para la oferta, empaquetándolo de dos formas distintas; en el primer bloque pondrá 2 cuadernos, 1 carpeta y 2 bolígrafos; en el segundo, pondrán 3 cuadernos, 1 carpeta y 1 bolígrafo. Los precios de cada paquete serán 6.5 y 7 €, respectivamente.

¿Cuántos paquetes le conviene poner de cada tipo para obtener el máximo beneficio?

```python
#función objetivo
def obj_func(Package):
    Val_Pack1 = 6.5
    Val_Pack2 = 7
    return Val_Pack1*Package[0] + Val_Pack2*Package[1]

#constraint paquete 1
def constraint_paq1(Package):
    Cuadernos_Paq1=2
    Cuadernos_Paq2=3
    return 600 - (Cuadernos_Paq1*Package[0] + Cuadernos_Paq2*Package[1])

#constraint paquete 2
def constraint_paq2(Package):
    Boli_Paq1=2
    Boli_Paq2=1
    return 400 - (Boli_Paq1*Package[0] + Boli_Paq2*Package[1])

#constraint carpetas
def constraint_folders(Package):
    return 500 - (Package[0] + Package[1])

#función a maximizar
def objective(Package):
    return -obj_func(Package)

```

```python
initial_guess = [300,200]
obj_func(initial_guess)
```

$\displaystyle 3350.0$

```python
con_1 = {'type': 'ineq', 'fun':constraint_paq1}
con_2 = {'type': 'ineq', 'fun':constraint_paq2}
con_fol = {'type': 'ineq', 'fun':constraint_folders}
cons = [con_1,con_2,con_fol]
```

```python
solution = minimize(objective,initial_guess,method='SLSQP',\
                   constraints=cons)
solution
```

         fun: -1675.0000000074115
         jac: array([-6.5, -7. ])
     message: 'Optimization terminated successfully.'
        nfev: 8
         nit: 2
        njev: 2
      status: 0
     success: True
           x: array([150., 100.])

```python
solution.fun*-1, solution.x
```

    (1675.0000000074115, array([150., 100.]))

##  Problema 13

Se dispone de 600 g de un determinado fármaco para elaborar pastillas grandes y pequeñas. Las grandes pesan 40 g y las pequeñas 30 g. Se necesitan al menos tres pastillas grandes, y al menos el doble de pequeñas que de las grandes. Cada pastilla grande proporciona un beneficio de 2 € y la pequeña de 1 €.

¿Cuántas pastillas se han de elaborar de cada clase para que el beneficio sea máximo?

```python
np.random.seed()

#función que representa el objetivo
def obj_fnc(Type_Pill):
    ben_x = 2 #beneficio de 2 euros
    ben_y = 1 #beneficio de 1 euro
    benefit = (ben_x*Type_Pill[0]) + (ben_y*Type_Pill[1])
    return benefit

#Restricción sobre material
def constraint_1(Weight_Pill):
    Wx = 40 #40 gramos por pildora grande
    Wy = 30 ##30 gramos por pildora grande
    Total_Weight = (Wx*Weight_Pill[0]) + (Wy*Weight_Pill[1])
    return 600 - Total_Weight

#Restricción mínimo de pastillas grandes
def constraint_x(Num_Pill):
    return Num_Pill[0] - 3

#restricción mínimo de pastillas pequeñas
def constraint_y(Benefit_Amnt):
    return Benefit_Amnt[1] - 2*Benefit_Amnt[0]

#función a optimizar
def objective(Type_Pill):
    return -obj_fnc(Type_Pill)

initial_guess = [4,8]
obj_fnc(initial_guess)
```

$\displaystyle 16$

```python
con_1 = {'type': 'ineq', 'fun':constraint_1}
con_x = {'type': 'ineq', 'fun':constraint_x}
con_y = {'type': 'ineq', 'fun':constraint_y}
cons = [con_1,con_x,con_y]
```

```python
solution = minimize(objective,initial_guess,method='SLSQP',\
                   constraints=cons)
solution
```

         fun: -24.000000000000007
         jac: array([-2., -1.])
     message: 'Optimization terminated successfully.'
        nfev: 12
         nit: 3
        njev: 3
      status: 0
     success: True
           x: array([ 6., 12.])

```python
solution.fun*-1, solution.x
```

    (24.000000000000007, array([ 6., 12.]))

##  Problema 14

El conjunto de datos proviene del repositorio UCI Machine Learning y está relacionado con campañas de marketing directo (llamadas telefónicas) de una institución bancaria portuguesa.

El objetivo de la clasificación es predecir si el cliente se suscribirá (1/0) a un depósito a plazo (variable y). El conjunto de datos se puede descargar desde aquí.

https://raw.githubusercontent.com/madmashup/targeted-marketing-predictive-engine/master/banking.csv

### Input variables

- age (numeric)
- job : type of job (categorical: “admin”, “blue-collar”, “entrepreneur”, “housemaid”, “management”, “retired”, “self-employed”, “services”, “student”, “technician”, “unemployed”, “unknown”)
- marital : marital status (categorical: “divorced”, “married”, “single”, “unknown”)
- education (categorical: “basic.4y”, “basic.6y”, “basic.9y”, “high.school”, “illiterate”, “professional.course”, “university.degree”, “unknown”)
- default: has credit in default? (categorical: “no”, “yes”, “unknown”)
- housing: has housing loan? (categorical: “no”, “yes”, “unknown”)
- loan: has personal loan? (categorical: “no”, “yes”, “unknown”)
- contact: contact communication type (categorical: “cellular”, “telephone”)
- month: last contact month of year (categorical: “jan”, “feb”, “mar”, …, “nov”, “dec”)
- day_of_week: last contact day of the week (categorical: “mon”, “tue”, “wed”, “thu”, “fri”)
- duration: last contact duration, in seconds (numeric). Important note: this attribute highly affects the output target (e.g., if duration=0 then y=’no’). The duration is not known before a call is performed, also, after the end of the call, y is obviously known. Thus, this input should only be included for benchmark purposes and should be discarded if the intention is to have a realistic predictive model
- campaign: number of contacts performed during this campaign and for this client (numeric, includes last contact)
- pdays: number of days that passed by after the client was last contacted from a previous campaign (numeric; 999 means client was not previously contacted)
- previous: number of contacts performed before this campaign and for this client (numeric)
- poutcome: outcome of the previous marketing campaign (categorical: “failure”, “nonexistent”, “success”)
- emp.var.rate: employment variation rate — (numeric)
- cons.price.idx: consumer price index — (numeric)
- cons.conf.idx: consumer confidence index — (numeric)
- euribor3m: euribor 3 month rate — (numeric)
- nr.employed: number of employees — (numeric)

### Predict variable (desired target):

y — has the client subscribed a term deposit? (binary: “1”, means “Yes”, “0” means “No”)

```python

```

```python
import os
import pandas as pd

banking = pd.read_csv('banking.csv')
print(banking.columns)
```

    Index(['age', 'job', 'marital', 'education', 'default', 'housing', 'loan',
           'contact', 'month', 'day_of_week', 'duration', 'campaign', 'pdays',
           'previous', 'poutcome', 'emp_var_rate', 'cons_price_idx',
           'cons_conf_idx', 'euribor3m', 'nr_employed', 'y'],
          dtype='object')

```python
banking.head()
```

      age
      job
      marital
      education
      default
      housing
      loan
      contact
      month
      day_of_week
      ...
      campaign
      pdays
      previous
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed
      y

      0
      44
      blue-collar
      married
      basic.4y
      unknown
      yes
      no
      cellular
      aug
      thu
      ...
      1
      999
      0
      nonexistent
      1.4
      93.444
      -36.1
      4.963
      5228.1
      0

      1
      53
      technician
      married
      unknown
      no
      no
      no
      cellular
      nov
      fri
      ...
      1
      999
      0
      nonexistent
      -0.1
      93.200
      -42.0
      4.021
      5195.8
      0

      2
      28
      management
      single
      university.degree
      no
      yes
      no
      cellular
      jun
      thu
      ...
      3
      6
      2
      success
      -1.7
      94.055
      -39.8
      0.729
      4991.6
      1

      3
      39
      services
      married
      high.school
      no
      no
      no
      cellular
      apr
      fri
      ...
      2
      999
      0
      nonexistent
      -1.8
      93.075
      -47.1
      1.405
      5099.1
      0

      4
      55
      retired
      married
      basic.4y
      no
      yes
      no
      cellular
      aug
      fri
      ...
      1
      3
      1
      success
      -2.9
      92.201
      -31.4
      0.869
      5076.2
      1

5 rows × 21 columns

```python
#score = 0.9106293095076236
```

```python
import os
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import LabelEncoder
from sklearn import preprocessing
import matplotlib.pyplot as plt

banking = pd.read_csv('banking.csv')
print(banking.columns)
```

    Index(['age', 'job', 'marital', 'education', 'default', 'housing', 'loan',
           'contact', 'month', 'day_of_week', 'duration', 'campaign', 'pdays',
           'previous', 'poutcome', 'emp_var_rate', 'cons_price_idx',
           'cons_conf_idx', 'euribor3m', 'nr_employed', 'y'],
          dtype='object')

```python
banking.head()
```

      age
      job
      marital
      education
      default
      housing
      loan
      contact
      month
      day_of_week
      ...
      campaign
      pdays
      previous
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed
      y

      0
      44
      blue-collar
      married
      basic.4y
      unknown
      yes
      no
      cellular
      aug
      thu
      ...
      1
      999
      0
      nonexistent
      1.4
      93.444
      -36.1
      4.963
      5228.1
      0

      1
      53
      technician
      married
      unknown
      no
      no
      no
      cellular
      nov
      fri
      ...
      1
      999
      0
      nonexistent
      -0.1
      93.200
      -42.0
      4.021
      5195.8
      0

      2
      28
      management
      single
      university.degree
      no
      yes
      no
      cellular
      jun
      thu
      ...
      3
      6
      2
      success
      -1.7
      94.055
      -39.8
      0.729
      4991.6
      1

      3
      39
      services
      married
      high.school
      no
      no
      no
      cellular
      apr
      fri
      ...
      2
      999
      0
      nonexistent
      -1.8
      93.075
      -47.1
      1.405
      5099.1
      0

      4
      55
      retired
      married
      basic.4y
      no
      yes
      no
      cellular
      aug
      fri
      ...
      1
      3
      1
      success
      -2.9
      92.201
      -31.4
      0.869
      5076.2
      1

5 rows × 21 columns

```python
banking.rename(columns={'y':'willRespond'},inplace=True)
banking.columns
```

    Index(['age', 'job', 'marital', 'education', 'default', 'housing', 'loan',
           'contact', 'month', 'day_of_week', 'duration', 'campaign', 'pdays',
           'previous', 'poutcome', 'emp_var_rate', 'cons_price_idx',
           'cons_conf_idx', 'euribor3m', 'nr_employed', 'willRespond'],
          dtype='object')

```python
banking.drop(['duration','contact','month','day_of_week','default','pdays',],axis=1,inplace=True) #Removing unnecessary columns
banking.head()
```

      age
      job
      marital
      education
      housing
      loan
      campaign
      previous
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed
      willRespond

      0
      44
      blue-collar
      married
      basic.4y
      yes
      no
      1
      0
      nonexistent
      1.4
      93.444
      -36.1
      4.963
      5228.1
      0

      1
      53
      technician
      married
      unknown
      no
      no
      1
      0
      nonexistent
      -0.1
      93.200
      -42.0
      4.021
      5195.8
      0

      2
      28
      management
      single
      university.degree
      yes
      no
      3
      2
      success
      -1.7
      94.055
      -39.8
      0.729
      4991.6
      1

      3
      39
      services
      married
      high.school
      no
      no
      2
      0
      nonexistent
      -1.8
      93.075
      -47.1
      1.405
      5099.1
      0

      4
      55
      retired
      married
      basic.4y
      yes
      no
      1
      1
      success
      -2.9
      92.201
      -31.4
      0.869
      5076.2
      1

```python
labels=banking.willRespond.values
labels
```

    array([0, 0, 1, ..., 0, 0, 0], dtype=int64)

```python
le=preprocessing.LabelEncoder()
le.fit(banking.poutcome)
list(le.classes_)
```

    ['failure', 'nonexistent', 'success']

```python
#se les asigna u valor numérico a cada uno de los posibles estados para cada columna
banking.poutcome=le.transform(banking.poutcome)
banking.head()
```

      age
      job
      marital
      education
      housing
      loan
      campaign
      previous
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed
      willRespond

      0
      44
      blue-collar
      married
      basic.4y
      yes
      no
      1
      0
      1
      1.4
      93.444
      -36.1
      4.963
      5228.1
      0

      1
      53
      technician
      married
      unknown
      no
      no
      1
      0
      1
      -0.1
      93.200
      -42.0
      4.021
      5195.8
      0

      2
      28
      management
      single
      university.degree
      yes
      no
      3
      2
      2
      -1.7
      94.055
      -39.8
      0.729
      4991.6
      1

      3
      39
      services
      married
      high.school
      no
      no
      2
      0
      1
      -1.8
      93.075
      -47.1
      1.405
      5099.1
      0

      4
      55
      retired
      married
      basic.4y
      yes
      no
      1
      1
      2
      -2.9
      92.201
      -31.4
      0.869
      5076.2
      1

```python
banking.housing = le.fit_transform(banking.housing)
banking.loan=le.fit_transform(banking.loan)
banking.job=le.fit_transform(banking.job)
banking.marital=le.fit_transform(banking.marital)
banking.education=le.fit_transform(banking.education)
banking.head()
```

      age
      job
      marital
      education
      housing
      loan
      campaign
      previous
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed
      willRespond

      0
      44
      1
      1
      0
      2
      0
      1
      0
      1
      1.4
      93.444
      -36.1
      4.963
      5228.1
      0

      1
      53
      9
      1
      7
      0
      0
      1
      0
      1
      -0.1
      93.200
      -42.0
      4.021
      5195.8
      0

      2
      28
      4
      2
      6
      2
      0
      3
      2
      2
      -1.7
      94.055
      -39.8
      0.729
      4991.6
      1

      3
      39
      7
      1
      3
      0
      0
      2
      0
      1
      -1.8
      93.075
      -47.1
      1.405
      5099.1
      0

      4
      55
      5
      1
      0
      2
      0
      1
      1
      2
      -2.9
      92.201
      -31.4
      0.869
      5076.2
      1

```python
plt.hist(banking.age)
```

```python
banking['age'].describe()
```

    count    41188.00000
    mean        40.02406
    std         10.42125
    min         17.00000
    25%         32.00000
    50%         38.00000
    75%         47.00000
    max         98.00000
    Name: age, dtype: float64

```python
banking.apply(lambda x: len(x.unique()))
```

    age                78
    job                12
    marital             4
    education           8
    housing             3
    loan                3
    campaign           42
    previous            8
    poutcome            3
    emp_var_rate       10
    cons_price_idx     26
    cons_conf_idx      26
    euribor3m         316
    nr_employed        11
    willRespond         2
    dtype: int64

```python
features = banking[['age','job','marital','education','housing','loan','poutcome','emp_var_rate','cons_price_idx','cons_conf_idx','euribor3m','nr_employed' ]]
features.head()
```

      age
      job
      marital
      education
      housing
      loan
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed

      0
      44
      1
      1
      0
      2
      0
      1
      1.4
      93.444
      -36.1
      4.963
      5228.1

      1
      53
      9
      1
      7
      0
      0
      1
      -0.1
      93.200
      -42.0
      4.021
      5195.8

      2
      28
      4
      2
      6
      2
      0
      2
      -1.7
      94.055
      -39.8
      0.729
      4991.6

      3
      39
      7
      1
      3
      0
      0
      1
      -1.8
      93.075
      -47.1
      1.405
      5099.1

      4
      55
      5
      1
      0
      2
      0
      2
      -2.9
      92.201
      -31.4
      0.869
      5076.2

```python
banking_dummies = pd.get_dummies(features)
banking_dummies.head()
```

      age
      job
      marital
      education
      housing
      loan
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed

      0
      44
      1
      1
      0
      2
      0
      1
      1.4
      93.444
      -36.1
      4.963
      5228.1

      1
      53
      9
      1
      7
      0
      0
      1
      -0.1
      93.200
      -42.0
      4.021
      5195.8

      2
      28
      4
      2
      6
      2
      0
      2
      -1.7
      94.055
      -39.8
      0.729
      4991.6

      3
      39
      7
      1
      3
      0
      0
      1
      -1.8
      93.075
      -47.1
      1.405
      5099.1

      4
      55
      5
      1
      0
      2
      0
      2
      -2.9
      92.201
      -31.4
      0.869
      5076.2

```python
banking_dummies.isna().any()
```

    age               False
    job               False
    marital           False
    education         False
    housing           False
    loan              False
    poutcome          False
    emp_var_rate      False
    cons_price_idx    False
    cons_conf_idx     False
    euribor3m         False
    nr_employed       False
    dtype: bool

```python
banking_dummies_train = banking_dummies.dropna()
banking_dummies_train.isna().any()
```

    age               False
    job               False
    marital           False
    education         False
    housing           False
    loan              False
    poutcome          False
    emp_var_rate      False
    cons_price_idx    False
    cons_conf_idx     False
    euribor3m         False
    nr_employed       False
    dtype: bool

```python
labels_train = labels[banking_dummies_train.index]
banking_dummies_train.head()
```

      age
      job
      marital
      education
      housing
      loan
      poutcome
      emp_var_rate
      cons_price_idx
      cons_conf_idx
      euribor3m
      nr_employed

      0
      44
      1
      1
      0
      2
      0
      1
      1.4
      93.444
      -36.1
      4.963
      5228.1

      1
      53
      9
      1
      7
      0
      0
      1
      -0.1
      93.200
      -42.0
      4.021
      5195.8

      2
      28
      4
      2
      6
      2
      0
      2
      -1.7
      94.055
      -39.8
      0.729
      4991.6

      3
      39
      7
      1
      3
      0
      0
      1
      -1.8
      93.075
      -47.1
      1.405
      5099.1

      4
      55
      5
      1
      0
      2
      0
      2
      -2.9
      92.201
      -31.4
      0.869
      5076.2

```python
model = LogisticRegression(solver='lbfgs',max_iter=2000)
model.fit(banking_dummies_train,labels_train)
```

    LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
                       intercept_scaling=1, l1_ratio=None, max_iter=2000,
                       multi_class='auto', n_jobs=None, penalty='l2',
                       random_state=None, solver='lbfgs', tol=0.0001, verbose=0,
                       warm_start=False)

```python
#real, # Predict
labels_train ,model.predict(banking_dummies_train)
```

    (array([0, 0, 1, ..., 0, 0, 0], dtype=int64),
     array([0, 0, 1, ..., 0, 0, 0], dtype=int64))

```python
true_predict = sum(model.predict(banking_dummies_train) ==  labels_train)
true_predict
```

    36958

```python
true_ratio = sum(model.predict(banking_dummies_train) ==  labels_train) / (len(labels_train))
true_ratio
```

$\displaystyle 0.897300184519763$

```python
print("logistic regression score: %f" % model.score(banking_dummies_train, labels_train))
```

    logistic regression score: 0.897300

```python
from sklearn.model_selection import train_test_split
```

```python
train_data, test_data, train_labels, test_labels = train_test_split(banking_dummies_train, labels_train,
                                                                    random_state=0,test_size=0.33)
```

```python
train_data.shape,test_data.shape

model = LogisticRegression(solver='lbfgs',max_iter=2000).fit(train_data,train_labels)
print("Logistic regression score: %f" % model.score(test_data,test_labels))
```

    Logistic regression score: 0.898919

```python
train_data.shape,test_data.shape

model = LogisticRegression(solver='lbfgs',max_iter=2000).fit(train_data,train_labels)
print("Logistic regression score: %f" % model.score(test_data,test_labels))
```

    Logistic regression score: 0.898919

```python

```


# Exercises for Machine Learning with Python, Lecture 1: *Linear Least Squares Regression*

## Before you begin the exercises:

The datafiles are text files stored here (also try and download them to your own computer, open and see what they contain):

Features: https://www.dropbox.com/s/pf2sfiy9l86xhww/boston_features.txt

Prices: https://www.dropbox.com/s/j7flze0oe86pr6o/boston_prices.txt

*   Start by downloading the dataset:

```
# Download the features and target (the prices) to Google Colab using !wget
!wget -O boston_features.txt https://www.dropbox.com/s/pf2sfiy9l86xhww/boston_features.txt
!wget -O boston_prices.txt https://www.dropbox.com/s/j7flze0oe86pr6o/boston_prices.txt
```

This time we will not be using a Pandas DataFrames, because we will code the Linear Least Squares Regression ourselves using Numpy.

*   Now, load the txt files into NumPy arrays:

```
import numpy as np

features = np.loadtxt("boston_features.txt")
prices = np.loadtxt("boston_prices.txt")
```

As you can see below, the features is a matrix contatining 506 rows (one for each house), each with 13 entries (one for each feature). Additionally, there are 506 prices (again, one for each house).

```
print(features.shape)
print(prices.shape)
```

```
print(features)
print(prices)
```

Beside the housing prices, the dataset contains and information about location, etc (see below), and the prices are units of in USD $1000.

```
Index   Description
-----------------------------------------------------------------------
   0    per capita crime rate by town
   1    proportion of residential land zoned for lots over 25,000 sq.ft.
   2    proportion of non-retail business acres per town
   3    Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
   4    nitric oxides concentration (parts per 10 million)
   5    average number of rooms per dwelling
   6    proportion of owner-occupied units built prior to 1940
   7    weighted distances to five Boston employment centres
   8    index of accessibility to radial highways
   9    full-value property-tax rate per $10,000
  10    pupil-teacher ratio by town
  11    1000(Bk - 0.63)^2 where Bk is the proportion of African Americans by town
  12    % lower status of the population
```

## Exercise 1.1: Exploratory Data Analysis

Before we begin the regression, lets have a look at the data. As in the lecture, we will plot the correlation between our features using Seaborn.

Since we loaded in the data as a Numpy Array, we have to create a Pandas DataFrame for Seaborn. This can be done with the code below:

```
#Pandas DataFrames
import pandas as pd

# Make a Pandas dataframe from the features
df = pd.DataFrame(features[:,:5])

# NOTE: ONLY TAKES THE FIRST 5 COLUMNS/FEATURES
# features[:,:5] is Numpy slice notation for "take all rows, and first five colums"

# Print the type of the dataframe, just to make sure we coverted correctly
print(type(df))
```

Note that since there are 13 features, the correlation plot would contain 169 plots. This would be quite slow in Google Colab. For speed reasons, we only loaded the first 5 featues into the pandas dataframe for plotting.

### Question 1.1.1:

*   Just like in the lecture, make an `sns.pairplot()` using Seaborn of the dataframe we just made.
*   (Optional) If you want, change the style of the plot as shown during the lecture. You can see some customization options in the documentation: https://seaborn.pydata.org/generated/seaborn.pairplot.html

```
import seaborn as sns
import matplotlib.pyplot as plt

# Plot the pairplot of the Pandas DataFrame
```

### Question 1.1.2:

One thing you might note from the pair-correlation plot is that some of the features look odd. However, these features still work well for linear regression.

*    Can you explain why the correlations between Feature 3 and everything else look odd?

**Give your answer:**

## Exercise 1.2: Training and Test sets

In order to train and evaluate our linear regression model, we first have to divide the dataset into two parts: A training set and a test set.

### Question 1.2.1:
A common practice is to have the training set be 70% of the full set and test set 30%.

There are 506 houses in our dataset, so divide your data into 354 in the training set and 152 in the test set.

You can use Numpy's slice notation for this, as introducted in the first lectures. For example, to take the first five *rows* from an array you can use the following notation:
```
data_first_five_rows = data[:5]
```

To complete this Question, do the following task:
*    Divide both of the numpy arrays `features` and `prices` into two parts.
*    Use, for example, the Numpy slice notation to achieve this.
*    Make sure that the same house in never in both the test and training set at the same time! Other than that, you are free to choose which rows to the test set and which go to the training set.

```
# Make the two sets of features below
features_train = ???
features_test = ???

# Make the two sets of prices below
prices_train = ???
prices_test = ???
```

## Exercise 1.3: Regression Fit

In the linear least squares regression, we solve an equation that looks like this:

$$ \mathbf{y} = \mathbf{X} \mathbf{\alpha}$$

Where $\mathbf{y}$ is a vector containing the target labels (for example housing prices), $\mathbf{X}$ is a matrix where the each row contain features (in our case the features for a given house in Boston) for each house. Finally, $\alpha is a vector containing the (unknown) regression coefficients.

Fortunately, Numpy has built-in capabilites for solving linear least squares regression. This is done using the function which performs the "least squares" fit:

```
alpha, residual, rank, singular_values = np.linalg.lstsq(X, y)
```

As you can see, the function actually returns four items, the first one being the regression coefficients, and the next three are the residuals of the fit, the rank of the matrix problem, and finally the singular values of the matrix.

For this exercise we only need to use the first one, but feel free to print and look at the three other items as well.

You can see the documentation for `np.linalg.lstsq()` here: https://numpy.org/doc/stable/reference/generated/numpy.linalg.lstsq.html

### Question 1.3.1:

*    Just like in the code above, use `np.linalg.lstsq()` to fit the alpha regression-coefficients.

**Hint:** Use the `features_train` instead of `X` and `prices_train` instead of `y`.

**Note:** *Google Colab uses a version of Numpy which might give you a warning abour "rcond", which is not a problem.*

```
# Get the alpha coefficients

```

## Exercise 1.4: Making predictions

Now that you have obtained the alpha coefficients in the previous question, it is time to use them to make predictions.

Remember how we are approximating the price as a linear sum of the weighted features for a given house:

\begin{equation}
f(\mathbf{x}) = x_1 \alpha_1 + x_2 \alpha_2 + \dots + x_n \alpha_n
\end{equation}
or written in vector notation:
\begin{equation}
f(\mathbf{x}) = \mathbf{x} \cdot \mathbf{\alpha}
\end{equation}

where $\mathbf{x}$ is the vector containing all the features for the house and $\mathbf{\alpha}$ is the vector of regression coefficient you obtained by fitting the features to the prices of the training set.

### Question 1.4.1:

With the alpha regression coefficients you found in the previous exercise, you can use your linear least squares "machine" to predict the price of house that are not in your training set.

As in the equation above, this is done by taking the dot product between the feature vector for a given house and the regression coefficients.

Remember, that the features for each house are stored in the rows of the "features" numpy arrays you created in Question 1.2.1.

*    Calculate the price of all the houses in the test set. That is, take the dot product between the regression coefficients and every row-vector of the `features_test` array.

```
# Calculate the prices of the houses in the test set
#, i.e. the dot product between "features_test" and "alpha"

```

*Hint:* Save the predicted prices for the test set in a list or numpy array, which you can use in question 1.4.2.

### Question 1.4.2:
Since we already know the true price of the houses in ou dataset, we can now compare the true prices of the house

Use for example `plt.scatter()` as we did in the introductory lectures.

*    Plot the correlation between the true prices stored in the `prices_test` and the predicted prices.

Does it look like there is some correlation?

```
# Write the code to plot the correlation between "prices_test" and the prices
# you predicted in Question 1.4.1.

```

### Question 1.4.3:

One common measure of the prediction error is the "root mean squared error" (RMSE) between the true values and the predicted values. The RMSE is calculated as follows:

\begin{equation}
\mathrm{RMSE} = \sqrt{\frac{1}{N}\sum_{i=0}^{N} \left( y_i^\mathrm{true} - y_i^\mathrm{predicted}\right)^2}
\end{equation}

*    In this question, calculate the RMSE for your test set, i.e. the RMSE between the true prices and the prices you predicted in Question 1.4.1.

```
# Calculate the RMSE

```

## Exercise 1.5: Linear Regression with Scikit-learn

As we saw in the lecture, the Python library Scikit-learn has capabilities for almost any type of macine learning you can think of.

It also does Linear Regression. Below is the a code example to use linear regression with sklearn.

```
# Import the machine
from sklearn.linear_model import LinearRegression

# Make a linear regression machine identically to our fitting in Numpy
machine = LinearRegression(fit_intercept=False)

# Fit the machine using the training features and training labels
machine.fit(x_train, y_train)
```

After the machine has been fitted, you can use the built-in `predict()` method to make predictions on new feature maps:

```
# Predict y-values using x_test features
y_test_predicted = machine.predict(x_test)
```

### Question 1.5.1:

*    In this question, use Scikit-learn to train a `LinearRegression` machine on the housing dataset. Use the same training and test data which you used in the previous example.

**Hint:** You use the above code snippets to solve this question.

```
# Implement the linear regression with Scikit-learn

```

### Question 1.5.2:

*    In this question, make a scatter plot between the between housing prices you predicted with Scikit-learn and the true prices.
*    Additionally, calculate the RMSE for prices you predicted with Scikit-learn.

**Hint:** If everything went well, you should have gotten the exact same plot and RMSE as you found in Questions 1.4.2 and 1.4.3.

```
# Make a scatter plot for  the housing prices you predicted with
# Scikit-learn and the true prices for the test set

```

```
# Calculate the RMSE for the housing prices you predicted with
# Scikit-learn and the true prices for the test set

```