s1Eva_IT2012_T2_MN Modelo Leontief

Ejercicio: 1Eva_IT2012_T2_MN Modelo Leontief

Planteamiento

X – TX = D

A(I-T) = D

(I-T)X = D

para el algoritmo:

A = I – T

B = D


Algoritmo en Python

Resultados del algoritmo

respuesta X: 
[[158.56573701]
 [288.73225044]
 [323.87373581]]
verificar A.X=B: 
[[ 79.99999997]
 [139.99999998]
 [200.        ]]
>>> itera
8
>>>

Instrucciones en Python

# Método de Gauss-Seidel
# solución de sistemas de ecuaciones
# por métodos iterativos

import numpy as np

# INGRESO
T = np.array([[0.40, 0.03, 0.02],
              [0.06, 0.37, 0.10],
              [0.12, 0.15, 0.19]])
A = np.identity(3) - T

B = np.array([80.0, 140.0, 200.0],dtype=float)

X0 = np.array([200.0,200.0,200.0])

tolera = 0.00001
iteramax = 100

# PROCEDIMIENTO
# Gauss-Seidel
tamano = np.shape(A)
n = tamano[0]
m = tamano[1]
#  valores iniciales
X = np.copy(X0)
diferencia = np.ones(n, dtype=float)
errado = 2*tolera

itera = 0
while not(errado<=tolera or itera>iteramax):
    # por fila
    for i in range(0,n,1):
        # por columna
        suma = 0 
        for j in range(0,m,1):
            # excepto diagonal de A
            if (i!=j): 
                suma = suma-A[i,j]*X[j]
        
        nuevo = (B[i]+suma)/A[i,i]
        diferencia[i] = np.abs(nuevo-X[i])
        
        X[i] = nuevo
    errado = np.max(diferencia)
    itera = itera + 1

# Respuesta X en columna
X = np.transpose([X])

# revisa si NO converge
if (itera>iteramax):
    X=0
# revisa respuesta
verifica = np.dot(A,X)

# SALIDA
print('respuesta X: ')
print(X)
print('verificar A.X=B: ')
print(verifica)

s1Eva_IIT2011_T2 Sistema de Ecuaciones, diagonal dominante

Ejercicio: 1Eva_IIT2011_T2 Sistema de Ecuaciones, diagonal dominante

1. Desarrollo analítico

Solución iterativa usando el método de Jacobi

El sistema de ecuaciones

\begin{cases} -2x+5y+9z=1\\7x+y+z=6\\-3x+7y-z=-26\end{cases}

cambia a su forma matricial AX=B

\begin{bmatrix} -2 & 5 & 9 \\ 7 & 1 & 1 \\ -3 & 7 &-1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \end{bmatrix} = \begin{bmatrix} 1 \\ 6 \\ -26 \end{bmatrix}

y luego como matriz aumentada y realizar el pivoteo parcial por filas, buscando hacerla diagonal dominante:

\begin{pmatrix} 7 & 1 & 1 &6\\ -3 & 7 &-1 & -26\\ -2 & 5 & 9 &1 \end{pmatrix}

las ecuaciones para el algoritmo se obtienen despejando una variable diferente en cada ecuación.

x_{i+1}=\frac{6-y_i-z_i}{7} y_{i+1}=\frac{-26+3x_i+z_i}{7} z_{i+1}=\frac{1+2x_i-5y_i}{9}

Dado el vector inicial X0= [0, 0, 0], y una tolerancia de 0.0001, e desarrollan al menos 3 iteraciones:

El error se verifica para éste ejercicio como el mayor valor de la diferencia entre iteraciones consecutivas. Analogía al video del acople entre las aeronaves. Si una coordenada aún no es la correcta …. menor a lo tolerado, pues NO hay acople…

itera = 0

x_1=\frac{6-(0)-(0)}{7} = 0.8571 y_1=\frac{-26+3(0)+(0)}{7} = -3,7142 z_1=\frac{1+2(0)-5(0)}{9} =0.111 diferencia = [ 0.8571 -0 , -3,7142 -0 ,0.1111- 0 ] = [ 0.8571 , -3,7142,0.1111 ] errado = max |diferencia| = 3,7142

error es más alto que lo tolerado

X_1= [ 0.8571 , -3.7142 ,0.1111 ]

Itera = 1

x_2=\frac{6-(-3,7142) -0.1111}{7} = 1.3718 y_2=\frac{-26+3(0.8571)+0.1111}{7} = -3.3310 z_2=\frac{1+2(0.8571)-5(-3,7142)}{9} = 2.3650 diferencia = [ 1.3718-0.8571 , -3.3310 -(-3.7142) , 2.3650 - 0.1111 ] = [0.5146 , 0.3832, 2.2539 ] errado = max |diferencia| = 2.2539

el error disminuye, pero es más alto que lo tolerado

X_2= [ 1.3718 , -3.3310, 2.3650 ]

Itera = 2

x_3 = \frac{6-(-3.3310)-2.3650}{7} = 0.9951 y_3 = \frac{-26+3(1.3718)+2.3650}{7} = -2.7884 z_3 = \frac{1+2(1.3718)-5(-3.3310)}{9} = 2.2665 diferencia = [ 0.9951 - 1.3718 , -2.7884 -(-3.3310) , 2.2665- 2.3650] diferencia = [ -0.3766 , 0.5425 , -0.0985] errado = max |diferencia| = 0.5425

el error disminuye, pero es más alto que lo tolerado

X_3= [ 0.9951 , -2.7884 , 2.2665]

Observación: Si el error disminuye en cada iteración, se puede intuir que se converge a la solución. Se puede continuar con la 4ta iteración…


2. Solución numérica usando Python

Usando el algoritmo desarrollado en clase se obtiene la respuesta con 13 iteraciones:

Matriz aumentada
[[ -2.   5.   9.   1.]
 [  7.   1.   1.   6.]
 [ -3.   7.  -1. -26.]]
Pivoteo parcial:
  1 intercambiar filas:  0 y 1
  2 intercambiar filas:  1 y 2
AB
Iteraciones Jacobi
itera,[X],errado
0 [0. 0. 0.] 1.0
1 [ 0.85714286 -3.71428571  0.11111111] 3.7142857142857144
2 [ 1.37188209 -3.33106576  2.36507937] 2.2539682539682544
3 [ 0.99514091 -2.78846777  2.26656589] 0.5425979915775843
4 [ 0.93170027 -2.96400162  1.8814023 ] 0.3851635892452223
5 [ 1.0117999  -3.04621384  1.96482318] 0.0834208883015708
6 [ 1.01162724 -2.99996816  2.02829656] 0.06347337312830126
7 [ 0.99595309 -2.99097453  2.00256614] 0.025730417621558477
8 [ 0.99834406 -3.0013678   1.99408654] 0.010393267289710018
9 [ 1.00104018 -3.00155447  2.0003919 ] 0.006305364149447268
10 [ 1.00016608 -2.99949822  2.00109475] 0.002056248145824391
11 [ 0.99977193 -2.99977243  1.99975814] 0.0013366043333828959
12 [ 1.00000204 -3.0001323   1.99982289] 0.0003598675094789172
13 [ 1.0000442  -3.00002443  2.00007395] 0.0002510632800638568
14 [ 0.99999292 -2.99997049  2.00002339] 5.3934767063168465e-05
respuesta de A.X=B : 
[ 0.99999292 -2.99997049  2.00002339]
iterado, incluyendo X0:  15

La gráfica muestra las coordenadas de las aproximaciones, observe el espiral que se va cerrando desde el punto inicial en verde al punto final en rojo.

Se debe controlar el número de iteraciones para verificar la convergencia con iteramax.

NO es necesario almacenar los valores de los puntos, solo el último valor y el contador itera permite determinar si el sistema converge.

# 1Eva_IIT2011_T2 Sistema de Ecuaciones, diagonal dominante
# MATG1052 Métodos Numéricos
# propuesta: edelros@espol.edu.ec,
import numpy as np

def jacobi(A,B,X0, tolera, iteramax=100, vertabla=False):
    ''' Método de Jacobi, tolerancia, vector inicial X0
        para mostrar iteraciones: vertabla=True
    '''
    A = np.array(A,dtype=float)
    B = np.array(B,dtype=float)
    X0 = np.array(X0,dtype=float)
    tamano = np.shape(A)
    n = tamano[0]
    m = tamano[1]
    diferencia = np.ones(n, dtype=float)
    errado = np.max(diferencia)
    X = np.copy(X0)
    xnuevo = np.copy(X0)
    tabla = [np.copy(X0)]

    itera = 0
    if vertabla==True:
        print('Iteraciones Jacobi')
        print('itera,[X],errado')
        print(itera, xnuevo, errado)
    while not(errado<=tolera or itera>iteramax):
        
        for i in range(0,n,1):
            nuevo = B[i]
            for j in range(0,m,1):
                if (i!=j): # excepto diagonal de A
                    nuevo = nuevo-A[i,j]*X[j]
            nuevo = nuevo/A[i,i]
            xnuevo[i] = nuevo
        diferencia = np.abs(xnuevo-X)
        errado = np.max(diferencia)
        X = np.copy(xnuevo)
        
        tabla = np.concatenate((tabla,[X]),axis = 0)

        itera = itera + 1
        if vertabla==True:
            print(itera, xnuevo, errado)

    # No converge
    if (itera>iteramax):
        X=itera
        print('iteramax superado, No converge')
    return(X,tabla)

def pivoteafila(A,B,vertabla=False):
    '''
    Pivotea parcial por filas, entrega matriz aumentada AB
    Si hay ceros en diagonal es matriz singular,
    Tarea: Revisar si diagonal tiene ceros
    '''
    A = np.array(A,dtype=float)
    B = np.array(B,dtype=float)
    # Matriz aumentada
    nB = len(np.shape(B))
    if nB == 1:
        B = np.transpose([B])
    AB  = np.concatenate((A,B),axis=1)
    
    if vertabla==True:
        print('Matriz aumentada')
        print(AB)
        print('Pivoteo parcial:')
    
    # Pivoteo por filas AB
    tamano = np.shape(AB)
    n = tamano[0]
    m = tamano[1]
    
    # Para cada fila en AB
    pivoteado = 0
    for i in range(0,n-1,1):
        # columna desde diagonal i en adelante
        columna = np.abs(AB[i:,i])
        dondemax = np.argmax(columna)
        
        # dondemax no es en diagonal
        if (dondemax != 0):
            # intercambia filas
            temporal = np.copy(AB[i,:])
            AB[i,:] = AB[dondemax+i,:]
            AB[dondemax+i,:] = temporal

            pivoteado = pivoteado + 1
            if vertabla==True:
                print(' ',pivoteado, 'intercambiar filas: ',i,'y', dondemax+i)
    if vertabla==True:
        if pivoteado==0:
            print('  Pivoteo por filas NO requerido')
        else:
            print('AB')
    return(AB)

# PROGRAMA Búsqueda de solucion
# INGRESO --------

# INGRESO
A = [[-2, 5, 9],
     [ 7, 1, 1],
     [-3, 7,-1]]

B = [1, 6,-26]

X0 = [0, 0,  0]
tolera = 0.0001
iteramax = 100

# PROCEDIMIENTO --------
AB = pivoteafila(A,B,vertabla=True)
# separa matriz aumentada en A y B
[n,m] = np.shape(AB)
A = AB[:,:m-1]
B = AB[:,m-1]

[X, puntos] = jacobi(A,B,X0,tolera,vertabla=True)
iterado = len(puntos)
# SALIDA --------
print('respuesta de A.X=B : ')
print(X)
print('iterado, incluyendo X0: ', iterado)

# GRAFICA DE ITERACIONES
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

figura = plt.figure() # Una hoja para dibujar
grafica = figura.add_subplot(111,projection = '3d')

# Puntos de la iteración
pxi = puntos[:,0]
pyi = puntos[:,1]
pzi = puntos[:,2]
grafica.plot(pxi,pyi,pzi, color = 'magenta',
             label = 'puntos[i]')
grafica.scatter(pxi[0],pyi[0],pzi[0], color = 'green', marker='o')
grafica.scatter(pxi[iterado-1],pyi[iterado-1],pzi[iterado-1],
                color = 'red', marker='o')

grafica.set_title('Puntos de iteración')
grafica.set_xlabel('eje x')
grafica.set_ylabel('eje y')
grafica.set_zlabel('eje z')
grafica.legend()
plt.show()

Gráfica de planos

Dado que el sistema de ecuaciones es de tres incógnitas, la solución se puede interpretar como la intersección de los planos formados por cada una de las ecuaciones en el espacio X,Y,Z.

Sistema Ecuaciones Diagonal Dominante 02

se comenta la última instrucción del algoritmo anterior, #plt.show(), y se añaden las siguientes líneas al algoritmo anterior para obtener la gráfica:

# Tema 2. Sistema de ecuaciones 3x3
# Concepto como interseccion de Planos
##import matplotlib.pyplot as plt
##from mpl_toolkits.mplot3d import Axes3D

ax = -5     # Intervalo X
bx = 5
ay = ax-2   # Intervalo Y
by = bx+2

muestras = 11

# PROCEDIMIENTO --------
# Ecuaciones de planos
z0 = lambda x,y: (-A[0,0]*x - A[0,1]*y + B[0])/A[0,2]
z1 = lambda x,y: (-A[1,0]*x - A[1,1]*y + B[1])/A[1,2]
z2 = lambda x,y: (-A[2,0]*x - A[2,1]*y + B[2])/A[2,2]

xi = np.linspace(ax,bx, muestras)
yi = np.linspace(ay,by, muestras)
Xi, Yi = np.meshgrid(xi,yi)

Z0 = z0(Xi,Yi)
Z1 = z1(Xi,Yi)
Z2 = z2(Xi,Yi)

# solución al sistema
punto = np.linalg.solve(A,B)

# SALIDA
print('respuesta de A.X=B : ')
print(punto)

# Interseccion entre ecuación 1 y 2
# PlanoXZ, extremo inferior de y
Aa  = np.copy(A[0:2,[0,2]])
Ba  = np.copy(B[0:2])
Ba  = Ba-ay*A[0:2,1]
pta = np.linalg.solve(Aa,Ba)
pa  = np.array([ay])
pxza = np.array([pta[0],ay,pta[1]])

# PlanoXZ, extremo superior de y
Bb  = np.copy(B[0:2])
Bb  = Bb-by*A[0:2,1]
ptb = np.linalg.solve(Aa,Bb)
pb  = np.array([by])
pxzb = np.array([ptb[0],by,ptb[1]])

# GRAFICA de planos
fig3D = plt.figure()
graf3D = fig3D.add_subplot(111, projection='3d')

graf3D.plot_wireframe(Xi,Yi,Z0,
                       color ='blue',
                       label='Z1')
graf3D.plot_wireframe(Xi,Yi,Z1,
                       color ='green',
                       label='Z2')
graf3D.plot_wireframe(Xi,Yi,Z2,
                       color ='orange',
                       label='Z3')
# recta intersección planos 1 y 2
graf3D.plot([pxza[0],pxzb[0]],
            [pxza[1],pxzb[1]],
            [pxza[2],pxzb[2]],
            label='Sol 1y2',
            color = 'violet',
            linewidth = 4)
# Punto solución del sistema 3x3
graf3D.scatter(punto[0],punto[1],punto[2],
                color = 'red',
                marker='o',
                label ='punto',
                linewidth = 6)

graf3D.set_title('Sistema de ecuaciones 3x3')
graf3D.set_xlabel('x')
graf3D.set_ylabel('y')
graf3D.set_zlabel('z')
graf3D.set_xlim(ax, bx)
graf3D.set_xlim(ay, by)
graf3D.legend()
graf3D.view_init(45, 45)
# rotacion de ejes
for angulo in range(45, 360+45, 5 ):
    graf3D.view_init(45, angulo)
    plt.draw()
    plt.pause(.001)
plt.show()


Tarea: Realice las modificaciones necesarias para usar el algoritmo de Gauss-Seidel. Luego compare resultados.


Revisión de resultados

Si se usan las ecuaciones sin pivorear y cambiar a diagonal dominante, como fueron presentadas en el enunciado, el algoritmo Jacobi NO converge, el error aumenta, y muy rápido como para observar la espiral hacia afuera en una gráfica.

Xi, errado
[ -0.5   6.   26. ] 26.0
[ 131.5  -16.5   69.5] 132.0
[ 271. -984. -484.] 967.5
[-4638.5 -1407.  -7675. ] 7191.0
[-38055.5  40150.5   4092.5] 41557.5
[ 118792.  262302.  395246.] 391153.5
[ 2434361.5 -1226784.   1479764. ] 2315569.5
[  3591977.5 -18520288.5 -15890546.5] 17370310.5
....

s1Eva_IT2011_T3_MN Precios unitarios en factura, k

Ejercicio: 1Eva_IT2011_T3_MN Precios unitarios en factura, k

Las ecuaciones basadas en las sumas de cantidad.preciounitario representan el valor pagado en cada factura.

Siendo Xi el precio unitario de cada material:

2x_1 + 5x_2 + 4x_3 = 35 3x_1 + 9x_2 + 8x_3 = k 5x_1 + 3x_2 + x_3 = 17

se escriben en la forma matricial Ax=B

\begin{bmatrix} 2 && 5 && 4 \\ 3 && 9 && 8 \\ 5 && 3 && 1 \end{bmatrix}.\begin{bmatrix} x_1 \\ x_2 \\ x_3 \end{bmatrix}=\begin{bmatrix} 35 \\ k \\ 17 \end{bmatrix}

luego se escribe la matriz aumentada:

\begin{bmatrix} 2 && 5 && 4 && 35\\ 3 && 9 && 8 && k\\ 5 && 3 && 1 && 17\end{bmatrix}

se pivotea por filas buscando tener una matriz diagonal dominante,

\begin{bmatrix} 5 && 3 && 1 && 17 \\ 3 && 9 && 8 && k\\ 2 && 5 && 4 && 35\\\end{bmatrix}

Luego se usa el procedimiento de eliminación hacia adelante,

\begin{bmatrix} 5 && 3 && 1 && 17 \\ 3-5\frac{3}{5} && 9-3\frac{3}{5} && 8-1\frac{3}{5} && k-17\frac{3}{5} \\ 2-5\frac{2}{5} && 5-3\frac{2}{5} && 4-1\frac{2}{5} && 35-17\frac{2}{5} \end{bmatrix} \begin{bmatrix} 5 && 3 && 1 && 17 \\ 0 && \frac{36}{5} && \frac{37}{5} && k-\frac{51}{5} \\ 0 && \frac{19}{5} && \frac{18}{5} && \frac{141}{5} \end{bmatrix} \begin{bmatrix} 5 && 3 && 1 && 17 \\ 0 && 36 && 37 && 5k-51 \\ 0 && 19 && 18 && 141 \end{bmatrix} \begin{bmatrix} 5 && 3 && 1 && 17 \\ 0 && 36 && 37 && 5k-51 \\ 0 && 19-36\frac{19}{36} && 18-37\frac{19}{36} && 141-(5k-51)\frac{19}{36} \end{bmatrix} \begin{bmatrix} 5 && 3 && 1 && 17 \\ 0 && 36 && 37 && 5k-51 \\ 0 && 0 && \frac{-55}{36} && \frac{6045-5k}{36} \end{bmatrix}

multiplicando la última fila por 36,

\begin{bmatrix} 5 && 3 && 1 && 17 \\ 0 && 36 && 37 && 5k-51 \\ 0 && 0 && -55 && 6045-5k \end{bmatrix}

con lo que se pueden obtener cada precio unitario en función de k.
Como variante, se continua siguiendo el procedimieno de Gauss, dejando como tarea el uso de Gauss-Jordan

-55x_3 = 6045-5k x_3 = -\frac{6045-5k}{55} 36 x_2 + 37 x_3 = 5k-51 x_2 = \frac{1}{36}(5k-51 - 37 x_3) x_2 = \frac{1}{36} \Big( 5k-51 - 37 \big(-\frac{6045-5k}{55}\big) \Big) 5x_1 + 3 x_2 +x_3 = 17 x_1 = \frac{1}{5} \Big[ 17 - 3 x_2 - x_3 \Big] x_1 = \frac{1}{5} \Big[17-3\frac{1}{36} \Big( 5k-21 - 37 \big(-\frac{6045-5k}{55}\big) \Big) - \Big( -\frac{6045-5k}{55} \Big) \Big]

para luego simplificar las expresiones (tarea).

En el literal c se indica que el valor de k es 65, con lo que se requiere sustituir en la solución el valor de K para encontrar los precios unitarios.

\begin{bmatrix} 5 && 3 && 1 && 17 \\ 3 && 9 && 8 && 65\\ 2 && 5 && 4 && 35\\\end{bmatrix}

Se encuentra que:

el vector solución X es:

[[-0.18181818]
 [ 5.18181818]
 [ 2.36363636]]

