Algebraic System - Python

Asked

Viewed 71 times

-5

Hello,

I need to do an activity to solve lower triangular systems of n unknown and n independent terms.

NOTE: none of the functions can have print inside them, and I can’t use the Matrix or numpy library.

It is necessary to make a python function that will have two lists as argument:

• the first list has (n (n + 1)) / 2 terms, which are the coefficients that accompany the unknowns;

• the second list contains the n independent terms of the system.

This function will return a list of the n values of the unknown x.

In addition, the programme should also have:

• a function to display/print the system (as shown below), and below the unknowns x and its values calculated by the other function.

Imagem que mostra como o sistema deve ser impresso

The code I tried was:

lista_1 = [] #Insira a lista de coeficientes
lista_2 = [] #Insira a lista de termos independentes
tamanho_l1 = len(lista_1)
tamanho_l2 = len(lista_2)
    
def solução(lista_1,lista_2):
    lista_3 = []
    if lista_1[0] == 0 and lista_2[0] == 0:
        return ("Sistema possível e indeterminado")
    elif lista_1[0] == 0 and lista_2[0] != 0:
        return ("Sistema impossível")
    else: 
        lista_3 = lista_3 + [lista_2[0]/lista_1[0]]
        for i in range(1, tamanho_l2): 
            soma = 0
            for j in range(0, i):
                soma = lista_1[i]*lista_3[j] + soma
            if lista_1[i] == 0 and lista_2[i] - soma == 0:
                return ("Sistema possível e indeterminado")
            elif lista_1[i] == 0 and lista_2[i] - soma != 0:
                return ("Sistema impossível")
            else: 
                lista_3 = lista_3 + [(lista_2[i] - soma)/lista_1[i]]
    return lista_3
 

print (solução(lista_1,lista_2)) 
print ('\n')
n = 1   
m = 1 
z = 2    
for i in range (tamanho_l2):
    v = 1
    if i == 0:
        print (f'{lista_1[i]: >6.2f}*x{v}', end = ' ')
        print (f'= {lista_2[i]: >30.2f} \n')
        n = n + 1
    elif i == 1:
        for j in range (i, 3):
            if j == 2:
                print (f'{lista_1[j]: >6.2f}*x{v}', end = ' ')
            else:
                print (f'{lista_1[j]: >6.2f}*x{v} +', end = ' ')
            v = v + 1
        n = n + 1
        print (f'= {lista_2[i]: >18.2f} \n')
    else: 
        v = 1
        for j in range(i + m, i + m + n):    
            if j == (i + m + n - 1):
                print (f'{lista_1[j]: >6.2f}*x{v}', end = ' ')
            else:
                print (f'{lista_1[j]: >6.2f}*x{v} +', end = ' ')
            v = v + 1
        n = n + 1  
        print (f'= {lista_2[i]: >6.2f} \n')
        m = m + z
        z = z + 1
            

In my code:

• The function to solve the system did not work

For example, using these 2 lists:

[-13, 13, 3, -5, -1, -1, 3, 0, 1, 1] (coefficients)

[-13, 13, -7, 4] (independent terms)

the answer should be [1, 0, 2, -1], but the output is [1,0, 0,0, -3,333333333335, 1,533333333337]

• I could not perform the last function (which starts after "print (' n')") without using print.

Could someone help me, please?

  • 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]?

  • I’m sorry, the answer would be [1, 0, 2, -1]. I’ll change the question.

  • 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 variable impressão = ''. Then where there is print, as for example in this line print (f'{lista_1[i]: >6.2f}*x{v}', end = ' '), I traded for impressão += f'{lista_1[i]: >6.2f}*x{v}'. At the end of the function I put return impressão, and out of function, print (impressão (lista_1, lista_2)). However, no printing occurs. @Paulomarques

3 answers

0


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.

  • Thank you! @Victor Stafusa

  • In my code I had made the check: if (lista_1 != [] or lista_2 != []) and (tamanho_l1 == ((tamanho_l2*(tamanho_l2 + 1)) / 2)) and ((all(isinstance(n, float) for n in lista_1) or (all(isinstance(n, int) for n in lista_1))) or (all(isinstance(n, float) for n in lista_2) or all(isinstance(n, int) for n in lista_2))): return True else: return False. in which tamanho_l2 = len(lista_2) and tamanho_l1 = len(lista_1)

  • You can help me with system printing as in image without using print?

  • 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 variable impressão = ''. Then where there is print, as for example in this line print (f'{lista_1[i]: >6.2f}*x{v}', end = ' '), I traded for impressão += f'{lista_1[i]: >6.2f}*x{v}'. At the end of the function I put Return printing, and out of function, print (impressão (lista_1, lista_2)). However, no impression occurs

  • @None Your problem with these prints is show the original matrix on the screen?

  • It’s because I can’t use print inside the function, the way I made the print comes out right, but I’d have to adjust to turn it into a function without print, like the other.

  • In fact it has to show the linear system, equal in the image, in which the list 1 accompanies the unknowns and has = independent term. In the case of example lists, something like this would have to come out:;-13.00*x1 = -13.00 &#xA;&#xA; 13.00*x1 + 3.00*x2 = 13.00 &#xA;&#xA; -5.00*x1 + -1.00*x2 + -1.00*x3 = -7.00 &#xA;&#xA; 3.00*x1 + 0.00*x2 + 1.00*x3 + 1.00*x4 = 4.00 Each one in a row, in my code, this impression can be made, but I could not redo the code without using print. I tried to do the same I explained in the third comment above that. @Victor

  • @None I edited the answer. Now it’s ok?

  • Fine. Thank you! This way I can redo the system printing part without using print.

  • @None I edited again, but only the first code. Serves?

  • I understood the second code better, I will try to do it for him. But I will try to make the impression of the system similar to this def mostra_vetor(vetor):. Thank you. @Victorstafusa

  • @None I also edited the second code.

  • @None If this answer solved your problem and you have no further questions, click the " " which is to the left of the answer to mark it as accepted/correct, which also marks your question as solved/answered. Otherwise, feel free to comment.

Show 8 more comments

0

Expensive,

Although the solution below has no test, see if it helps you in solving the problem.

I commented on the code because I thought it would be better to do a paragraph describing what it does.

coeficientes = [-13, 13, 3, -5, -1, -1, 3, 0, 1, 1]
termos_independentes = [-13, 13, -7, 4]

lista_x = []

# Onde o `slice` de coeficientes começará.
idx = 0

for termo in termos_independentes:
    # qtd - quantos elementos da lista serão usados. Número de `x` já encontrados + 1
    qtd = len(lista_x) + 1

    # slice - pedaço de coeficientes que será usado 
    slice = coeficientes[idx: idx + qtd]

    # inicializando soma
    soma = 0

    # loop que fará a soma considerando os `x` já encontrados e o slice
    for i, x in enumerate(lista_x):
        soma = soma + (slice[i] * x)

    # o último termo do `slice` não foi usado, é para ele que o novo `x` tem que ser calculado
    res = (termo - soma) / slice[-1]

    # inclui `x` na lista
    lista_x.append(res)

    # atualiza o `idx`, ou seja, a partir de onde o próximo slice começará
    idx = idx + qtd

print(lista_x)
[1.0, 0.0, 2.0, -1.0]

If you have any questions in the code, please comment that I update the post with more details.

I hope it helps

  • 1

    Thank you! @Paulomarques

0

Heed: This algorithm does no checking or error handling.

linhas = int(input('Qual o número de equações no sistema: '))

a = [[0] * linhas for l in range(linhas)]    #inicializa a lista de coeficientes. 

#Inicializa a coleta de dados...
for l in range(linhas):
  linha = input(f'Digite todos os coeficientes da linha {l + 1} separados por espaço:\n')
  for c, val in enumerate(str.split(linha,' ')):
    a[l][c] = float(val)

termos = input(f'Digite todos os termos independentes separados por espaço:\n')
b = [float(t) for t in str.split(termos,' ')]
#...finalizada a coleta de dados.

x = [0 for l in range(linhas)]    #Unicializa a lista de soluções.    
x[0]= b[0] / a[0][0]              #Calcula  x₁

#A partir de x₂ ...
for i in range(1, linhas):
  #usa a formula para calcular xₗ
  x[i] = (b[i] - sum([a[i][j] * x[j] for j in range(0, i)])) / a[i][i]  

print(f'solução: {x}')

test the code on Repli.it

Example:

Qual o número de equações no sistema: 3
Digite todos os coeficientes da linha 1 separados por espaço:
2
Digite todos os coeficientes da linha 2 separados por espaço:
1 -9
Digite todos os coeficientes da linha 3 separados por espaço:
6 5 9
Digite todos os termos independentes separados por espaço:
10 2 70
solução: [5.0, 0.3333333333333333, 4.259259259259259]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.