diff --git a/band_lu_factorization.py b/band_lu_factorization.py new file mode 100644 index 0000000..563384d --- /dev/null +++ b/band_lu_factorization.py @@ -0,0 +1,135 @@ +import numpy as np +from copy import deepcopy +from band_matrix import BandMatrix + +def mult(m1: BandMatrix, m2: BandMatrix): + matRes = [] + + for i in range(0, m1.dimension_x): + matRes.append([]) + + for j in range(0, m2.dimension_y): + # multiplica cada linha de mat1 por cada coluna de mat2; + listMult = [x*y for x, y in zip(m1.get_line(i), m2.get_col(j))] + + # e em seguida adiciona a matRes a soma das multiplicações + matRes[i].append(sum(listMult)) + + return matRes + +def print_matrix(matrix): + for line in matrix: + print("|{}|".format("\t".join(list(map(lambda item: "{:7.2f}".format(item), line))))) + print('\n\n') + +def set_diagonal(m, n = 1): + for i in range(m.dimension_x): + m.set(i, i, n) + +def find_pivo(matrix, col): + maior = matrix.get(col, col) + index = col + for i in range(col, matrix.dimension_x): + if(abs(matrix.get(i, col)) > abs(maior)): + maior = matrix.get(i, col) + index = i + return index, maior + +def lu_factor(matrix): + u = deepcopy(matrix) + l = BandMatrix(12, 12, matrix.lower_bandwidth, 0) + for k in range(matrix.dimension_x - 1): + # pivoteamento # + """index, maior = find_pivo(u, k) + print("Swap line {} with line {}".format(k, index)) + u.swap_lines(k, index) + l.swap_lines(k, index)""" + ## + for j in range(k + 1, matrix.dimension_x): + l.set(j, k, u.get(j, k)/u.get(k, k)) + for i in range(k, matrix.dimension_x): + u.set(j, i, u.get(j, i) - l.get(j, k)*u.get(k, i)) + set_diagonal(l) + return l, u + + +def solvingl(l, b): + n = l.dimension_x + for i in np.arange(n): + pivo = b[i] + + for j in np.arange(n): + if(j > i): + b[j] = b[j] + round((l.get(j,i)*-1),2) * pivo # Multiplica l *multiplicadores* com o pivo e soma com b + + return(np.copy(b)) + +def solvingu(A, b): + n = A.dimension_x + x = np.zeros(n) + x[n-1] = b[n-1]/A.get(n-1, n-1) + + for k in range(n-1, -1, -1): # linha + soma = 0 + for j in range(0,n): # coluna + soma = soma + A.get(k,j) * x[j] + x[k]=(b[k] - soma)/A.get(k,k) + + return(x) + +if __name__ == "__main__": + + normal_matrix = [ + [ 1, 0, 0, 0, 1], + [-1, 1, 0, 0, 1], + [-1, -1, 1, 0, 1], + [-1, -1, -1, 1, 1], + [-1, -1, -1, -1, 1] + ] + + normal_matrix = [ + [ 10, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0], + [ 20, 20, 21, 14, 4, 0, 0, 0, 0, 0, 0, 0], + [ 90, 65, 82, 64, 10, 3, 0, 0, 0, 0, 0, 0], + [ 0, 90, 101, 12, 49, 14, 7, 0, 0, 0, 0, 0], + [ 0, 0, 90, 29, 46, 48, 20, 7, 0, 0, 0, 0], + [ 0, 0, 0, 90, 101, 92, 83, 20, 4, 0, 0, 0], + [ 0, 0, 0, 0, 90, 65, 80, 84, 15, 5, 0, 0], + [ 0, 0, 0, 0, 0, 90, 92, 82, 53, 11, 2, 0], + [ 0, 0, 0, 0, 0, 0, 90, 101, 79, 47, 5, 9], + [ 0, 0, 0, 0, 0, 0, 0, 90, 47, 19, 28, 20], + [ 0, 0, 0, 0, 0, 0, 0, 0, 90, 20, 35, 86], + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 92, 30] + ] + + b = [28, 79, 314, 273, 240, 390, 339, 330, 331, 204, 231, 212] + + m = BandMatrix(12, 12, 2, 3) + m.convert(normal_matrix) + + l, u = lu_factor(m) + + print("l (banda):") + l.print() # printa a matriz de banda + print('\n\nu (banda):') + u.print() # printa a matriz de banda + + + print("\n\nl (completo):") + l.print_complete_matrix() # printa a matriz completa + print('\n\nu (completo):') + u.print_complete_matrix() # printa a matriz completa + + print_matrix(mult(l, u)) + + # i) ly = b + y = solvingl(l, b) + # ii) ux = y + x = solvingu(u,y) + + print("\n\nResolvendo ly = b..") + print("y: ") + print(list(y)) + print("\n\nResolvendo ux = y..") + print("x: ") + print(list(x)) \ No newline at end of file diff --git a/band_matrix.py b/band_matrix.py index 850fdde..a215c83 100644 --- a/band_matrix.py +++ b/band_matrix.py @@ -2,17 +2,25 @@ class BandMatrix: - def __init__(self, dimension_x, dimension_y, lower_bandwidth, superior_bandwidth): + def __init__(self, dimension_x, dimension_y, lower_bandwidth, superior_bandwidth, matrix=None): self.dimension_x = dimension_x self.dimension_y = dimension_y self.lower_bandwidth = lower_bandwidth self.superior_bandwidth = superior_bandwidth self.width = lower_bandwidth + superior_bandwidth + 1 - self._matrix = [[0]*self.width for i in range(self.dimension_y)] + if not matrix: + self._matrix = [[0]*self.width for i in range(self.dimension_y)] + else: + self._matrix = matrix def print(self): for line in self._matrix: print("|{}|".format("\t".join(list(map(lambda item: "{:6.2f}".format(item), line))))) + + def print_complete_matrix(self): + for i in range(0, self.dimension_x): + line = self.get_line(i) + print("|{}|".format("\t".join(list(map(lambda item: "{:6.2f}".format(item), line))))) def convert(self, normal_matrix): for i in range(len(normal_matrix)): @@ -39,26 +47,38 @@ def get(self, i, j): return self._matrix[i][self.lower_bandwidth + j - i] def set(self, i, j, new_val): - print(i, j) - if not self._valid_position(i, j): - raise ValueError('Position ({}, {}) is not a valid position'.format(i, j)) if(self.lower_bandwidth + j - i) < 0 or (self.lower_bandwidth + j - i) >= len(self._matrix[0]) or i >= len(self._matrix): - if new_val != 0: - raise ValueError() - else: - self._matrix[i][self.lower_bandwidth + j - i] = new_val + return + self._matrix[i][self.lower_bandwidth + j - i] = new_val + + def get_line(self, n, aux=None): + if aux is None: + aux = self.dimension_y-1 + self.get_line(n, aux) + + if aux == -1: + return [] + + return self.get_line(n, aux-1) + [self.get(n, aux)] + + def get_col(self, n, aux=None): + if aux is None: + aux = self.dimension_y-1 + self.get_col(n, aux) + + if aux == -1: + return [] + + return self.get_col(n, aux-1) + [self.get(aux, n)] def swap_lines(self, l1, l2): - if(l1 != l2 and l1 < len(self._matrix) and l1 >=0 and l2 < len(self._matrix) and l2 >=0): - aux = self._matrix[l1] - self._matrix[l1] = self._matrix[l2] - self._matrix[l2] = aux + temp = [] + for i in range(0, self.dimension_y): + temp.append(self.get(l1, i)) + + for i in range(0, self.dimension_y): + self.set(l1, i, self.get(l2, i)) + + for i in range(0, self.dimension_y): + self.set(l2, i, temp[i]) - def to_normal(self): - m = [] - for i in range(self.dimension_x): - m.append([0]*self.dimension_x) - for i in range(self.dimension_x): - for j in range(self.dimension_y): - m[i][j] = self.get(i, j) - return m \ No newline at end of file diff --git a/lu_factorization.py b/lu_factorization.py index fd7e389..4bb04c5 100644 --- a/lu_factorization.py +++ b/lu_factorization.py @@ -51,10 +51,29 @@ def lu_factor(matrix): u = clone_matrix(matrix) l = build_zero_matrix(len(matrix)) for k in range(len(matrix) - 1): + # pivoteamento # + print('L:') + print_matrix(l) + print('U:') + print_matrix(u) + index, maior = find_pivo(u, k) + print("Swap line {} with line {}".format(k, index)) + u = swap_lines(matrix, k, index) + l = swap_lines(l, k, index) + print('L:') + print_matrix(l) + print('U:') + print_matrix(u) + ## + print(f"Pivo - {u[k][k]}") for j in range(k + 1, len(matrix)): l[j][k] = u[j][k]/u[k][k] for i in range(k, len(matrix)): u[j][i] = u[j][i] - l[j][k]*u[k][i] + print('L:') + print_matrix(l) + print('U:') + print_matrix(u) set_diagonal(l) return l, u @@ -68,12 +87,6 @@ def lu_factor(matrix): [-1, -1, -1, -1, 1] ] - m = [ - [1, 1, 1], - [2, 2, 5], - [4, 6, 8] - ] - m = [ [ 10, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0], [ 20, 20, 21, 14, 4, 0, 0, 0, 0, 0, 0, 0], diff --git a/test.py b/test.py index 7efc694..d22b447 100644 --- a/test.py +++ b/test.py @@ -19,4 +19,6 @@ m = BandMatrix(12, 12, 2, 3) m.convert(normal_matrix) m.print() -print(m.get(1, 5))#49 \ No newline at end of file +print(m.get(3, 4))#49 +print(m.get(1, 1))#20 +print(m.get(3, 4))#29 \ No newline at end of file