Lo que muestra que debe existir un error en el planteamiento del enunciado, considerando que los precios NO deberían ser negativos como sucede con el primer precio unitario de la respuesta.

que es lo que suponemos ser trata de corregir en el literal d, al indicar que se cambie en la matriz el valor de 5 por 5.1. Los resultados en éste caso son más coherentes con el enunciado. Todas las soluciones son positivas.

A = np.array([[ 5.1, 3  , 1],
              [ 3. , 9  , 8],
              [ 2. , 5.1, 4]])
B1 = np.array([ 17, 65, 35])

el vector solución X es:
[[0.33596838]
 [3.88669302]
 [3.62648221]]

El error relativo de los precios encontrados entre las ecuaciones planteadas es:

diferencia = [0.335968-0.181818,
              3.886693-5.181818, 
              3.626482-2.363636]
           = [0.154150, -1.295125, 1.262845]
error(dolares) = max|diferencia| = 1.295125
Por las magnitudes de los precios, el error se aprecia
usando el error relativo referenciado 
al mayor valor de la nueva solución
error relativo = 1.295125/3.886693 = 0.333220
es decir de aproximadamente 33%

Para revisar otra causa del error se analiza el número de condición de la matriz:

>>> A
array([[5.1, 3. , 1. ],
       [3. , 9. , 8. ],
       [2. , 5.1, 4. ]])
>>> np.linalg.cond(A)
60.28297696795716

El número de condición resulta lejano a 1, por lo que para éste problema:
pequeños cambios en la matriz de entrada producen grandes cambios en los resultados.

por ejemplo: un 0.1/5= 0.02 que es un 2% de variación en la entrada produce un cambio del 33% en el resultado.

Algoritmo en Python

Resultados del algoritmo

Matriz aumentada
[[ 2.  5.  4. 35.]
 [ 3.  9.  8. 65.]
 [ 5.  3.  1. 17.]]
Pivoteo parcial:
  1 intercambiar filas:  0 y 2
[[ 5.  3.  1. 17.]
 [ 3.  9.  8. 65.]
 [ 2.  5.  4. 35.]]
Elimina hacia adelante:
 fila 0 pivote:  5.0
   factor:  0.6  para fila:  1
   factor:  0.4  para fila:  2
 fila 1 pivote:  7.2
   factor:  0.5277777777777778  para fila:  2
 fila 2 pivote:  -0.3055555555555558
[[ 5.00000000e+00  3.00000000e+00  1.00000000e+00  1.70000000e+01]
 [ 0.00000000e+00  7.20000000e+00  7.40000000e+00  5.48000000e+01]
 [ 0.00000000e+00 -4.44089210e-16 -3.05555556e-01 -7.22222222e-01]]
Elimina hacia Atras:
 fila 2 pivote:  -0.3055555555555558
   factor:  -24.2181818181818  para fila:  1
   factor:  -3.2727272727272703  para fila:  0
 fila 1 pivote:  7.1999999999999895
   factor:  0.4166666666666671  para fila:  0
 fila 0 pivote:  5.0
[[ 1.00000000e+00  0.00000000e+00  0.00000000e+00 -1.81818182e-01]
 [ 0.00000000e+00  1.00000000e+00  0.00000000e+00  5.18181818e+00]
 [-0.00000000e+00  1.45338287e-15  1.00000000e+00  2.36363636e+00]]
solución X: 
[-0.18181818  5.18181818  2.36363636]
>>>

Instrucciones en Python

# 1Eva_IT2011_T3_MN Precios unitarios en factura, k
# Método de Gauss-Jordan
# Solución a Sistemas de Ecuaciones
# de la forma A.X=B

import numpy as np

def pivoteafila(A,B,vertabla=False):
    '''
    Pivotea parcial por filas
    Si hay ceros en diagonal es matriz singular,
    Tarea: Revisar si diagonal tiene ceros
    '''
    A = np.array(A,dtype=float)
    B = np.array(B,dtype=float)
    # Matriz aumentada
    nB = len(np.shape(B))
    if nB == 1:
        B = np.transpose([B])
    AB  = np.concatenate((A,B),axis=1)
    
    if vertabla==True:
        print('Matriz aumentada')
        print(AB)
        print('Pivoteo parcial:')
    
    # Pivoteo por filas AB
    tamano = np.shape(AB)
    n = tamano[0]
    m = tamano[1]
    
    # Para cada fila en AB
    pivoteado = 0
    for i in range(0,n-1,1):
        # columna desde diagonal i en adelante
        columna = np.abs(AB[i:,i])
        dondemax = np.argmax(columna)
        
        # dondemax no es en diagonal
        if (dondemax != 0):
            # intercambia filas
            temporal = np.copy(AB[i,:])
            AB[i,:] = AB[dondemax+i,:]
            AB[dondemax+i,:] = temporal

            pivoteado = pivoteado + 1
            if vertabla==True:
                print(' ',pivoteado, 'intercambiar filas: ',i,'y', dondemax+i)
    if vertabla==True:
        if pivoteado==0:
            print('  Pivoteo por filas NO requerido')
        else:
            print(AB)
    return(AB)

def gauss_eliminaAdelante(AB, vertabla=False,lu=False,casicero = 1e-15):
    ''' Gauss elimina hacia adelante, a partir de,
    matriz aumentada y pivoteada.
    Para respuesta en forma A=L.U usar lu=True entrega[AB,L,U]
    '''
    tamano = np.shape(AB)
    n = tamano[0]
    m = tamano[1]
    L = np.identity(n,dtype=float) # Inicializa L
    if vertabla==True:
        print('Elimina hacia adelante:')
    for i in range(0,n,1):
        pivote = AB[i,i]
        adelante = i+1
        if vertabla==True:
            print(' fila',i,'pivote: ', pivote)
        for k in range(adelante,n,1):
            if (np.abs(pivote)>=casicero):
                factor = AB[k,i]/pivote
                AB[k,:] = AB[k,:] - factor*AB[i,:]

                L[k,i] = factor # llena L
                
                if vertabla==True:
                    print('   factor: ',factor,' para fila: ',k)
            else:
                print('  pivote:', pivote,'en fila:',i,
                      'genera division para cero')
    respuesta = AB
    if vertabla==True:
        print(AB)
    if lu==True:
        U = AB[:,:n-1]
        respuesta = [AB,L,U]
    return(respuesta)

def gauss_eliminaAtras(AB, vertabla=False, precision=5, casicero = 1e-15):
    ''' Gauss-Jordan elimina hacia atras
    Requiere la matriz triangular inferior
    Tarea: Verificar que sea triangular inferior
    '''
    tamano = np.shape(AB)
    n = tamano[0]
    m = tamano[1]
    
    ultfila = n-1
    ultcolumna = m-1
    if vertabla==True:
        print('Elimina hacia Atras:')
        
    for i in range(ultfila,0-1,-1):
        pivote = AB[i,i]
        atras = i-1  # arriba de la fila i
        if vertabla==True:
            print(' fila',i,'pivote: ', pivote)
            
        for k in range(atras,0-1,-1):
            if (np.abs(AB[k,i])>=casicero):
                factor = AB[k,i]/pivote
                AB[k,:] = AB[k,:] - factor*AB[i,:]
                
                if vertabla==True:
                    print('   factor: ',factor,' para fila: ',k)
            else:
                print('  pivote:', pivote,'en fila:',i,
                      'genera division para cero')
 
        AB[i,:] = AB[i,:]/AB[i,i] # diagonal a unos
    X = np.copy(AB[:,ultcolumna])
    
    if vertabla==True:
        print(AB)
    return(X)

# PROGRAMA ------------------------
# INGRESO
A = np.array([[2,5,4],
              [3,9,8],
              [5,3,1]])

B = np.array([[35],
              [65],
              [17]])

# PROCEDIMIENTO
AB = pivoteafila(A,B,vertabla=True)

AB = gauss_eliminaAdelante(AB,vertabla=True)

X = gauss_eliminaAtras(AB,vertabla=True)

# SALIDA
print('solución X: ')
print(X)

 

s1Eva_IT2011_T1_MN Fondo de inversión

Ejercicio: 1Eva_IT2011_T1_MN Fondo de inversión

Planteamiento

Siendo C(t), considerando A como un millón, A=1

C(t)=Ate^{-t/3}

Se observa la gráfica de la función que muestra el valor máximo en el intervalo entre [2, 5] , alrededor de  3

Para encontrar el valor del máximo, se requiere usar la derivada respecto al tiempo y encontrar el cruce por cero.

\frac{dC}{dt} = -t e^{-t/3} +e^{-t/3}

Adicionalmente, para el literal b en la gráfica se incluye como meta donde C(t) disminuye a 1/4 o 0.25. Lo que estaría en el intervalo entre [10, 14].

Instrucciones en Python para observar la función:

# 1ra Evaluación I Término 2011
# Tema 1. Fondo de Inversion
import numpy as np
import matplotlib.pyplot as plt

ft = lambda t: t*np.exp(-t/3)

a=0
b=20
tolera = 0.0001
muestras = 101
meta = 0.25
# PROCEDIMIENTO
# Observar la función entre [a,b]
ti = np.linspace(a,b,muestras)
fti = ft(ti)

# Salida
# Gráfica
plt.plot(ti,fti, label='f(t)')
plt.axhline(meta, color = 'r')
plt.axhline(0, color = 'k')
plt.legend()
plt.show()

literal a

Para encontrar el máximo se puede determinar la derivada con Sympy.

Para la derivada se usa la forma simbólica de la función, que se convierte a forma numérica lambda para evaluarla de forma más fácil y obtener la gráfica.

# Literal a) usando derivada simbólica
import sympy as sp
x = sp.Symbol('x')
fxs = x*sp.exp(-x/3)
dfxs = fxs.diff(x,1)

# convierte la expresión a lambda
dfxn = sp.utilities.lambdify(x,dfxs,'numpy')
dfxni = dfxn(ti)
print('derivada de la función: ')
print(dfxs)
# Gráfica de la derivada.
plt.plot(ti,dfxni, label='df(t)/dt')
plt.axhline(0, color = 'k')
plt.legend()
plt.show()

derivada de la función: 
-x*exp(-x/3)/3 + exp(-x/3)

Se busca la raíz con algún método, por ejemplo bisección, siendo f(x) = 0

f(t) = \frac{dC}{dt} = -t e^{-t/3} +e^{-t/3}

Desarrollo analítico

itera = 0, a = 2, b= 5

c = \frac{a+b}{2} =\frac{2+5}{2}=3.5 f(2) = -2 e^{-2/3} +e^{-2/3} =0.1711 f(3.5) = -5 e^{-3.5/3} +e^{-3.5/3} = -0.0519 f(5) = -5 e^{-5/3} +e^{-5/3} = -0.1259

cambio de signo del lado izquierdo

a = 2, b = 3.5

error = | 3.5-2 | = 1.5

itera = 1, a = 2, b = 3.5

c = \frac{2+3.5}{2}=2.75 f(2.75) = -2.75 e^{-2.75/3} +e^{-2.75/3} = 0.0333

cambio de signo del lado derecho

a = 2.75, b = 3.5

error = | 3.5-2.75 | = 0.75

itera = 2, a = 2.75, b = 3.5

c = \frac{2.75+3.5}{2}=3.125 f(3.125) = -3.125 e^{-3.125/3} +e^{-3.125/3} = -0.0147

cambio de signo del lado izquierdo

a = 2.75, b = 3.1255

error = | 3.12555-2.75 | = 0.375

y se continúa hasta alcanzar la tolerancia dada para el ejercicio.

Usando el algoritmo se encuentra luego de 14 iteraciones:

método de Bisección
i ['a', 'c', 'b'] ['f(a)', 'f(c)', 'f(b)']
   tramo
0 [2.  3.5 5. ] [ 0.1711 -0.0519 -0.1259]
   1.5
1 [2.   2.75 3.5 ] [ 0.1711  0.0333 -0.0519]
   0.75
2 [2.75  3.125 3.5  ] [ 0.0333 -0.0147 -0.0519]
   0.375
3 [2.75   2.9375 3.125 ] [ 0.0333  0.0078 -0.0147]
   0.1875
4 [2.9375 3.0312 3.125 ] [ 0.0078 -0.0038 -0.0147]
   0.09375
5 [2.9375 2.9844 3.0312] [ 0.0078  0.0019 -0.0038]
   0.046875
6 [2.9844 3.0078 3.0312] [ 0.0019 -0.001  -0.0038]
   0.0234375
7 [2.9844 2.9961 3.0078] [ 0.0019  0.0005 -0.001 ]
   0.01171875
8 [2.9961 3.002  3.0078] [ 0.0005 -0.0002 -0.001 ]
   0.005859375
9 [2.9961 2.999  3.002 ] [ 0.0005  0.0001 -0.0002]
   0.0029296875
10 [2.999  3.0005 3.002 ] [ 1.1979e-04 -5.9866e-05 -2.3935e-04]
   0.00146484375
11 [2.999  2.9998 3.0005] [ 1.1979e-04  2.9941e-05 -5.9866e-05]
   0.000732421875
12 [2.9998 3.0001 3.0005] [ 2.9941e-05 -1.4968e-05 -5.9866e-05]
   0.0003662109375
13 [2.9998 2.9999 3.0001] [ 2.9941e-05  7.4847e-06 -1.4968e-05]
   0.00018310546875
14 [2.9999 3.     3.0001] [ 7.4847e-06 -3.7422e-06 -1.4968e-05]
   9.1552734375e-05
raíz en:  3.000030517578125

Instrucciones en Python

# 1Eva_IT2011_T1_MN Fondo de Inversión
# Algoritmo de Bisección
# [a,b] se escogen de la gráfica de la función
# error = tolera
import numpy as np

def biseccion(fx,a,b,tolera,iteramax = 20, vertabla=False, precision=4):
    '''
    Algoritmo de Bisección
    Los valores de [a,b] son seleccionados
    desde la gráfica de la función
    error = tolera
    '''
    fa = fx(a)
    fb = fx(b)
    tramo = np.abs(b-a)
    itera = 0
    cambia = np.sign(fa)*np.sign(fb)
    if cambia<0: # existe cambio de signo f(a) vs f(b)
        if vertabla==True:
            print('método de Bisección')
            print('i', ['a','c','b'],[ 'f(a)', 'f(c)','f(b)'])
            print('  ','tramo')
            np.set_printoptions(precision)
            
        while (tramo>=tolera and itera<=iteramax):
            c = (a+b)/2
            fc = fx(c)
            cambia = np.sign(fa)*np.sign(fc)
            if vertabla==True:
                print(itera,np.array([a,c,b]),np.array([fa,fc,fb]))
            if (cambia<0):
                b = c
                fb = fc
            else:
                a = c
                fa = fc
            tramo = np.abs(b-a)
            if vertabla==True:
                print('  ',tramo)
            itera = itera + 1
        respuesta = c
        # Valida respuesta
        if (itera>=iteramax):
            respuesta = np.nan

    else: 
        print(' No existe cambio de signo entre f(a) y f(b)')
        print(' f(a) =',fa,',  f(b) =',fb) 
        respuesta=np.nan
    return(respuesta)

# INGRESO
fx  = lambda t: -t*np.exp(-t/3)/3 + np.exp(-t/3)
a = 2
b = 5
tolera = 0.0001

# PROCEDIMIENTO
respuesta = biseccion(fx,a,b,tolera,vertabla=True)
# SALIDA
print('raíz en: ', respuesta)

Determine el monto de la inversión inicial A necesaria para que el máximo sea igual a un millón de dólares. Como el máximo se encuentra en t=3, se tiene que:

C(t)=Ate^{-t/3} 1=A(3)e^{-3/3} A=\frac{1}{(3)e^{-1}} = 0.906093

considerando que las unidades se encuentran en millones.


literal b

