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 1 | Material 2 | Material 3 | |
|---|---|---|---|
| Componente 1 | 5 x0 | 9 x0 | 3 x0 |
| Componente 2 | 7 x1 | 7 x1 | 16 x1 |
| Componente 3 | 9 x2 | 3 x2 | 4 x2 |
| Total | 945 | 987 | 1049 |
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:
