Como resolver sistemas de equações usando Python
Usar o Python para automatizar sua vida é incrível né? Mas sabe o mais legal? Ele pode te ensinar muito sobre matemática!

Como resolver sistemas de equações usando Python

Nesse post vamos mostrar como você pode usar o Python para resolver sistemas de equações. No entanto, meu objetivo vai além disso… eu quero mostrar pra você que a computação pode te ajudar a entender melhor os problemas de matemática e suavizar sua caminhada por essa disciplina.

Então você gosta de aplicações práticas da computação? Não esqueça de ver nossa página de exemplos de aplicações… tem um monte de “mini-sistemas” didáticos que foram feitos pra você aprender mais sobre computação e aplicar seus conhecimentos na prática.

O que é um sistema de equações?

Um sistema de equações lineares é definido como:

Um sistema de equações lineares é um conjunto finito de equações lineares aplicadas num mesmo conjunto, igualmente finito, de variáveis. [1][2]

Parece difícil né? mas não é…

Imagine por exemplo que você possui 3 retas que seguem direções diferentes mas se interceptam em um único ponto:

Ponto de interseção de retas

Esse ponto de interseção é um único ponto que satisfaz três equações de retas para que elas possuam o mesmo resultado. Nesse caso em específico, as retas possuem 2 dimensões, portanto, um ponto como esse mostrado na figura exatamente dois valores: x e y (por exemplo, [2,3] ).

Outra opção para esse tipo de sistema é considerar que existem 3 dimensões possíveis (famosa profundidade “z”). Então, para representar esse sistema devemos usar três variáveis (x, y e z). Assim, uma solução para um sistema linear é uma atribuição de números às incógnitas que satisfazem simultaneamente todas as equações do sistema.

Se estivéssemos olhando para uma imagem de um sistema desses, teríamos três planos que se intersectam em um único ponto. Seria algo mais ou menos assim:

Planos se intersectando
Créditos da imagem: Fred the Oyster sob a licença Creative Commons S.A. 4.0

Mas olhando para o sistema de equações você vê apenas algo assim:

3x + 2y - z = 1
2x - 2y + 4z = -2
-x + 1/2y - z = 0

Claro, que se você quiser solucionar esse sistema precisará seguir uma metodologia criada há muitos anos atrás. Ela naturalmente segue alguns passos como o calculo de determinantes ou então soma e subtração de equações. No entanto, se você visitar esse website, facilmente você visualizará a solução (inclusive mostrando os passos para resolver esse sistema).

x = 1 
y = -2 
z = -2

Mas ai você vai pensar… poxa, mas então você está me ensinando como trapacear em provas?

Na verdade não… estou ensinando a você que esses problemas já são muito bem conhecidos e outras pessoas já resolveram eles de inúmeras formas. O seu trabalho agora é simplesmente encontrar a melhor forma de compreender esse problema. Eu acredito que uma solução é usar a computação como aliada.

Mas vamos focar um pouco na computação disso tudo… se esse site está online e funciona perfeitamente, alguém teve que codificá-lo. Assim, alguém conseguiu abstrair a regra para resolver esse problema em um algoritmo de computador que resolve qualquer sistema de equação. Portanto, hoje vamos entender como nós podemos usar o Python para fazer isso.

Entendendo a regra de Cramer

Para entender como resolver um sistema de equações eu recomendo que você assista esse vídeo:

Nesse vídeo incrível, o professor mostra como solucionar o sistema de equações usando a regra de Cramer. Só pra você saber, o “Cramer” se refere ao Gabriel Cramer (esse da pintura). Ele publicou um artigo explicando mais sobre a regra que ele havia estudado (em 1750) e você estuda isso até hoje!

Gabriel Cramer
Esse é o Gabriel Cramer

Seu método usa a determinante das matrizes para definir os valores de X, Y, Z. Então, recomendo que se você não sabe muito sobre o que são matrizes e determinantes dar uma relembrada nisso antes de continuar.

Como usar a regra de Cramer usando Python

A primeira coisa que precisamos fazer é compreender é que um sistema de equações pode ser representado por meio de matrizes. Veja um exemplo prático:

# Considere o seguinte sistema de equações 
x + 2y  +z = 0
2x - y + z = 1
-x + 3y +z = -2

# Em formato de matrizes teríamos
1, 2, 1
2, -1, 1
-1, 3, 1

# Escrito em Python temos:
sistema = [
        [1,2,1],
        [2,-1,1],
        [-1,3,1]
]

# as igualdades são representadas por:
igualdades = [1,-2,0]

Perfeito, agora que temos nossa matriz precisamos criar uma função que resolva determinantes, para isso vamos recorrer aos nossos conhecimentos sobre matrizes e manipulação de vetores usando laços de repetição:


## importa o numpy
import numpy as np
## importa o deepcopy para fazer cópias de matrizes
from copy import copy, deepcopy

def resolverDeterminante(mat):
    # aqui fazemos uma cópia da matriz original para não corrermos o risco de alterar a matriz original
    matT = deepcopy(mat)
    
    diagonalPrincipal = []
    diagonalSecundaria = []
    

    # aqui aplicamos a transformação da matriz para podermos resolver o determinante
    for c in range(0,3):
        for d in range(0,2):
            matT[c].append(mat[c][d])
    
    # resolve a diagonal principal
    for x in range (0,3):
        c = 0 + x
        multiplica = []
        for l in range(0,3):
            multiplica.append(matT[l][c])
            c += 1
        diagonalPrincipal.append(np.prod(multiplica))
    
    #print(diagonalPrincipal)
    
    # resolve a diagonal secundária
    for x in range (0,3):
        c = 0 + x
        multiplica = []
        for l in range(2,-1,-1):
            multiplica.append(matT[l][c])
            c += 1
        diagonalSecundaria.append(np.prod(multiplica))
    
    #print(diagonalSecundaria)
    
    # faz a subtração da soma dos elementos 
    determinante = sum(diagonalPrincipal) - sum(diagonalSecundaria)
    return determinante

Uma das particularidades desse código é o “deepcopy”. Esse recurso é necessário porque quando você passa por parâmetro uma matriz é comum que o Python use uma referência da matriz original e não uma cópia dela. Isso pode ser bastante problemático, visto que se alterarmos a matriz original não poderemos utilizar ela novamente, visto que ela já sofreu alterações.

Esse problema é muito fácil de entender quando você já estudou C ou C++ e entende um pouco de ponteiros e passagem por valor e por referência. Mas se você não sabe o que é isso, fique tranquilo… pense apenas que estamos fazendo cópias das matrizes para preservar a matriz original.

Certo, agora se fizermos a chamada dessa função teremos o resultado do determinante:

resolverDeterminante(sistema)
output: -3.0

Agora que temos uma função auxiliar pronta para receber nossos cálculos de determinante, podemos criar uma função para realmente resolver um sistema de equações. Para isso devemos:

  1. substituir o vetor de igualdades pelas dimensões x, y e z da nossa matriz sistema;
  2. calcular o determinante dessa nova matriz;
  3. dividir o determinante dessa matriz pelo determinante da matriz original.

Então podemos criar a seguinte função:

def resolverSistema(sistema, igualdades):
    
    determinante = resolverDeterminante(sistema)
    
    # print(determinante)
    #para DX
    ## primeiro fazemos uma cópia do sistema original (para podermos fazer os outros cálculos tranquilamente)
    sis = deepcopy(sistema)
    # aqui vamos substituir a dimensão 0, ou seja, a dimensão X
    dimensao = 0
    
    # fazemos a substituição...
    for i in range(0,3):
        sis[i][dimensao] = igualdades[i]
    # resolvemos o determinante de "sis" e dividimos pelo determinante da matriz original
    x = resolverDeterminante(sis)/determinante
    
    # para Dy 
    # mais uma cópia
    sis = deepcopy(sistema)
    # agora para dimensão y
    dimensao = 1
    
    # substituição
    for i in range(0,3):
        sis[i][dimensao] = igualdades[i]
    # calculo de Y
    y = resolverDeterminante(sis)/determinante
    
    # para Dz
    ## daqui pra baixo é tudo igual e só mudamos a dimensão
    sis = deepcopy(sistema)
    # agora para Z
    dimensao = 2
    
    for i in range(0,3):
        sis[i][dimensao] = igualdades[i]
        
    z = resolverDeterminante(sis)/determinante
    
    print("conjunto solução:", "x = ", x , "y = ", y, "z = ", z)

Ao executar essa função temos:

resolverSistema(sistema,igualdades)
output: conjunto solução: x =  1.0 y =  -2.0 z =  -2.0

Conclusão

A matemática sempre traz desafios muito legais que podem ser fonte de grande aprendizado para computação. A grande vantagem de implementar esse tipo de código é que você ganha conhecimento em duas áreas diferentes ao mesmo tempo. Além disso, ao implementar um algoritmo assim, você consegue entender exatamente como funcionam todos os seus passos.

Veja nosso Github

Referências

[1] – Poole, David (2005). Álgebra linear 1 ed. São Paulo: Pioneira Thompson Learning

[2] – Adaptado de “sistemas de equações lineares” – Wikipédia

Vinicius dos Santos

Apenas um apaixonado por Ciência da Computação e a forma com que ela pode transformar vidas!

Deixe uma resposta