Para el literal b, se busca la raíz usando el método de Newton-Raphson como se indica en el enunciado.
En la función nueva se usa el valor de A encontrado, y la meta establecida.
Se obtiene la misa derivada del problema anterior multiplicada por A, por ser solo un factor que multiplica a la función original. El valor de meta es una constante, que se convierte en cero al derivar.

resultado con el algoritmo:

['xi', 'xnuevo', 'tramo']
[[1.0000e+01 1.0880e+01 8.7987e-01]
 [1.0880e+01 1.1056e+01 1.7580e-01]
 [1.1056e+01 1.1076e+01 2.0098e-02]
 [1.1076e+01 1.1078e+01 1.9337e-03]
 [1.1078e+01 1.1078e+01 1.8202e-04]]
raiz en:  11.077880437153812
con error de:  0.00018201925869298918
>>>

Instrucciones en Python

# 1Eva_IT2011_T1_MN Fondo de Inversión 
# Método de Newton-Raphson
# Ejemplo 1 (Burden ejemplo 1 p.51/pdf.61)

import numpy as np

# INGRESO
fx  = lambda t: 0.906093*t*np.exp(-t/3) - 0.25
dfx = lambda t: -t*np.exp(-t/3)/3 + np.exp(-t/3)

x0 = 10
tolera = 0.001

# PROCEDIMIENTO
tabla = []
tramo = abs(2*tolera)
xi = x0
while (tramo>=tolera):
    xnuevo = xi - fx(xi)/dfx(xi)
    tramo  = abs(xnuevo-xi)
    tabla.append([xi,xnuevo,tramo])
    xi = xnuevo

# convierte la lista a un arreglo.
tabla = np.array(tabla)
n = len(tabla)

# SALIDA
print(['xi', 'xnuevo', 'tramo'])
np.set_printoptions(precision = 4)
print(tabla)
print('raiz en: ', xi)
print('con error de: ',tramo)

el valor de t para la meta es: 11.0779035867

s1Eva_IT2011_T1 Encontrar α en integral

Ejercicio: 1Eva_IT2011_T1 Encontrar α en integral

Desarrollo Analítico

Se iguala la ecuación al valor buscado = 10, y se resuelve

\int_{\alpha}^{2\alpha} x e^{x}dx = 10

siendo: μ = x , δv = ex, δu = δx , v = ex

\int u dv = uv - \int v \delta u xe^x \Big|_{\alpha}^{2 \alpha} - \int_{\alpha}^{2\alpha} e^{x}dx - 10 = 0 2\alpha e^{2 \alpha} -\alpha e^{\alpha} - (e^{2\alpha} - e^{\alpha}) - 10 = 0 (2\alpha-1)e^{2 \alpha}+ (1-\alpha) e^{\alpha} - 10 = 0

la función a usar en el método es

f(\alpha) = (2\alpha-1)e^{2 \alpha}+ (1-\alpha)e^{\alpha} -10

Se obtiene la derivada para el método de Newton Raphson

f'(\alpha) = 2e^{2 \alpha} + 2(2\alpha-1)e^{2 \alpha} - e^{\alpha} + (1-\alpha) e^{\alpha} f'(\alpha) = (2 + 2(2\alpha-1))e^{2 \alpha} +(-1 + (1-\alpha)) e^{\alpha} f'(\alpha) = 4\alpha e^{2 \alpha} -\alpha e^{\alpha}

la fórmula para el método de Newton-Raphson

\alpha_{i+1} = \alpha_i - \frac{f(\alpha)}{f'(\alpha)}

se prueba con α0 = 1, se evita el valor de cero por la indeterminación que se da por f'(0) = 0

iteración 1:

f(1) = (2(1)-1)e^{2(1)}+ (1-(1))e^{(1)} -10 f'(1) = 4(1) e^{2 (1)} -(1) e^{(1)} \alpha_{1} = 1- \frac{f(1)}{f'(1)}

\alpha_{1} = 1.0973
error = 0.0973

iteración 2:
f(2) = (2(1.0973)-1)e^{2(1.0973)}+ (1-(1.0973))e^{(1.0973)} -10

f'(2) = 4(1.0973) e^{2 (1.0973)} -(1.0973) e^{(1.0973)} \alpha_{2} = 1.0973 - \frac{f(1.0973)}{f'(1.0973)}

\alpha_{2} = 1.0853
error = 0.011941

iteración 3:
f(3) = (2(1.0853)-1)e^{2(1.0853)}+ (1-(1.0853))e^{(1.0853)} -10

f'(3) = 4(1.0853) e^{2 (1.0853)} -(1.0853) e^{(1.0853)} \alpha_{3} = 1.0853- \frac{f(1.0853)}{f'(1.0853)}

\alpha_{3} = 1.0851
error = 0.00021951

[  xi,          xnuevo,      f(xi),      f'(xi),       tramo ]
[  1.           1.0973      -2.6109      26.8379       0.0973]
[  1.0973e+00   1.0853e+00   4.3118e-01   3.6110e+01   1.1941e-02]
[  1.0853e+00   1.0851e+00   7.6468e-03   3.4836e+01   2.1951e-04]
[  1.0851e+00   1.0851e+00   2.5287e-06   3.4813e+01   7.2637e-08]
raiz:  1.08512526549

se obtiene el valor de la raíz con 4 iteraciones, con error de aproximación de 7.2637e-08

Desarrollo con Python