s1Eva2017TI_T4 Componentes eléctricos

Ejercicio: 1Eva2017TI_T4 Componentes eléctricos

Desarrollo Analítico

Solo puede usar las cantidades disponibles de material indicadas, por lo que las cantidades desconocidas de producción por componente se convierten en las incógnitas x0, x1, x2. Se usa el índice cero por compatibilidad con las instrucciones Python.

Material 1Material 2Material 3
Componente 15 x09 x03 x0
Componente 27 x17 x116 x1
Componente 39 x23 x24 x2
Total9459871049

Se plantean las fórmulas a resolver:

5 x0 +  7 x1 + 9 x2 = 945
9 x0 +  7 x1 + 3 x2 = 987
3 x0 + 16 x1 + 4 x2 = 1049

Se reescriben en la forma matricial AX=B

\begin{bmatrix} 5 & 7 & 9\\ 9 & 7 & 3 \\ 3 & 16 & 4 \end{bmatrix} \begin{bmatrix} x_0 \\ x_1 \\ x_2 \end{bmatrix}= \begin{bmatrix} 945 \\ 987 \\ 1049 \end{bmatrix}

Se reordena, pivoteando por filas para tener la matriz diagonalmente dominante:

\begin{bmatrix} 9 & 7 & 3\\ 3 & 16 & 4 \\ 5 & 7 & 9 \end{bmatrix} \begin{bmatrix} x_0 \\ x_1 \\ x_2 \end{bmatrix}= \begin{bmatrix} 987 \\ 1049 \\ 945 \end{bmatrix}

Se determina el número de condición de la matriz, por facilidad con Python:

numero de condicion: 4.396316324708121

Obtenido con:

# 1Eva_IT2017_T4 Componentes eléctricos
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
A = [[9, 7,3],
     [3,16,4],
     [5, 7,9]]

B = [987,1049,945]

# PROCEDIMIENTO
A = np.array(A,dtype=float)
B = np.array(B,dtype=float)

# numero de condicion
ncond = np.linalg.cond(A)

# SALIDA
print('numero de condicion:', ncond)

Recordando que la matriz debe ser tipo real, se añade un punto a los dígitos.

El número de condición es cercano a 1, por lo que el sistema si debería converger a la solución.

Desarrollo con Python

La forma AX=B permite usar los algoritmos desarrollados, obteniendo la solución. Se verifica el resultado al realizar la multiplicación de A con el vector respuesta, debe ser el vector B con un error menor al tolerado.

Matriz aumentada
[[   9.    7.    3.  987.]
 [   3.   16.    4. 1049.]
 [   5.    7.    9.  945.]]
Pivoteo parcial:
  Pivoteo por filas NO requerido
Iteraciones Jacobi
itera,[X]
     ,errado,|diferencia|
0 [0. 0. 0.]
  nan
1 [109.66667  65.5625  105.     ]
  109.66666666666667 [109.66667  65.5625  105.     ]
2 [23.67361 18.75    -6.91898]
  111.91898148148148 [ 85.99306  46.8125  111.91898]
3 [97.38966 62.85344 77.26466]
  84.18364197530865 [73.71605 44.10344 84.18364]
4 [35.02577 27.98577  2.00862]
  75.2560388803155 [62.36389 34.86767 75.25604]
...
83 [63.00004 45.00002 35.00005]
  0.00010522690335079687 [8.85109e-05 5.08730e-05 1.05227e-04]
84 [62.99997 44.99998 34.99996]
  8.874058288199649e-05 [7.46435e-05 4.29025e-05 8.87406e-05]
Metodo de Jacobi
numero de condición: 4.396316324708121
X:  [62.99997 44.99998 34.99996]
errado: 8.874058288199649e-05
iteraciones: 84

Si interpreta el resultado, se debe obtener solo la parte entera [63,45,35] pues las unidades producidas son números enteros.

Algoritmo en Python:

# 1Eva_IT2017_T4 Componentes eléctricos
# Metodo de Jacobi para sistemas de ecuaciones
import numpy as np
 
def jacobi(A,B,X0, tolera, iteramax=100,
           vertabla=False, precision=4):
    ''' Método de Jacobi, tolerancia, vector inicial X0
        para mostrar iteraciones y tabla: vertabla=True
    '''
    # Matrices como arreglo, numeros reales
    A = np.array(A,dtype=float)
    B = np.array(B,dtype=float)
    X0 = np.array(X0,dtype=float)
    tamano = np.shape(A) # tamaño A
    n = tamano[0]
    m = tamano[1]
     
    # valores iniciales
    diferencia = 2*tolera*np.ones(n, dtype=float)
    errado = 2*tolera     # np.max(diferencia)
    tabla = [np.copy(X0)] # tabla de iteraciones
    tabla = np.concatenate((tabla,[[np.nan]]),
                            axis=1) # errado
 
    if vertabla==True:
        print('Iteraciones Jacobi')
        print('itera,[X]')
        print('     ,errado,|diferencia|')
        print(0,X0)
        print(' ',np.nan)
        np.set_printoptions(precision)
 
    itera = 0 # Jacobi
    X = np.copy(X0)
    Xnuevo = np.copy(X0)
    while errado>tolera and itera<=iteramax:
         
        for i in range(0,n,1): # una ecuacion
            suma = B[i]
            for j in range(0,m,1): # un coeficiente
                if (i!=j): # excepto diagonal de A
                    suma = suma-A[i,j]*X[j]
            Xnuevo[i] = suma/A[i,i]
        diferencia = abs(Xnuevo-X)
        errado = np.max(diferencia)
        X = np.copy(Xnuevo)
 
        Xfila = np.concatenate((Xnuevo,[errado]),axis=0)
        tabla = np.concatenate((tabla,[Xfila]),axis=0)
 
        itera = itera + 1
 
        if vertabla==True:
            print(itera, Xnuevo)
            print(' ',errado,diferencia)
 
    # No converge
    if (itera>iteramax):
        X = np.nan
        print('No converge,iteramax superado')
 
    if vertabla==True:
        X = [X,tabla]
    return(X)
 
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')
            print(AB)
    return(AB)
 
# PROGRAMA Búsqueda de solucion  --------
# INGRESO
A = [[9, 7,3],
     [3,16,4],
     [5, 7,9]]

B = [987,1049,945]
 
X0 = [0,0,0]
tolera = 0.0001
iteramax = 100
verdecimal = 5
 
# PROCEDIMIENTO
AB = pivoteafila(A,B,vertabla=True)
n,m = np.shape(AB)
A = AB[:,:n] # separa en A y B
B = AB[:,n]
 
[X, tabla] = jacobi(A,B,X0,tolera,iteramax,
                    vertabla=True,
                    precision=verdecimal)
n_itera = len(tabla)-1
errado = tabla[-1,-1]
 
# numero de condicion
ncond = np.linalg.cond(A)
 
# SALIDA
print('Metodo de Jacobi')
print('numero de condición:', ncond)
print('X: ',X)
print('errado:',errado)
print('iteraciones:', n_itera)

# GRAFICA de iteraciones
errados = tabla[:,n]
 
import matplotlib.pyplot as plt
# grafica de error por iteracion
fig2D = plt.figure()
graf = fig2D.add_subplot(111)
graf.plot(errados)
graf.set_xlabel('itera')
graf.set_ylabel('|error|')
graf.set_title('Método de Jacobi: error[itera]')
graf.grid()
 
plt.show()

al ejecutar el algoritmo se determina que se requieren 83 iteraciones para cumplir con con el valor de error tolerado.

La gráfica de errores por iteración muestra que es convergente:

1Eva2017TI_T4 Componentes Eléctricos gráfica de errores por iteración 01

Ejemplos - Ejercicios resueltos de Métodos Numéricos