In [1]:
import numpy as np
class Array:
"Una clase minima de Algebra lineal"
def __init__(self, list_of_rows):
"Constructor y validador"
# obtener dimensiones
self.data = list_of_rows
nrow = len(list_of_rows)
# ___caso vector: redimensionar correctamente
if not isinstance(list_of_rows[0], list):
nrow = 1
self.data = [[x] for x in list_of_rows]
# ahora las columnas deben estar bien aunque sea un vector
ncol = len(self.data[0])
self.shape = (nrow, ncol)
# validar tamano correcto de filas
if any([len(r) != ncol for r in self.data]):
raise Exception("Las filas deben ser del mismo tamano")
def __repr__(self):
respuesta = "["
for i in range(0,len(self.data)):
respuesta = respuesta + "["
for j in range (0,len(self.data[0])):
respuesta = respuesta + str(self.data[i][j])
if j < len(self.data[0]) - 1:
respuesta = respuesta + ","
respuesta = respuesta + "]"
if i < len(self.data) - 1:
respuesta = respuesta + ","
return respuesta + "]"
def __str__(self):
respuesta = "Array["
for i in range(0,len(self.data)):
respuesta = respuesta + "["
for j in range (0,len(self.data[0])):
respuesta = respuesta + str(self.data[i][j])
if j < len(self.data[0]) - 1:
respuesta = respuesta + ","
respuesta = respuesta + "]"
if i < len(self.data) - 1:
respuesta = respuesta + ","
return respuesta + "]"
def __getitem__(self, idx):
return self.data[idx[0]][idx[1]]
def __setitem__(self, idx, new_value):
self.data[idx[0]][idx[1]] = new_value
def zeros(self, shape):
respuesta = [[0. for i in range(0, shape[0,0])] for j in range (0, shape[1,0])]
return respuesta
def eye(self, n):
respuesta = list()
for i in range (0, n):
subrespuesta = list()
for j in range(0, n):
if j == i:
subrespuesta.append(1,)
else:
subrespuesta.append(0,)
respuesta.append(subrespuesta)
return respuesta
def transpose(self):
respuesta = list()
for i in range(0, len(self.data[0])):
subrespuesta = list()
for j in range (0, len(self.data)):
subrespuesta.append(self.data[j][i])
respuesta.append(subrespuesta)
return Array(respuesta)
def __add__(self, other):
"Hora de sumar"
if isinstance(other, Array):
if self.shape != other.shape:
raise Exception("Las dimensiones son distintas!")
rows, cols = self.shape
newArray = Array([[0. for c in range(cols)] for r in range(rows)])
for r in range(rows):
for c in range(cols):
newArray.data[r][c] = self.data[r][c] + other.data[r][c]
return newArray
elif isinstance(2, (int, float, complex)): # en caso de que el lado derecho sea solo un numero
rows, cols = self.shape
newArray = Array([[0. for c in range(cols)] for r in range(rows)])
for r in range(rows):
for c in range(cols):
newArray.data[r][c] = self.data[r][c] + other
return newArray
else:
return NotImplemented # es un tipo de error particular usado en estos metodos
def __sub__(self, other):
"Hora de restar"
if isinstance(other, Array):
if self.shape != other.shape:
raise Exception("Las dimensiones son distintas!")
rows, cols = self.shape
newArray = Array([[0. for c in range(cols)] for r in range(rows)])
for r in range(rows):
for c in range(cols):
newArray.data[r][c] = self.data[r][c] - other.data[r][c]
return newArray
elif isinstance(2, (int, float, complex)): # en caso de que el lado derecho sea solo un numero
rows, cols = self.shape
newArray = Array([[0. for c in range(cols)] for r in range(rows)])
for r in range(rows):
for c in range(cols):
newArray.data[r][c] = self.data[r][c] - other
return newArray
else:
return NotImplemented # es un tipo de error particular usado en estos metodos
def __radd__(self, other):
return self + other
def __mul__(self, other):
if isinstance(other, Array):
if self.shape[0] != other.shape[1] | self.shape[1] != other.shape[0] :
raise Exception("Las dimensiones son incorrectas!")
rows, cols = self.shape
respuestaArr = Array([[0. for c in range(rows)] for r in range(rows)])
for iN in range(rows):
for jN in range (rows):
sumatoria = 0
for m in range (cols):
sumatoria = sumatoria + self.data[iN][m] * other.data[m][jN]
respuestaArr.data[iN][jN] = sumatoria
return respuestaArr
elif isinstance(2, (int, float, complex)): # en caso de que el lado derecho sea solo un numero
rows, cols = self.shape
newArray = Array([[0. for c in range(cols)] for r in range(rows)])
for r in range(rows):
for c in range(cols):
newArray.data[r][c] = self.data[r][c] * other
return newArray
else:
return NotImplemented # es un tipo de error particular usado en estos metodos
def __rmul__(self,other):
"hacer rmul"
In [2]:
A = Array([[1,2,3], [4,5,6]])
A
Out[2]:
In [3]:
A[0,1] = 8
print(A)
In [4]:
A.zeros(Array([4,5]))
Out[4]:
In [5]:
A.eye(5)
Out[5]:
In [6]:
A.transpose()
Out[6]:
In [7]:
print(A)
In [8]:
B = Array([[2,3,4], [1,1,1]])
A + B
Out[8]:
In [9]:
B + 10
Out[9]:
In [10]:
B - 1
Out[10]:
In [11]:
1 + B
Out[11]:
In [12]:
A
Out[12]:
In [13]:
C = Array([[2,3], [1,1], [4,6]])
In [14]:
#[[14,31,24],[5,13,9],[28,62,48]]
C * A
Out[14]:
In [15]:
C * 3
Out[15]:
In [16]:
C.transpose()*C
Out[16]:
In [17]:
class Vector(Array): # declara que Vector es un tipo de Array
def __init__(self, list_of_numbers):
self.vdata = list_of_numbers
list_of_rows = [[x] for x in list_of_numbers]
return Array.__init__(self, list_of_rows)
def __repr__(self):
return "Vector(" + str(self.vdata) + ")"
def __str__(self):
return str(self.vdata)
def __add__(self, other):
new_arr = Array.__add__(self, other)
return Vector([x[0] for x in new_arr.data])
In [18]:
Vector([1,2,3]).__dict__
Out[18]:
In [19]:
def dameVectorUyValorL(arr_semilla, arr_objetivo, columna):
valor_L = arr_objetivo.data[0][columna] / arr_semilla.data[0][columna]
fila_U = arr_objetivo - (arr_semilla * valor_L)
return valor_L, fila_U
In [20]:
#A = Array([[25, 5, 1],[64, 8, 1],[144, 12, 1]])
A = Array([[1, 1, -1],[0, 1, 3],[-1, 0, -2]])
L = Array(A.eye(A.shape[0]))
U = A
fila_L, columna_obj = 0, 0
In [21]:
for ij in range(0, A.shape[1] - 1):
for i in range(1, A.shape[1] - ij):
valor_L, fila_U = dameVectorUyValorL(Array([A[fila_L,:]]),Array([A[fila_L + i,:]]), columna_obj)
L[fila_L + i, columna_obj] = valor_L
for j in range(fila_U.shape[1]):
U[fila_L + i, j] = fila_U[0,j]
fila_L = fila_L + 1
columna_obj = columna_obj + 1
In [22]:
print(L)
In [23]:
U.data[0][1]
Out[23]:
In [24]:
U
Out[24]:
In [25]:
L*U
Out[25]:
In [26]:
def convierteAuno(A, pos_fila, pos_col):
fila = Array([A[pos_fila,:]])
if fila[0, pos_col] != 0:
fila = Array([[fila[0, j] / fila[0, pos_col] for j in range(fila.shape[1])]])
for j in range(fila.shape[1]):
A[pos_fila, j] = fila[0,j]
def convierteAcero(A, pos_fila_semilla, pos_fila_objetivo, pos_col):
fila_semilla = Array([A[pos_fila_semilla,:]])
if fila_semilla[0, pos_col] != 0:
fila_objetivo = Array([A[pos_fila_objetivo,:]])
multiplicador = fila_objetivo[0, pos_col] / fila_semilla[0, pos_col]
fila_objetivo = fila_objetivo - Array([[fila_semilla[0, j] * multiplicador for j in range(fila_semilla.shape[1])]])
for j in range(fila_objetivo.shape[1]):
A[pos_fila_objetivo, j] = fila_objetivo[0,j]
def cerosHaciaAbajo(A, pos_fila_semilla, pos_col):
for i in range(pos_fila_semilla + 1, A.shape[0]):
convierteAcero(A, pos_fila_semilla, i, pos_col)
def cerosHaciaArriba(A, pos_fila_semilla, pos_col):
for i in range(0, pos_fila_semilla):
convierteAcero(A, pos_fila_semilla, i, pos_col)
def resuelveSistemaLower(A):
for i in range(A.shape[0]):
convierteAuno(A, i, i)
cerosHaciaAbajo(A, i, i)
def resuelveSistemaUpper(A):
for i in range(A.shape[0]):
convierteAuno(A, i, i)
cerosHaciaArriba(A, i, i)
def resuelveSistemaDeEcuaciones(A):
resuelveSistemaLower(A)
resuelveSistemaUpper(A)
return [A[i,A.shape[1] - 1] for i in range(A.shape[0])]
In [27]:
# Aj = X, Y, Z, R
A = Array([[1, 1, -1, 9],[0, 1, 3, 3],[-1, 0, -2, 2]])
resuelveSistemaDeEcuaciones(A)
Out[27]:
In [28]:
B = Array([[2, 1, 2],[4, 6, 1]])
resuelveSistemaDeEcuaciones(B)
Out[28]:
In [ ]:
In [ ]: