Pular para conteúdo

Lista 07 · Eliminação de Gauss

Acompanha o capítulo 7. Sistemas lineares em circuitos, química e economia: primeiro o escalonamento à mão, depois os laços, depois o pivotamento. Confira sempre com A @ x.

Abrir no Colab

Baixar o caderno

Como esta lista funciona

Abra o caderno no Colab, escreva a sua solução no lugar do # TODO e rode a célula de teste logo abaixo. Ela mesma diz o que passou e o que falhou — você não precisa esperar correção de ninguém.

O código de cada exercício também está aqui embaixo, caso você prefira colar num editor local. Os testes comparam números com tolerância.

Exercícios marcados com ✏️ são à mão, no papel, com 4 casas decimais — como na parte em papel das avaliações.

Exercício 01

✏️ À mão. Resolva por eliminação de Gauss (sem trocar linhas):

\[ \begin{aligned} 2x + y - z &= 8\\ -3x - y + 2z &= -11\\ -2x + y + 2z &= -3 \end{aligned} \]

a) Escreva a matriz \(A\) e o vetor \(b\).

b) Faça a eliminação: diga os fatores usados em cada passo e escreva a matriz triangular e o novo \(b\).

c) Faça a substituição de trás para frente.

d) Confira substituindo a resposta nas três equações.

Exercício 02

Escreva eliminacao(A, b), que faz a fase de eliminação de Gauss (sem trocar linhas) e devolve a tupla (U, c): a matriz triangular superior e o lado direito transformado. Não modifique A nem b: trabalhe em cópias (.copy()).

import numpy as np


def eliminacao(A, b):
    """Triangulariza A x = b (sem pivotamento). Devolve (U, c), sem mexer em A e b."""
    U = A.copy()
    c = b.copy()
    n = len(c)
    # TODO: para cada coluna k, para cada linha i abaixo: fator e subtração
    return (U, c)


# --- testes (não altere) ---
import numpy as np


A = np.array([[2.0, 1.0, -1.0], [-3.0, -1.0, 2.0], [-2.0, 1.0, 2.0]])
b = np.array([8.0, -11.0, -3.0])
U, c = eliminacao(A, b)
esperado_U = [[2, 1, -1], [0, 0.5, 0.5], [0, 0, -1]]
for i in range(3):
    for j in range(3):
        assert abs(U[i, j] - esperado_U[i][j]) < 1e-12, f"U[{i}, {j}] = {U[i, j]}"
for i in range(3):
    assert abs(c[i] - [8, 1, 1][i]) < 1e-12, f"c[{i}] = {c[i]}"
assert A[1, 0] == -3.0 and b[1] == -11.0, "A e b originais não podem mudar: use .copy()"
print("Exercício 02: todos os testes passaram!")

Exercício 03

Escreva substituicao(U, c), que resolve um sistema triangular superior de trás para frente:

\[ x_i = \frac{c_i - \sum_{j > i} U_{ij}\,x_j}{U_{ii}}. \]
import numpy as np


def substituicao(U, c):
    """Resolve U x = c, com U triangular superior, de trás para frente."""
    n = len(c)
    x = np.zeros(n)
    # TODO: for i in range(n - 1, -1, -1): comece com c[i], subtraia U[i, j] * x[j]
    # para j depois de i e divida por U[i, i]
    return x


# --- testes (não altere) ---
import numpy as np


U = np.array([[2.0, 1.0, -1.0], [0.0, 0.5, 0.5], [0.0, 0.0, -1.0]])
c = np.array([8.0, 1.0, 1.0])
x = substituicao(U, c)
for i in range(3):
    assert abs(x[i] - [2, 3, -1][i]) < 1e-12, f"x = {x}"
x = substituicao(np.array([[4.0]]), np.array([10.0]))
assert abs(x[0] - 2.5) < 1e-12, "sistema de uma equação só"
print("Exercício 03: todos os testes passaram!")

Exercício 04

Pivotamento parcial. Escreva gauss_pivotamento(A, b), que resolve \(A\,x = b\) por eliminação de Gauss, mas, antes de zerar cada coluna \(k\), troca a linha \(k\) pela linha (de \(k\) para baixo) com o maior valor absoluto na coluna \(k\) — nos dois, A e b.

Para trocar duas linhas de uma matriz, guarde uma cópia de uma delas:

linha = A[k].copy()
A[k] = A[p]
A[p] = linha

Teste no sistema do capítulo, com o pivô \(10^{-17}\): sem pivotamento, \(x\) sai 0; com pivotamento, sai 1.

import numpy as np


def gauss_pivotamento(A, b):
    """Resolve A x = b por Gauss com pivotamento parcial."""
    A = A.copy()
    b = b.copy()
    n = len(b)
    # TODO: para cada coluna k: ache a linha p (de k para baixo) com o maior
    # abs(A[p, k]); troque as linhas k e p em A e em b; depois elimine.
    # No fim, a substituição de trás para frente.
    pass


# --- testes (não altere) ---
import numpy as np


A = np.array([[1e-17, 1.0], [1.0, 1.0]])
b = np.array([1.0, 2.0])
x = gauss_pivotamento(A, b)
assert x is not None, "faltou o return?"
assert abs(x[0] - 1) < 1e-12 and abs(x[1] - 1) < 1e-12, f"com pivotamento, x = (1, 1) (veio {x})"
A = np.array([[0.0, 2.0, 1.0], [1.0, 1.0, 1.0], [2.0, 1.0, 3.0]])
b = np.array([5.0, 6.0, 13.0])
x = gauss_pivotamento(A, b)
assert np.max(A @ x - b) < 1e-12 and np.min(A @ x - b) > -1e-12, "pivô zero na primeira linha"
print("Exercício 04: todos os testes passaram!")

Exercício 05

Conferir sempre. Escreva residuo_maximo(A, x, b), que calcula o resíduo \(r = b - A\,x\) (com @) e devolve o maior valor absoluto entre os elementos de \(r\). Um resíduo perto de \(10^{-15}\) quer dizer que \(x\) resolve o sistema; um resíduo grande quer dizer que não.

def residuo_maximo(A, x, b):
    """O maior |b_i - (A x)_i|: quanto a resposta erra ao ser substituída."""
    # TODO: r = b - A @ x; depois o padrão extremo com abs
    pass


# --- testes (não altere) ---
import numpy as np


A = np.array([[2.0, 1.0], [1.0, 3.0]])
b = np.array([3.0, 5.0])
assert residuo_maximo(A, np.array([0.8, 1.4]), b) < 1e-12, "(0.8, 1.4) é a solução"
assert abs(residuo_maximo(A, np.array([1.0, 1.0]), b) - 1.0) < 1e-12, "(1, 1) erra por 1 na segunda equação"
print("Exercício 05: todos os testes passaram!")

Exercício 06

Química — balanceamento. Na queima de um hidrocarboneto \(\text{C}_n\text{H}_m\),

\[ \text{C}_n\text{H}_m + a\,\text{O}_2 \to b\,\text{CO}_2 + c\,\text{H}_2\text{O}. \]

Cada elemento dá uma equação, porque os átomos se conservam:

  • carbono: \(b = n\);
  • hidrogênio: \(2c = m\);
  • oxigênio: \(2a = 2b + c\).

Escreva combustao(nC, nH), que monta esse sistema com as incógnitas na ordem \((a, b, c)\) e o resolve com np.linalg.solve.

combustao(3, 8)    # propano  -> [5. 3. 4.]
combustao(1, 4)    # metano   -> [2. 1. 2.]
import numpy as np


def combustao(nC, nH):
    """Coeficientes (a, b, c) de CnHm + a O2 -> b CO2 + c H2O."""
    # TODO: uma linha da matriz por elemento (C, H, O), com as incógnitas a, b, c;
    # passe tudo que tem incógnita para a esquerda
    pass


# --- testes (não altere) ---
r = combustao(3, 8)
assert r is not None, "faltou o return?"
for i in range(3):
    assert abs(r[i] - [5, 3, 4][i]) < 1e-12, f"propano: veio {r}"
r = combustao(8, 18)
for i in range(3):
    assert abs(r[i] - [12.5, 8, 9][i]) < 1e-12, f"octano: veio {r}"
print("Exercício 06: todos os testes passaram!")

Exercício 07

Economia — o modelo de Leontief. Numa economia de dois setores (agricultura e indústria), para produzir R$ 1 de agricultura gastam-se R$ 0,20 de agricultura e R$ 0,40 de indústria; para produzir R$ 1 de indústria, R$ 0,30 de agricultura e R$ 0,10 de indústria. A matriz \(A\) guarda esses consumos (coluna = quem produz). Para atender uma demanda final \(d\) (o que vai para a população), a produção total \(x\) tem de cobrir o consumo interno e a demanda:

\[ x = A\,x + d \quad\Longleftrightarrow\quad (I - A)\,x = d, \]

em que \(I - A\) tem \(1 - A_{ii}\) na diagonal e \(-A_{ij}\) fora dela.

Escreva producao_total(A, demanda), que monta a matriz \(I - A\) com dois laços — comece com M = np.zeros((n, n)), uma matriz \(n \times n\) de zeros — e resolve o sistema.

A = np.array([[0.2, 0.3], [0.4, 0.1]])
producao_total(A, np.array([100.0, 50.0]))    # -> ≈ [175.  133.33]
import numpy as np


def producao_total(A, demanda):
    """Produção x de cada setor para atender a demanda final: (I - A) x = demanda."""
    n = len(demanda)
    M = np.zeros((n, n))
    # TODO: dois laços (i e j): na diagonal, 1 - A[i, j]; fora dela, -A[i, j].
    # Depois resolva M x = demanda.
    pass


# --- testes (não altere) ---
import numpy as np


A = np.array([[0.2, 0.3], [0.4, 0.1]])
x = producao_total(A, np.array([100.0, 50.0]))
assert x is not None, "faltou o return?"
esperado = [175.0, 133.33333333333334]
for i in range(2):
    assert abs(x[i] - esperado[i]) < 1e-9, f"veio {x}"
assert A[0, 0] == 0.2, "não mexa na matriz A"
print("Exercício 07: todos os testes passaram!")