Look, one approach to solving this problem is to think with classes, objects and methods. You have an object, which is an array. This matrix can have methods for obtaining a value, changing a value, obtaining width, height, summing a line with a set of values, or multiplying a line by a value, among other possibilities. Finally, there is a static method that can build a lower triangular matrix from the given values and another (non-static) that can perform the Gauss elimination method which is what you are doing.
That is to say:
# Autor - /users/132
class Matriz:
def __init__(self, largura, altura, valores):
if len(valores) != altura:
raise IndexError("O conjunto de valores não tem o tamanho correto.")
for linha in valores:
if len(linha) != largura:
raise IndexError("O conjunto de valores não tem o tamanho correto.")
self.__valores = valores
@property
def largura(self):
return len(self.__valores[0])
@property
def altura(self):
return len(self.__valores)
def valor(self, num_linha, num_coluna):
if num_linha < 0 or num_linha >= self.altura or num_coluna < 0 or num_coluna >= self.largura:
raise IndexError(f"Não há posição a_{num_linha}_{num_coluna}.")
return self.__valores[num_linha][num_coluna]
def definir(self, num_linha, num_coluna, valor):
if num_linha < 0 or num_linha >= self.altura or num_coluna < 0 or num_coluna >= self.largura:
raise IndexError(f"Não há posição a_{num_linha}_{num_coluna}.")
self.__valores[num_linha][num_coluna] = valor
def multiplicar_linha(self, num_linha, valor):
if num_linha < 0 or num_linha >= self.altura:
raise IndexError(f"Não há linha {num_linha}.")
for coluna in range(0, self.largura):
self.__valores[num_linha][coluna] *= valor
def somar_linha(self, num_linha, valores, multiplicador):
if num_linha < 0 or num_linha >= self.altura:
raise IndexError(f"Não há linha {num_linha}.")
if len(valores) != self.largura:
raise IndexError("O conjunto de valores não tem o tamanho correto.")
for coluna in range(0, self.largura):
self.__valores[num_linha][coluna] += valores[coluna] * multiplicador
def linha(self, num_linha):
if num_linha < 0 or num_linha >= self.altura:
raise IndexError(f"Não há linha {num_linha}.")
return self.__valores[num_linha]
@staticmethod
def triangular_inferior(lista_1, lista_2):
t = len(lista_2)
if t * (t + 1) / 2 != len(lista_1):
raise IndexError("A segunda lista não tem a quantidade correta de termos.")
matriz = []
n = 0
for i in range(0, t):
linha = []
for j in range(0, i + 1):
linha.append(lista_1[n])
n += 1
for j in range(i + 1, t):
linha.append(0)
matriz.append(linha)
linha.append(lista_2[i])
return Matriz(t + 1, t, matriz)
def eliminacao_gauss(self):
for i in range(0, self.altura):
if self.__valores[i][i] == 0:
raise IndexError("Zero na coluna principal.")
for i in range(0, self.altura):
self.multiplicar_linha(i, 1 / self.__valores[i][i])
for j in range(i + 1, self.altura):
self.somar_linha(j, self.__valores[i], -self.__valores[j][i])
ret = []
for i in range(0, self.altura):
ret.append(self.__valores[i][-1])
return ret
def __str__(self):
t = ""
for i in range(0, self.altura):
for j in range(0, self.largura):
v = self.__valores[i][j]
if j == self.largura - 1:
t += f" = {v: >6.2f}"
else:
if j != 0: t += " "
if v == 0:
t += " " * (12 + len(str(j + 1)))
else:
s = "+" if v > 0 else "-"
t += f"{s} {abs(v): >6.2f} * x{j + 1}"
t += "\n"
return t
def mostra_vetor(vetor):
aux = ""
for i in range(0, len(vetor)):
aux += f"{vetor[i]} * x{i + 1}\n"
return aux
m = Matriz.triangular_inferior([-13, 13, 3, -5, -1, -1, 3, 0, 1, 1], [-13, 13, -7, 4])
print(m)
resultado = m.eliminacao_gauss()
print(resultado)
print(mostra_vetor(resultado))
This solution allows you to add other methods in the matrix to do other things. See here working on ideone.
If you prefer to join only the necessary parts in one procedure, the result would be this:
# Autor - /users/132
def solucao_triangular_inferior(lista_1, lista_2):
# Descobre a altura e a largura e verifica se as listas tem o tamanho certo.
altura = len(lista_2)
largura = altura + 1
if altura * (altura + 1) / 2 != len(lista_1):
raise IndexError("A segunda lista não tem a quantidade correta de termos.")
# Constrói a matriz a partir das listas. A última coluna serão os valores de lista_2.
matriz = []
n = 0
for i in range(0, altura):
linha = []
for j in range(0, i + 1):
linha.append(lista_1[n])
n += 1
for j in range(i + 1, altura):
linha.append(0)
matriz.append(linha)
linha.append(lista_2[i])
# Cria uma segunda matriz como cópia da primeira, pois a primeira será destruída como parte do processo de eliminação de Gauss.
copia = []
for linha in matriz:
copia.append(linha[:])
# Verifica se não há nenhum zero na diagonal principal.
for i in range(0, altura):
if matriz[i][i] == 0:
raise IndexError("Zero na coluna principal.")
# Zera os coeficientes fora da diagonal principal.
for i in range(0, altura):
# Reduz o coeficiente da diagonal principal para 1 e todos os outros da mesma linha na mesma proporção.
valor = 1 / matriz[i][i]
for coluna in range(0, largura):
matriz[i][coluna] *= valor
# Corrige as demais linhas abaixo.
for j in range(i + 1, altura):
# Conceitualmente, o certo seria percorrer todas as colunas da linha j.
# No entanto, todas as colunas diferentes da coluna i e da última teriam seus valores inalterados,
# e portanto só precisamos mexer nessas duas colunas.
matriz[j][-1] -= matriz[i][-1] * matriz[j][i]
matriz[j][i] = 0
# Monta o resultado final.
ret = []
for i in range(0, altura):
ret.append(matriz[i][-1])
# Retorna a matriz original e o resultado.
return copia, ret
def mostra_matriz(matriz):
altura = len(matriz)
largura = len(matriz[0])
t = ""
for i in range(0, altura):
for j in range(0, largura):
v = matriz[i][j]
if j == largura - 1:
t += f" = {v: >6.2f}"
else:
if j != 0: t += " "
if v == 0:
t += " " * (12 + len(str(j + 1)))
else:
s = "+" if v > 0 else "-"
t += f"{s} {abs(v): >6.2f} * x{j + 1}"
t += "\n"
return t
def mostra_vetor(vetor):
aux = ""
for i in range(0, len(vetor)):
aux += f"{vetor[i]} * x{i + 1}\n"
return aux
matriz, resultado = solucao_triangular_inferior([-13, 13, 3, -5, -1, -1, 3, 0, 1, 1], [-13, 13, -7, 4])
print(mostra_matriz(matriz))
print(mostra_vetor(resultado))
See here working on ideone.
You could show how from the lists of coefficients and independent terms, you would arrive at the result of
[1, 0, 2, 2]
, would not be[1, 0, 2, -1]
?– Paulo Marques
I’m sorry, the answer would be [1, 0, 2, -1]. I’ll change the question.
– None
Do you know how I can do the last function without using print? I tried to define a function
def impressão (lista_1, lista_2)
, adding the variableimpressão = ''
. Then where there is print, as for example in this lineprint (f'{lista_1[i]: >6.2f}*x{v}', end = ' ')
, I traded forimpressão += f'{lista_1[i]: >6.2f}*x{v}'
. At the end of the function I putreturn impressão
, and out of function,print (impressão (lista_1, lista_2))
. However, no printing occurs. @Paulomarques– None