35
Sistemas Lineares Paulo J. S. Silva 12 de setembro de 2017 1 Sistemas Lineares Um dos problemas mais clássicos em computação científica é a resolução de sistemas lineares. Isso se dá por pelo menos dois motivos: 1. Sabemos resolvê-los bem. Ou seja, temos confiança que conseguimos resolver com alta precisão e de forma eficiente sistemas lineares com um número enorme de variáveis. 2. Outros problemas importantes podem ser reduzidos à solução de um ou mais sistemas lineares (po- tencialmente grandes, potencialmente infinitos). Por isso vamos estudá-los durante as próximas aulas. Vamos começar estabelecendo um pouco de notação e recordando o que já sabemos sobre a solução de sistemas lineares. Lembramos inicialmente que qualquer sistema linear de n variáveis e n incógnitas pode ser descrito em forma matricial. Ou seja, podemos descrever o problema de resolução de sistemas por uma equação. Ax = b, em que A é uma matriz de R n×n e b um vetor do R n . É claro que também é possível usar o mesmo tipo de notação para sistemas com números diferentes entre variáveis e incógnitas e nesse caso a matriz deixa de ser quadrada. Uma primeira pergunta natural é: Quão fácil é resolver um sistema? A resposta para isso não é única. Pensando em um sistema geral, com centenas de variáveis por exemplo, ficamos com a impressão que é muito difícil. Mas se a matriz A tiver estrutura especial, pode ser que a resolução do sistema seja fácil. Dois exemplos são: A é a identidade. Nesse caso o solução é trivial x = b. A é diagonal (todos os elementos fora da diagonal principal de A são nulos). Mais uma vez a solução do sistema também é fácil, basta definir x i = b i /a ii , i = 1, . . . , n, considerando que todos os elementos da diagonal são não nulos. 1.1 Sistemas triangulares Outro caso interessante ocorre quando A é triangular inferior, ou superior, com todos os elementos da dia- gonal não nulos. Nesse caso podemos resolver o sistema por substituição. Vejamos um exemplo triangular superior. a 11 x 1 + a 12 x 2 + a 13 x 3 + a 14 x 4 = b 1 a 22 x 2 + a 23 x 3 + a 24 x 4 = b 2 a 33 x 3 + a 34 x 4 = b 3 a 44 x 4 = b 4 . Nesse caso é fácil achar o valor de x 4 usando a última equação. Susbtituindo o valor encontrado na penúltima equação passa a ser fácil encontrar encontrar o valor de x 3 e a assim por diante. Obtemos: 1

Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Sistemas Lineares

Paulo J. S. Silva

12 de setembro de 2017

1 Sistemas Lineares

Um dos problemas mais clássicos em computação científica é a resolução de sistemas lineares. Isso se dápor pelo menos dois motivos:

1. Sabemos resolvê-los bem. Ou seja, temos confiança que conseguimos resolver com alta precisão e deforma eficiente sistemas lineares com um número enorme de variáveis.

2. Outros problemas importantes podem ser reduzidos à solução de um ou mais sistemas lineares (po-tencialmente grandes, potencialmente infinitos).

Por isso vamos estudá-los durante as próximas aulas. Vamos começar estabelecendo um pouco denotação e recordando o que já sabemos sobre a solução de sistemas lineares.

Lembramos inicialmente que qualquer sistema linear de n variáveis e n incógnitas pode ser descrito emforma matricial. Ou seja, podemos descrever o problema de resolução de sistemas por uma equação.

Ax = b,

em que A é uma matriz de Rn×n e b um vetor do Rn. É claro que também é possível usar o mesmo tipode notação para sistemas com números diferentes entre variáveis e incógnitas e nesse caso a matriz deixade ser quadrada.

Uma primeira pergunta natural é: Quão fácil é resolver um sistema? A resposta para isso não é única.Pensando em um sistema geral, com centenas de variáveis por exemplo, ficamos com a impressão que émuito difícil. Mas se a matriz A tiver estrutura especial, pode ser que a resolução do sistema seja fácil. Doisexemplos são:

• A é a identidade. Nesse caso o solução é trivial x = b.• A é diagonal (todos os elementos fora da diagonal principal de A são nulos). Mais uma vez a solução

do sistema também é fácil, basta definir xi = bi/aii, i = 1, . . . , n, considerando que todos os elementosda diagonal são não nulos.

1.1 Sistemas triangulares

Outro caso interessante ocorre quando A é triangular inferior, ou superior, com todos os elementos da dia-gonal não nulos. Nesse caso podemos resolver o sistema por substituição. Vejamos um exemplo triangularsuperior.

a11x1 + a12x2 + a13x3 + a14x4 = b1a22x2 + a23x3 + a24x4 = b2

a33x3 + a34x4 = b3a44x4 = b4.

Nesse caso é fácil achar o valor de x4 usando a última equação. Susbtituindo o valor encontrado napenúltima equação passa a ser fácil encontrar encontrar o valor de x3 e a assim por diante. Obtemos:

1

Page 2: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

x4 = b4/a44

x3 = (b3 − a34x4)/a33

x2 = (b2 − a23x3 − a24x4)/a22

x1 = (b1 − a12x2 − a13x3 − a14x4)/a11.

Isso pode ser facilmente generalizado para o caso de mais variáveis. Chegamos à fórmula

xi =bi − ∑n

j=i+1 aijxj

aii, i = 1, . . . , n. (1)

Agora, o curso de Cálculo Numérico não é apenas um curso de Matemática, então para nós não bastadeduzir as fórmulas, temos que pensar um pouco como implementá-las. Vamos então apresentar umarotina simples que resolve um sistema por (retro) substituição.

In [1]: # Funcao para resolver sistema triangular superior por retro substituicaofunction retro_substituicao(A, b)

n = length(b)x = Array(Float64, n)x[n] = b[n]/A[n, n]for i = n - 1:-1:1

# Note que abaixo usamos a notacao de Julia e outras linguagens# que permite manipular múltiplos elementos de um vetor ou# matriz por vez.x[i] = (b[i] - dot(A[i, i + 1:end], x[i + 1:end]))/A[i, i]

endreturn x

end

# Dados para testeA = [1.0 2 3; 0 3 7; 0 0 7]b = [1.0, 4, 3.2]

# Resolve o sistemasol = retro_substituicao(A, b)println("Solucao obtida é ", sol)

# Verifica a respostaprintln("A*sol, deveria ser igual a b: ", A*sol, b)

Solucao obtida é [-0.734762,0.266667,0.776143]A*sol, deveria ser igual a b: [1.0,4.0,3.6][1.0,4.0,3.2]

Um exercício interessante é escrever a versão do código para resolução de sistemas que são triangularesinferiores. Nesse caso a variável da solução que pode ser obtida imediatamente é x1 e não mais xn. A partirdela se obtém x2 continuando até xn. Que tal fazer isso na caixa de programa abaixo?

In [2]: # Tente implementar e testar uma rotina de substituicao para frente# (para sistemas triangulares inferiores) aqui e faca alguns testes.

2

Page 3: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

1.2 Sistemas gerais

Agora o que fazer quando nos deparamos com um sistema geral como abaixo?2x1 + 3x2 + x3 + x4 = 34x1 + 7x2 + 4x3 + 3x4 = 64x1 + 7x2 + 6x3 + 4x4 = 46x1 + 9x2 + 9x3 + 8x4 = 3.

(2)

Uma abordagem para isso, que é ensinada no ensino médio, é a ideia de escalonamento. Busca-se introdu-zir zeros nos coeficientes da primeira coluna das equações 2 em diante (para baixo). Depois transformamosem zeros os coeficientes da segunda coluna da equação 3 para frente e assim sucessivamente. O objetivo,é claro, é obter um sistema triangular equivalente ao sistema original. Para isso precisamos introduziros zeros usando operações que preservem as soluções do sistema original. Isso pode ser feito usando-seoperações elementares.

1.2.1 Operações elementares

1. Multiplicar uma equação por um escalar não nulo.2. Trocar duas equações de lugar.3. Somar/Subtrair uma equação a outra.

Por exemplo, podemos introduzir um zero no primeiro coeficiente da segunda equação multiplicandoa primeira linha por −2 e somando o resultado a segunda. Obteríamos então o sistema:

2x1 + 3x2 + x3 + x4 = 3+ x2 + 2x3 + x4 = 0

4x1 + 7x2 + 6x3 + 4x4 = 46x1 + 9x2 + 9x3 + 8x4 = 3.

(3)

Outro fato interessante, que pode nos aproximar de uma implementação, é que as variáveis aparecemacima apenas por comodidade ou costume. A única informação que é realmente importante são os coefi-cientes e o lado direito. Isso sugere mais uma vez usar uma representação matricial do sistema. O sistemaoriginal poderia então ser representado por:

2 3 1 1 34 7 4 3 64 7 6 4 46 9 9 8 3.

. (4)

Já o sistema transformado, após colocar um zero na posição (2, 1) seria2 3 1 1 30 1 2 1 04 7 6 4 46 9 9 8 3.

. (5)

É claro que podemos colocar zeros também nas posições 3 e 4 da primeira coluna. Para isso bastasomar à terceira linha mais uma vez −2 vezes a primeira. O coeficiente usado na multiplicação nada maisé do que o negativo valor da posição que se quer zerar divido pelo elemento que está na posição 1 × 1.Já para colocar um zero na posição (4, 1) devemos somar à quarta −3 vezes a primeira. Mais uma vez ocoeficiente −3 usado é obtido através da divisão entre o negativo do número que está na posição que deveser eliminada dividido pelo número que está em (1, 1). Vamos fazer isso, mas usando Julia.

In [3]: # Dados do sistema

A = [2.0 3 1 1; 0 1 2 1; 4 7 6 4; 6 9 9 8]b = [3.0, 0, 4, 3]

3

Page 4: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

b = reshape(b, 4, 1)println("Sistema")sistema = [A b]

Sistema

Out[3]: 4Œ5 Array{Float64,2}:2.0 3.0 1.0 1.0 3.00.0 1.0 2.0 1.0 0.04.0 7.0 6.0 4.0 4.06.0 9.0 9.0 8.0 3.0

In [4]: # Introduzindo zero na posicao (3, 1)

sistema[3, :] = sistema[3, :] - sistema[3,1]/sistema[1,1]*sistema[1, :]println("Sistema")sistema

Sistema

Out[4]: 4Œ5 Array{Float64,2}:2.0 3.0 1.0 1.0 3.00.0 1.0 2.0 1.0 0.00.0 1.0 4.0 2.0 -2.06.0 9.0 9.0 8.0 3.0

In [5]: # Introduzindo zero na posicao (4, 1)

sistema[4, :] = sistema[4, :] - sistema[4, 1]/sistema[1,1]*sistema[1, :]println("Sistema:")sistema

Sistema:

Out[5]: 4Œ5 Array{Float64,2}:2.0 3.0 1.0 1.0 3.00.0 1.0 2.0 1.0 0.00.0 1.0 4.0 2.0 -2.00.0 0.0 6.0 5.0 -6.0

Assim, ao terminarmos de colocar zeros na primeira coluna abaixo da posição (1, 1), obtemos2 3 1 1 30 1 2 1 00 1 4 2 −20 0 6 5 −6

. (6)

O próximo passo para se obter um sistema triangular é colocar zeros abaixo da posição (2, 2). Isso podeser obtido somando à terceira linha o inverso da segunda. Por sorte, o elemento na posição (4, 2) já é zeroe não precisa ser modificado. Fazemos então:

In [6]: # Introduzindo zero na posicao (3, 2)

sistema[3,:] = sistema[3, :] - sistema[3, 2]/sistema[2, 2]*sistema[2, :]println("Sistema:")sistema

4

Page 5: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Sistema:

Out[6]: 4Œ5 Array{Float64,2}:2.0 3.0 1.0 1.0 3.00.0 1.0 2.0 1.0 0.00.0 0.0 2.0 1.0 -2.00.0 0.0 6.0 5.0 -6.0

Terminamos o processo introduzindo um zero na posição (4, 3) usando um múltiplo da linha 3.

In [7]: # Introduzindo zero na posicao (4, 3)

sistema[4, :] = sistema[4, :] - sistema[4, 3]/sistema[3, 3]*sistema[3, :]println("Sistema:")sistema

Sistema:

Out[7]: 4Œ5 Array{Float64,2}:2.0 3.0 1.0 1.0 3.00.0 1.0 2.0 1.0 0.00.0 0.0 2.0 1.0 -2.00.0 0.0 0.0 2.0 0.0

Ao final temos o sistema 2 3 1 1 30 1 2 1 00 0 2 1 −20 0 0 2 0

. (7)

Ou usando a notação mais usual2x1 + 3x2 + 1x3 + 1x4 = 3

+ 1x2 + 2x3 + 1x4 = 02x3 + 1x4 = −2

2x4 = 0.

(8)

O sistema triangular superior que está pronto para ser resolvido por retro-substituição, apresentadaacima. É claro que podemos escrever um programa em Julia que faz tudo de uma vez, pegando um sistemaoriginal e devolvendo a versão escalonada.

In [8]: # Escalonamento em Juliafunction escalonamento(A, b)

n = length(b)sistema = [copy(A) reshape(copy(b), n, 1)]# Coloca zeros abaixo da posicao i x i usando a linha ifor i = 1:n - 1

coefs = sistema[i + 1:end, i]/sistema[i, i]sistema[i + 1:end, i] = 0.0sistema[i + 1:end, i + 1:end] -= coefs * sistema[i, i + 1:end]'

endreturn sistema

end

5

Page 6: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

A = [2.0 3 1 1; 4 7 4 3; 4 7 6 4; 6 9 9 8]b = [3.0, 6, 4, 3]print("Sistema escalonado:")escalonamento(A, b)

Sistema escalonado:

Out[8]: 4Œ5 Array{Float64,2}:2.0 3.0 1.0 1.0 3.00.0 1.0 2.0 1.0 0.00.0 0.0 2.0 1.0 -2.00.0 0.0 0.0 2.0 0.0

Veja que o sistema obtido ao final é examente o desejado.O código acima exige alguns comentários para explicar o que ocorre no laço for. A primeira linha

dentro do for calcula os coeficientes que serão usados para multiplicar pela linha i (e depois somar nasdebaixo). É interessante porque podemos calcular todos de uma vez. A segunda linha coloca zeros abaixoda posição (i, i). Já sabemos que esses zeros vão aparecer lá, pois foi com esse objetivo que definimos oscoeficientes. A última linha atualiza a matriz. Para entendê-la temos que entender como Julia interpreta umvetor * um vetor transposto. Julia faz o mais natural em Matemática que é considerar o vetor como umamatriz composta de uma única coluna e multiplica essa matriz pela de uma única linha gerada pelo vetortransposto. Com isso Julia gera uma matriz que tem dimensões iguais a número de elementos do primeirovetor vezes o número de elementos do segundo vetor. A matriz resultante tem cada linha formada pelamultiplicações do respectivo coeficiente pelo vetor transposto, que é exatamente o que queremos somar nosistema original. Veja o exemplo abaixo para isso ficar mais claro. Isso em Matemática é conhecido comoum produto externo.

In [9]: M = collect(1:9)

Out[9]: 9-element Array{Int64,1}:123456789

In [10]: coefs = collect(1:5)

Out[10]: 5-element Array{Int64,1}:12345

In [11]: coefs * M'

Out[11]: 5Œ9 Array{Int64,2}:1 2 3 4 5 6 7 8 92 4 6 8 10 12 14 16 183 6 9 12 15 18 21 24 274 8 12 16 20 24 28 32 365 10 15 20 25 30 35 40 45

6

Page 7: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

1.3 Fatoração LU

Se A é uma matriz, uma fatoração de A é um produto de outras matrizes, geralmente mais simples, queresulta em A. Isso é análogo ao caso de números inteiros que são fatorados em números primos.

Um fato interessante sobre o processo de escalonamento é que ele encontra, implicitamente, uma fato-ração especial de A. Se organizarmos as contas de escalonamento podemos mostrar que ela encontra umamatriz triangular inferior L e outra superior U tal que

A = LU.

Para vermos que isso é verdade vamos analisar como representar cada operação realizada pelo escalo-namento através de produtos de matrizes. Com esse objetivo vamos pensar o que ocorre quando multipli-camos uma matriz A à esquerda por uma outra matriz que é igual à identidade a menos de uma posiçãofora da diagonal. Por exemplo

1 0 0 00 1 0 0

−2 0 1 00 0 0 1

2 3 1 14 7 4 34 7 6 46 9 9 8

.

Trabalhando um pouco nesse exemplo você verá que a matriz resultante é igual a matriz da direita com aterceira linha trocada pela linha que estava lá menos 2 vezes a primeira linha, ou seja

2 3 1 14 7 4 30 1 4 26 9 9 8

.

De uma maneira geral, de multiplicarmos uma matriz A à esquerda por uma matriz igual à identidadea menos de um elemento c na posição (i, j), obteremos uma matriz igual com a linha i trocada por elamesma somada a c vezes a linha j. Esse é exatamente o tipo de operação usada pelo escalonamento. Elapode ser interpretada como uma sequência de operações elementares do tipo multiplicar uma linha por umnúmero não nulo e trocar uma linha por ela mesma mais outra. Logo o processo de escalonamento pode serrepresentada por multiplicações por matrizes. Por exemplo, para preencher com zeros a primeira colunada matriz original acima, começando pela posição (2, 1) até a posição (4, 1) bastaria considerar os seguintesprodutos por matrizes (leia da direita para a esquerda para entender mais facilmente).

1 0 0 00 1 0 00 0 1 0

−3 0 0 1

︸ ︷︷ ︸

L41

1 0 0 00 1 0 0

−2 0 1 00 0 0 1

︸ ︷︷ ︸

L31

1 0 0 0

−2 1 0 00 0 1 00 0 0 1

︸ ︷︷ ︸

L21

2 3 1 14 7 4 34 7 6 46 9 9 8

︸ ︷︷ ︸

A

=

2 3 1 10 1 2 10 1 4 20 0 6 5

.

A notacão Lij representa matriz que coloca zero na posição (i, j). De fato vamos verificar isso computacio-nalmente.

In [12]: A = [2 3 1 1; 4 7 4 3; 4 7 6 4; 6 9 9 8]L21 = eye(4, 4)L21[2, 1] = -2L31 = eye(4, 4)L31[3, 1] = -2L41 = eye(4, 4)L41[4, 1] = -3

L41*(L31*(L21*A))

7

Page 8: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Out[12]: 4Œ4 Array{Float64,2}:2.0 3.0 1.0 1.00.0 1.0 2.0 1.00.0 1.0 4.0 2.00.0 0.0 6.0 5.0

Compare o resultado obtido com o resultado do processo de escalonamento depois de colocar zerosabaixo do primeiro elemento da diagonal acima. Veja que a matriz de partida é a mesma. Outro fatointeressante sobre as matrizes L1, L2, L3 acima é que o seu produto é particularmente simples.

1 0 0 00 1 0 00 0 1 0

−3 0 0 1

︸ ︷︷ ︸

L41

1 0 0 00 1 0 0

−2 0 1 00 0 0 1

︸ ︷︷ ︸

L31

1 0 0 0

−2 1 0 00 0 1 00 0 0 1

︸ ︷︷ ︸

L21

=

1 0 0 0

−2 1 0 0−2 0 1 0−3 0 0 1

︸ ︷︷ ︸

L1

.

Basta copiar abaixo da primeira diagonal da identidade os coeficientes que aparecem nas três matrizesna sua posição natural, formando assim a matriz que zera os elementos desejados da coluna 1. Vamoschamar essa matriz de L1. Para entender o porque isso acontece basta interpretar o produto da direita paraa esquerda. Podemos mais uma vez confirmar isso computacionalmente.

In [13]: L1 = L41*L31*L21

Out[13]: 4Œ4 Array{Float64,2}:1.0 0.0 0.0 0.0

-2.0 1.0 0.0 0.0-2.0 0.0 1.0 0.0-3.0 0.0 0.0 1.0

Outro fato interessante sobre as matrizes que se combinam para formar L1 é que suas inversas são fáceisde calcular. Basta inverter o elemento de fora da diagonal. Por exemplo

L−131 =

1 0 0 00 1 0 02 0 1 00 0 0 1

.

Confirmando:

In [14]: L31menos1 = eye(4, 4)L31menos1[3, 1] = 2

L31menos1*L31

Out[14]: 4Œ4 Array{Float64,2}:1.0 0.0 0.0 0.00.0 1.0 0.0 0.00.0 0.0 1.0 0.00.0 0.0 0.0 1.0

Isso pode ser entendido porque essa mudança de sinal desfaz a operação elementar representa por essasmatrizes. Pense um pouco.

Agora lembrando que o inverso de um produto é o produto invertido das inversas termos

L−11 = (L41L31L21)

−1 = L−121 L−1

31 L−141 =

1 0 0 02 1 0 02 0 1 03 0 0 1

.

8

Page 9: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

De novo ocorre o fenômeno que é simples multiplicar essas matrizes, basta copiar os elementos adequadosnas respostas.

O restante do processo de escalonamento também pode continuar sendo representado por multiplicaçãopor matrizes desse tipo. Continuamos o processo colocando zeros abaixo do segundo elemento da diagonale por fim abaixo do terceiro. O processo todo seria então representado pelo produto.

1 0 0 00 1 0 00 0 1 00 0 −3 1

︸ ︷︷ ︸

L43︸ ︷︷ ︸L3

1 0 0 00 1 0 00 0 1 00 0 0 1

︸ ︷︷ ︸

L42

1 0 0 00 1 0 00 −1 1 00 0 0 1

︸ ︷︷ ︸

L32︸ ︷︷ ︸L2

L1

2 3 1 14 7 4 34 7 6 46 9 9 8

︸ ︷︷ ︸

A

=

2 3 1 10 1 2 10 0 2 10 0 0 2

.

In [15]: L2 = eye(4, 4)L2[3, 2] = -1L2[4, 2] = 0L3 = eye(4, 4)L3[4, 3] = -3

(L3*(L2*(L1*A)))

Out[15]: 4Œ4 Array{Float64,2}:2.0 3.0 1.0 1.00.0 1.0 2.0 1.00.0 0.0 2.0 1.00.0 0.0 0.0 2.0

Agora, vamos partir dessa última equação. Temos

L3L2L1 A = U,

em que U é a matriz triangular superior que obtemos ao final do processo de escalonamento. Podemosentão passar o produto das matrizes Lk para o outro lado, usando suas inversas, que sabemos como calcular.Obtendo:

A = L−11 L−1

2 L−13 U.

Mais uma vez há um "golpe de sorte"e o produto L−11 L−1

2 L−13 também tem uma expressão particularmente

simples, bastando copiar os elementos que aparecem abaixo das diagonais de cada uma dessa matrizesna resposta. Isso ocorre porque o produto L−1

k . . . L−1n−1 é composto por matrizes que têm zeros abaixo da

diagonal na coluna k− 1, já que nessas posições sempre houve 0 nas linhas que já foram combinadas. Agoraquando se multiplica essa matriz intermediária à esquerda por Lk−1 na coluna k − 1 apenas os elementos deLk−1 que estão estão abaixo da diagonal na coluna k − 1 irão importar, sendo diretamente copiados. Façauns exemplos manualmente para se convencer disso. Já a confirmação numérica podemos fazer agora.

In [16]: inv(L3*L2*L1)

Out[16]: 4Œ4 Array{Float64,2}:1.0 0.0 0.0 0.02.0 1.0 0.0 0.02.0 1.0 1.0 0.03.0 0.0 3.0 1.0

De fato a inversa obtida também é uma matriz triangular inferior com os elementos das matrizes inver-sas copiados. A essa matriz L−1

1 L−12 . . . L−1

n−1 vamos chamar de matriz L. Dessa forma obtermos justamentea expressão desejada:

A = LU.

9

Page 10: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Não podemos deixar de observar que talvez fosse mais natural nomear a matriz L−11 L−1

2 . . . L−1n−1 de L−1.

Isso não é feito para evitar uma notação pesada na importante igualdade A = LU.Deste modo fica natural adaptar o código de escalonamento para calcular a fatoração LU de uma matriz.

Para isso basta guardar os coeficientes usados, com sinal adequado, na matriz L. A matriz U é a matriztriangular superior final.

In [17]: # Fatoracao LU de uma matriz A sem pivoteamentofunction preLU(A)

# Reserva espaco para a respostan = size(A)[1]L = eye(n)U = copy(A)# Coloca zeros abaixo da posicao i x i usando a linha ifor i = 1:n - 1

coefs = U[i + 1:end, i] / U[i, i]L[i + 1:end, i] = coefsU[i + 1:end, i] = 0.0U[i + 1:end, i + 1:end] -= coefs * U[i, i + 1:end]'

endreturn L, U

end

A = [2.0 3 1 1; 4 7 4 3; 4 7 6 4; 6 9 9 8]b = [3.0, 6, 4, 3]L, U = preLU(A);

In [18]: L

Out[18]: 4Œ4 Array{Float64,2}:1.0 0.0 0.0 0.02.0 1.0 0.0 0.02.0 1.0 1.0 0.03.0 0.0 3.0 1.0

In [19]: U

Out[19]: 4Œ4 Array{Float64,2}:2.0 3.0 1.0 1.00.0 1.0 2.0 1.00.0 0.0 2.0 1.00.0 0.0 0.0 2.0

In [20]: L*U

Out[20]: 4Œ4 Array{Float64,2}:2.0 3.0 1.0 1.04.0 7.0 4.0 3.04.0 7.0 6.0 4.06.0 9.0 9.0 8.0

Vejam que de fato LU é igual à matriz A original. Na verdade, essa igualdade absoluta é obtida nessecaso por que todas as contas, apesar de serem feitas com ponto flutante, geraram números inteiros quepodem ser representados. De uma forma geral esperamos que o resultado final sejam aproximadamente aL e a U desejadas. Voltaremos a discutir erros depois.

10

Page 11: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

1.4 Utilizando a fatoração LU para resolver sistemas

Começamos essa discussão falando sobre a solução de sistemas lineares mas fizemos um desvio acimapara comentar sobre uma fatoração de matrizes. Vamos agora voltar a trilha original, vendo como usar afatoração LU para resolver um sistema linear. Desejamos encontrar x tal que

Ax = b.

Isso é equivalente a buscar x tal queLUx = b.

Como lidar com sistemas que tem produtos de matrizes como acima? Uma ideia é criar variáveis interme-diárias, resolvendo o sistema da esquerda para a direita. Por exemplo, no caso acima podemos inicialmentebuscar y tal que

Ly = b.

Isso é fácil de calcular porque o sistema é triangular inferior. Depois disso resolvemos

Ux = y.

Assim, obtemos o x desejado, solução do sistema original. Note que de novo basta resolver um sistematriangular, mas agora superior. De fato colocando as duas últimas expressões juntas temos

Ux = y =⇒ L(Ux) = b =⇒ Ax = b.

A primeira implicação usa a definição de y. Mais uma vez, podemos ver isso funcionando usando o códigoque já desenvolvemos até aqui.

In [21]: # Alem da rotina de retro substituicao para a resolucao de sistemas# triangulares superiores precisamos de uma outra que faca a resolucao# de sistemas triangulares inferiores. Isso tinha ficado como exercicio# antes e agora voces podem ver uma resposta.function substituicao(A, b)

n = length(b)x = Array(Float64, n)x[1] = b[1]/A[1, 1]for i = 2:n

x[i] = (b[i] - dot(A[i, 1:i], x[1:i]))/A[i, i]endreturn x

end

# Por fim, usamos as rotinas implementadas até agora para resolver um# sistema linear.A = [2.0 3 1 1; 4 7 4 3; 4 7 6 4; 6 9 9 8]b = [3.0, 6, 4, 3]L, U = preLU(A)y = substituicao(L, b)x = retro_substituicao(U, y)println("Solucao = ", x)println("Verificacao, Ax = ", A*x)

Solucao = [-1.0,2.0,-1.0,0.0]Verificacao, Ax = [3.0,6.0,4.0,3.0]

Um fato que pode ser importante em alguns casos é que uma vez calculada a fatoração LU de umamatriz ela pode ser utilizada sempre no lugar de A. Assim, por exemplo, se quisermos resolver sistemaslineares com diferentes lados direitos (diferentes vetores b) a fatoração pode ser feita uma única vez.

11

Page 12: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

1.5 Tempo de execução (complexidade)

Ao escrevermos programas de computador é importante que tenhamos uma ideia do seu tempo de execu-ção. Muitas vezes não basta inventar um algoritmo que esteja correto, é preciso que ele seja eficiente. Issoé um pouco menos importante nos dias de hoje do que era há algumas décadas, já que os computadoresestão muito mais poderosos. Mas ainda é fácil escrever programas que demoram demais para realizar assuas tarefas.

Quando falamos em programas numéricos, cujo principal objetivo é realizar longas sequencias de cálcu-los, podemos buscar adquirir uma ideia do tempo de execução ou complexidade de um algoritmo atravésda contagem do número de operações de ponto flutuantes realizadas. Isso é apenas uma aproximação dacomplexidade total do processo, já que outras operações que não envolvem cálculos com números reaisnão são contadas. Isso pode ser particularmente dramático por desprezar a movimentação de dados en-tre a memória e o processador, algo que é muito demorado em computadores modernos. A contagem donúmero de operações continua sendo usada, porém, porque geralmente uma implementação cuidadosa deum método numérico é tipicamente limitada por essas operações.

Usaremos a sigla FLOP (de Foating Point OPeration) para designar uma operação básica de ponto flutu-ante como a soma, subtração, multiplicação, divisão ou extração de raiz quadrada. Nosso objetivo nessaseção é contar a quantidade de FLOPs de cada um dos principais algoritmos implementados até agora.

1.5.1 Substituição

Vamos começar pela retro_substituicao. Olhando o seu código, vemos que a maior parte do trabalhoocorre dentro do laço for. Para calcular o novo x[i] precisamos executar uma subtração, uma divisão eo produto interno dot(A[i, i + 1:end], x[i + 1:end]) entre dois vetores de n − (i + 1) + 1 = n − ielementos. Esse produto interno precisa então de n − i produtos de números reais e n − i − 1 somas. O totalde operações realizadas nessa linha é então 2 + (n − i) + (n − i − 1) = 2(n − i) + 1. Dessa forma, podemoscalcular o trabalho total:

n

∑i=1

2(n − i) + 1 =n

∑i=1

(2n + 1)− 2n

∑i=1

i = n(2n + 1)− n(n + 1) = n2.

Obs: vejam que usei o i variando de 1 até n, isso foi feito para contar também a primeira operação feita,para calcular o x[n] que está fora do laço.

Vejam que o tempo é bem razoável, afinal uma matriz triangular tem cerca de n2/2 entradas não nulas,então fazemos cerca de duas operações de ponto flutuante (FLOPs) por entrada da matriz. É difícil imaginaralgo muito melhor do que isso.

Por fim, como o algoritmo de substituicao (para frente) é apenas uma versão invertida daretro_substituicao, o número de operações será o mesmo. Faça os detalhes como exercício.

1.5.2 Fatoração LU

Agora vamos para algo mais desafiador. Vamos tentar avaliar o tempo gasto na rotina preLU. De novo elatem um único laço. Na primeira linha desse laço são executadas n − 1 divisões para calcular os coeficientes.Depois na quarta linha fazemos primeiro o produto externo de dois vetores (n - 1) o que precisa de (n − i)2

produtos. Por fim atualizamos a matriz U com (n − i)2 subtrações, totalizado

2(n − i)2 + (n − i)

FLOPs. Note que a segunda e terceira linha do laço não geram FLOPs, são realizadas apenas cópias devalores em memória. Estamos prontos para escrever a somatória que irá acumular todo o trabalho feito.

n−1

∑i=1

2(n − i)2 + (n − i) = [2(n − 1)2 + (n − 1)] + [2(n − 2)2 + (n − 2)] + . . . + [2 · 22 + 2] + [2 · 12 + 1].

Note que lendo essa somatória de trás para frente chegamos a uma expressão um pouco mais simples.

n−1

∑i=1

2i2 + i.

12

Page 13: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Aqui nos deparamos com uma dificuldade. Como calcular a soma ∑ni=1 i2? Isso tem uma resposta

conhecida que én

∑i=1

i2 =n(n + 1)(2n + 1)

6.

Você pode encontrar várias demonstrações disso. Um exemplo legal é essa. Mas há várias outras demons-trações.

Retornando ao nosso problema queremos

n−1

∑i=1

2i2 + i =(n − 1)n(2n − 1)

3+

(n − 1)n2

= (n − 1)n(

2n − 13

+12

)= (n − 1)n

(2n3

+16

)=

2n3

3− n2

2− n

6

≈ 2n3

3.

A aproximação final vale para n grande, que é o que interessa quando o problema aumenta.De fato, em geral nós estamos interessados apenas nos termos de maior grau, assim podemos simplificar

muito as contas eliminando termos intermediários que não serão importantes (para n grande). As contasacima ficariam com algo como

n−1

∑i=1

2i2 + i ≈n−1

∑i=1

2i2

= 2(n − 1)n(2n − 1)

6

≈ 2n3

3.

Note que o tempo de calcular uma fatoração LU é muito maior do que o tempo de resolver um sistematriangular por substituição, afinal ele cresce com o cubo da dimensão da matriz. Isso mostra que, pararesolver um sistema linear fazendo primeiro a fatoração LU, a maior parte do trabalho está no processo defatoração. Ele irá dominar o tempo de execução.

1.6 Pivoteamento

O processo de fatoração LU descrito parece de fato muito interessante. Uma pergunta natural é se essafatoração existe para qualquer matriz quadrada. A resposta para isso pode ser retirada do próprio processode fatoração. Olhando o algoritmo vemos que o algoritmo consegue ir até o fim se, e somente se, a cadaiteração o termo aii usando para calcular os coeficientes for não nulo. Ou seja o algoritmo irá falhar se, esomente se, após k − 1 iterações encontrarmos a seguinte situação:

U =

X X X X . . . X X . . . X0 X X X . . . X X . . . X0 0 X X . . . X X . . . X...

.... . . . . . . . .

...... . . . X

0 0 0 . . . 0 X X . . . X...

......

... X X X . . . X0 0 0 0 X X X . . . X

.

13

Page 14: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Acima os elementos potencialmente não nulos estão denotados por X e a linha e coluna k estão destacadas.Agora na k-ésima iteração o objetivo é zerar os elementos abaixo da posição k × k usando o elemento da

diagonal que infelizmente é 0 e o algoritmo não pode continuar. Em particular a porção superior esquerdacom k linhas e k colunas dessa matriz, que vamos denotar por Uk, foi obtida através de um processo deescalonamento da mesma porção da matriz original, isso é de A[1 : k, 1 : k]. Relembrando a discussão quenos levou a descobrir a ideia da fatoração LU isso nos ensina que existem matrizes L1, . . . , Lk−1 ∈ Rk×k

inversíveis tais queLk−1 . . . L1 A[1 : k, 1 : k] = U[1 : k, 1 : k].

Como as matrizes Li, i = 1, . . . , k − 1 são inversíveis e a matriz U[1 : k, 1 : k] não é inversível pois tem aúltima linha de zeros, vemos que a matriz A[1 : k, 1 : k] também não é inversível. Isso pode ser confirmadode muitas formas. Por exemplo lembrando que um sistema baseado em A[1 : k, 1 : k] e em U[1 : k, 1 : k] temque ter as mesmas soluções, com possíveis adaptações do lado direito. Claramente um sistema baseado emU[1 : k, 1 : k] pode ter nenhuma ou infinitas soluções, mas nunca solução única. Isso caracteriza uma matriznão inversível. Outra forma ainda mais fácil é usar a propriedade que o determinante de um produto dematrizes é igual ao produto dos determinantes e lembrar do fato que uma matriz é inversível se, e somente,se seu determinante for não nulo. Isso nos leva ao seguinte resultado:

Teorema. Uma matriz A ∈ Rn×n pode ser fatorada pelo algoritmo preLU, que chamaremos de fatoraçãoLU sem pivoteamento, se, e somente se, as submatrizes A[1 : k, 1 : k], k = 1 . . . n − 1, tiverem determinantesnão nulos.

Obs: Os determinantes das submatrizes A[1 : k, 1 : k], k = 1 . . . n são conhecidos como menores principaisde A.

Mas o que fazer nesse caso? Olhando de novo para a matriz acima, podemos ter a ideia de tentarprocurar na coluna k abaixo da diagonal um elemento não nulo de A. Se isso for possível, trocamos a linhak pela linha desse elemento (que seria equivalente a trocar duas equações de posição no sistema linear) eobtemos um sistema equivalente para o qual o algoritmo pode continuar. Essa operação de troca é de novouma operação elementar, que pode ser representada por uma matriz identidade com as respectivas linhastrocadas, multiplicada à esquerda. Verifique.

A aplicação dessa regra permite calcular uma fatoração LU, não mais de A mas de uma versão de Acom linhas permutadas. Esse tipo de matriz pode ser representado pela multiplicação à esquerda de A poruma matriz de permutação P que é uma matriz identidade com linhas trocadas de lugar representando asvárias trocas de linhas necessárias para levar o processo à cabo. Ou seja, ao final obteremos algo na forma

PA = LU.

Mais uma vez vemos que agora o método só pára se não encontrar nenhum elemento não nulo daposição k × k para baixo, ou seja se a matriz parcial tiver a forma

U =

X X X X . . . X X . . . X0 X X X . . . X X . . . X0 0 X X . . . X X . . . X...

.... . . . . . . . .

...... . . . X

0 0 0 . . . 0 X X . . . X...

......

...... X X . . . X

0 0 0 0 0 X X . . . X

.

Mas essa matriz tem determinante nulo. Para ver isso, comece fazendo a expansão do seu determinantepela primeira coluna. Como a coluna é quase inteira de zero vemos que esse determinante é o u11 det(U[2 :n, 2 : n]). Continuando esse processo até a coluna k obtemos

det(U) = u11u22 . . . ukk det(u[k + 1 : n, k + 1 : n]) = 0.

A última igualdade vem do fato que ukk = 0.Concluímos que o processo de fatoração LU com pivoteamento parcial somente pára se a matriz U en-

contrada for não inversível. Mais uma vez essa matriz é obtida a partir de A pelo produto de matrizes

14

Page 15: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

triangulares inversíveis e portanto concluímos que o processo somente pára se A é não inversível. Prova-mos um novo resultado.

Teorema Se uma matriz A ∈ Rn×n for inversível, então ela admite fatoração LU com pivoteamentoparcial.

Nosso próximo desafio é adaptar a rotina preLU para incorporar o pivoteamento parcial. Para isso énecessário guardar a informação de onde as linhas foram parar, e trocar linhas de U e L quando o pivotea-mento for feito. Veja abaixo

In [22]: # Fatoracao LU de uma matriz A com pivoteamento parcialfunction LU(A)

# Reserva espaco para a respostan = size(A)[1]# Cria um vetor para guardar a posição das linhasP = collect(1:n)L = eye(n)U = copy(A)# Coloca zeros abaixo da posicao i x i trazendo para linha i a com# maior pivot.for i = 1:n - 1

# Busca o maior pivot em valor absolutomaxind = indmax(abs(U[i:end, i])) + i - 1# Troca as linhas de lugar e guarda a informação.U[i, i:end], U[maxind, i:end] = U[maxind, i:end], U[i, i:end]L[i, 1:i-1], L[maxind, 1:i-1] = L[maxind, 1:i-1], L[i, 1:i-1]P[i], P[maxind] = P[maxind], P[i]# Continua com a fatoração LU.coefs = U[i + 1:end, i] / U[i, i]L[i + 1:end, i] = coefsU[i + 1:end, i] = 0.0U[i + 1:end, i + 1:end] -= coefs * U[i, i + 1:end]'

endreturn P, L, U

end

#A = [2.0 3 1 1; 4 7 4 3; 4 7 6 4; 6 9 9 8]A = [1.0 2 1 1; 2 3 1 1; 2 4 5 1; 1 1 1 1]b = [3.0, 6, 4, 3]P, L, U = LU(A);

In [23]: P

Out[23]: 4-element Array{Int64,1}:2341

In [24]: L

Out[24]: 4Œ4 Array{Float64,2}:1.0 0.0 0.0 0.01.0 1.0 0.0 0.00.5 -0.5 1.0 0.00.5 0.5 -0.6 1.0

In [25]: U

15

Page 16: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Out[25]: 4Œ4 Array{Float64,2}:2.0 3.0 1.0 1.00.0 1.0 4.0 0.00.0 0.0 2.5 0.50.0 0.0 0.0 0.8

In [26]: L*U

Out[26]: 4Œ4 Array{Float64,2}:2.0 3.0 1.0 1.02.0 4.0 5.0 1.01.0 1.0 1.0 1.01.0 2.0 1.0 1.0

Note que a matriz LU obtida ao final é igual à matriz A com a primeira linha trocada com a quarta,como está indicado no vetor que guardas as permutações P.

Como podemos usar isso para resolver um sistema Ax = b? Como a matriz LU ao final representao mesmo sistema com algumas equações com ordem trocada, basta aplicar a mesma troca de ordem paracomponentes de b e resolver o sistema usando LU. Vejamos a implementação.

In [27]: # Resolve sistema Ax = b por LU com pivoteamento parcial.function resolve_LU(A, b)

P, L, U = LU(A)# Troca as coordenadas de b de lugar.b = b[P]y = substituicao(L, b)x = retro_substituicao(U, y)return x

end

# Por fim, usamos as rotinas implementadas até agora para resolver um sistema linea.A = [2.0 3 1 1; 4 7 4 3; 4 7 6 4; 6 9 9 8]b = [3.0, 6, 4, 3]x = resolve_LU(A, b)println("Solucao = ", x)println("Verificacao, Ax = ", A*x)

Solucao = [-1.0,2.0,-1.0,-0.0]Verificacao, Ax = [3.0,6.0,4.0,3.0]

1.6.1 Pivoteamento completo

Uma alternativa ao pivoteamento parcial é o pivoteamento completo. Nessa variação, no início da iteraçãok o algoritmo não procura trazer para a posição (k, k) da diagonal o maior elemento em módulo da da parteda colua k de U que está abaixo da diagonal. Podemos querer ser mais gulosos e procurar o maior elementoem toda a porção inferior direita de U, ou seja em U[k : n, k : n]. Imagine que esse elemento está na posição(i, j). Podemos trazer esse elemento para a posição (k, k) trocando a linha i com a k de lugar e depois ascolunas j e k. Esse método pode continuar sempre, a menos que toda a matriz U[k : n, k : n] seja composta

16

Page 17: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

por zeros, ou seja o algoritmo só para se ele se deparar com a configuração

U =

X X X X . . . X X . . . X0 X X X . . . X X . . . X0 0 X X . . . X X . . . X...

.... . . . . . . . .

...... . . . X

0 0 0 . . . 0 0 0 . . . 0...

......

...... 0 0 . . . 0

0 0 0 0 0 0 0 . . . 0

.

Mas nesse caso a matriz U já é triangular superior! O método pode parar pois não há mais o que fazer.Observe ainda que já sabíamos que o processo de troca de duas linhas pode ser representado pela multi-plicação à esquerda de uma matriz permutação obtida da identidade trocando-se duas de suas linhas. Jáa troca de colunas pode ser representada por uma multiplicação por uma matriz de permutação à direita.Isso pode ser explorado para provar o seguinte teorema:

Teorema Toda matriz quadrada A ∈ Rn×n admite uma fatoração LU com pivoteamento completo. Ouseja, existem matrizes de permutação P e Q, obtidas trocando-se linhas e colunas da matriz identidade delugar, uma matriz triangular inferior L e uma matriz triangular superior U tal que

PAQ = LU.

2 Erros numéricos e número de condição

Bom, conseguimos então escrever uma rotina que é capaz de calcular a fatoração PLU de qualquer matrizinversível dada. Ela pode então ser usada para resolver sistemas. Porém, a necessidade de pivoteamentofoi introduzida apenas em um caso muito radical, que é quando o elemento da diagonal encontrado é 0.Já a implementação faz algo ainda mais robusto. Ela sempre traz para a diagonal o maior elemento emmódulo. Será que isso era realmente necessário? Ou será que estamos fazendo trabalho à toa e deveríamosmover elementos apenas no caso de encontrar zero?

Vamos pensar um pouco analisando o seguinte caso.

In [28]: A = [1.0e-20 1; 1 1]

Out[28]: 2Œ2 Array{Float64,2}:1.0e-20 1.01.0 1.0

In [29]: L, U = preLU(A)L

Out[29]: 2Œ2 Array{Float64,2}:1.0 0.01.0e20 1.0

In [30]: U

Out[30]: 2Œ2 Array{Float64,2}:1.0e-20 1.00.0 -1.0e20

In [31]: L*U

Out[31]: 2Œ2 Array{Float64,2}:1.0e-20 1.01.0 0.0

17

Page 18: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Notem que a matriz LU obtida é muito diferente de A, isso pode ser visto claramente comparando oselementos (2, 2). Como entender o que aconteceu? Nesse caso a única coisa que o algoritmo preLU faz éalterar a última linha para

[1.0, 1.0]− 1020[10−20, 1].

Se as contas tivessem sido realizadas exatamente teríamos ao final

[0, 1 − 1020].

Porém as contas não são realizadas exatamente, elas são realizadas em ponto flutuante no computador esabemos que a precisão é de cerca de 16 casas decimais (ϵmac ≈ 10−16). Nesse caso o 1 é tão menor emmódulo que o −1020 que ele acaba sendo ignorado. Mas depois ele faz falta ao se tentar remontar a matrizA a partir dos seus fatores. A situação também se mostra muito ruim se tentamos usar os fatores calculadospara resolver um sistema

In [32]: b = [1.0, 0]y = substituicao(L, b)x = retro_substituicao(U, y)println("b = ", b)println("Solucao = ", x)println("Verificacao, Ax = ", A*x)

b = [1.0,0.0]Solucao = [0.0,1.0]Verificacao, Ax = [1.0,1.0]

Note que o valor do Ax obtido, aproximadamente (1, 1)′, é muito diferente do lado direito original(1, 0)′. Isso pode sempre ocorrer quando o valor o pivot for muito pequeno em módulo, já que ele entradividindo a linha da matriz que será somada às outras. Nesse caso a linha dividida pelo pivot pode ficarmuito grande e ao usar esses coeficientes para gerar a linha que será somada às outras essa linha fica tãogrande que tende a apagar a informação das demais. Isso mostra que não devemos apenas trocar linhasquando o valor na diagonal for 0, queremos também evitar valores pequenos. Este é o motivo de porque édesejável sempre trocar as linhas de forma a trazer o maior valor possível para a posição do pivot. De fatoveja o que obteríamos se usássemos a rotina com pivoteamento parcial.

In [33]: P, L, U = LU(A)L

Out[33]: 2Œ2 Array{Float64,2}:1.0 0.01.0e-20 1.0

In [34]: U

Out[34]: 2Œ2 Array{Float64,2}:1.0 1.00.0 1.0

In [35]: L*U

Out[35]: 2Œ2 Array{Float64,2}:1.0 1.01.0e-20 1.0

Veja que a matriz LU obtida recupera a matriz A original com as linhas trocadas como esperado. Alémdisso se resolvermos o sistema teremos.

18

Page 19: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

In [36]: x = resolve_LU(A, b)println("b = ", b)println("Solucao = ", x)println("Verificacao, Ax = ", A*x)

b = [1.0,0.0]Solucao = [-1.0,1.0]Verificacao, Ax = [1.0,0.0]

Veja que agora o valor correto do lado direito correto é recuperado.

2.0.1 Número de condição

Vimos anteriormente que a menos que tomemos cuidado de fazer pivoteamento parcial a fatoração LUpode falhar em resolver sistemas lineares simples. Pelo menos a precisão final obtida pode ser muito ruim.

Vamos agora ver que há sistemas lineares que tem uma propriedade intrínseca que impede que elessejam resolvidos com alta precisão. Para entender isso vamos apresentar dois casos de sistemas no plano erelembrar um pouco sobre a sua solução geométrica.

Dado um sistema de duas equações e duas icógnitas, por exemplo

x + y = 2x − 2y = −1.

Aprendemos que podemos resolvê-lo graficamente desenhando as retas que representam cada uma dasduas equações e procurando o seu ponto de cruzamento. Nesse caso teríamos.

In [37]: using PyPlotx = linspace(0.0, 2.0, 100)# Para obter as funções abaixo basta resolver as equações para y.plot(x, 2 - x)plot(x, (x + 1)/2)

19

Page 20: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Out[37]: 1-element Array{Any,1}:PyObject <matplotlib.lines.Line2D object at 0x7fe935a4b190>

Nessa imagem vemos claramento o ponto de cruzamento que é (1, 1). A situação ficaria bem menosclara se as duas retas fossem quase paralelas. Isso ocorre por exemplo com o sistema

x + y = 2

(1.0 + 10−1)x + y = 2 + 10−1.

Nesse caso a figura fica:

In [38]: plot(x, 2 - x)plot(x, 2.1 - 1.1x)

20

Page 21: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Out[38]: 1-element Array{Any,1}:PyObject <matplotlib.lines.Line2D object at 0x7fe91945f710>

Agora o ponto de intersecção continua sendo (1, 1) mas isso é muito menos claro visualmente. A únicasolução é ir tentando aumentar a imagem próximo à região de intersecção (zoom) para tentar ver melhor.Por outro lado se você imaginar que as linhas tem espessura fixa o zoom não vai adiantar muito. Há umaprecisão máxima que pode ser obtida. De forma análoga ao caso de linhas de espessura fixa, a precisão quepode ser atingida com números do tipo ponto flutuante é também limitada.

Dessa forma, é de se esperar que quando queremos resolver um sistema associado a equações quaseparalelas o computador tenha problemas. Vamos ver isso.

In [49]: # Constroi um sistema que tem solucao exata (1, 1) mas com a segunda# equacao muito parecida com a primeira.pertubacao = 1.0e-8A = [1.0 1.0; 1.0 + pertubacao 1.0 - pertubacao]b = [2.0 2.0]x = resolve_LU(A, b)println("Solucao calculada = ", x[1], " ", x[2])println("Erro relativo = ", norm(x - ones(2)))

Solucao calculada = 1.0000000055511151 0.9999999944488848Erro relativo = 7.850462371923499e-9

Veja que a solução calculada já erra na nona casa. Isso é confirmado pelo calculo do erro relativo.Um fato interessante é que é possível calcular um valor a partir da matriz que nos diz quando esperarque problemas numéricos como os que vimos acima podem ocorrer. Mas para isso precisamos fazer umpequeno desvio e falar sobre normas de matrizes.

21

Page 22: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

2.0.2 Distâncias e normas de vetores e matrizes.

Em Matemática chamamos de norma, ou comprimento de um vetor x ∈ Rn, uma função x 7→ ∥x∥ ∈ R talque:

1. ∥x∥ ≥ 0 para todo x ∈ Rn e ∥x∥ = 0 somente se x = 0.

2. ∥αx∥ = |α|∥x∥, para todo x ∈ Rn e α ∈ R.

3. ∥x + y∥ ≤ ∥x∥+ ∥y∥ para todos x, y ∈ Rn (desigualdade triangular).

A ideia por detrás dessa definição é capturar diferentes formas de medir tamanho ou distância, maspreservando a propriedade que vetores pequenos tem tamanhos pequenos, somente o vetor nulo tem ta-manho 0 e que o tamanho do lado de um triângulo é menor ou igual a soma dos tamanhos dos outros doislados.

Com a norma definida podemos definir a distância entre dois vetores como a norma de sua diferença,como é natural.

Vejamos agora alguns os exemplos mais importantes de norma nesse curso.

∥x∥1 = |x1|+ |x2|+ . . . + |xn|.

∥x∥2 =√

x21 + x2

2 + . . . + x2n.

∥x∥∞ = max{|x1|, |x2|, . . . , |xn|}.

É fácil mostrar que as definições acima obedecem às três propriedades que definem uma norma usandoas propriedades relacionadas da função módulo.

Uma pergunta natural é: porque se preocupar com formas alternativas de medir comprimento de vetorou distância entre dois vetores que não seja a distância usual, euclidiana, que é capturada na definição danorma 2? Para entender disso imagine que você mora em uma cidade com ruas formando um quadriculado.Se você está em um ponto (x1, y1) nessa cidade e quer ir para o ponto (x2, y2) é fácil entender que o mínimoque você precisa se movimentar é justamente |x1 − x2| na horizontal |y1 − y2| na vertical. Ou seja, na práticaa distância entre esses pontos é |x1 − x2|+ |y1 − y2| que está justamente relacionada à norma 1.

Da mesma forma que podemos estar interessados em definir o comprimento ou de vetores podemostambém querer definir o comprimento ou tamanho de matrizes. Isso é usualmente feito referindo-se anormas de vetores. Vamos mais uma vez apresentar as definições mais importantes para o curso. SejaA ∈ Rn×n temos

∥A∥1 = max{∥a1:n,i∥1, i = 1, . . . , n} (máxima norma 1 das colunas de A).∥A∥2 = max

∥x∥2=1{∥Ax∥2}.

∥A∥∞ = max{∥ai,1:n∥1, i = 1, . . . , n} (máxima norma 1 das linhas de A).

Uma propriedade fundamental que relaciona as normas de matrizes com as respectivas normas de ve-tores é apresentada a seguir.

Proposição.∥Ax∥† ≤ ∥A∥†∥x∥†,

em que † pode ser substituido (nas três posições ao mesmo tempo) por 1, 2, ou ∞.Vejamos um exemplo numérico.

In [50]: A = reshape(1:25, 5, 5)@show norm(A, 1)@show norm(A, 2)

@show norm(A, Inf);

22

Page 23: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

norm(A,1) = 115.0norm(A,2) = 74.2540539375446norm(A,Inf) = 75.0

De posse dessas definições, estamos prontos para retomar o nosso objetivo original: apresentar um valorque pode ser calculado a partir da matriz associada ao sistema que desejamos resolver e que seja capaz deestimar a risco de corremos de ter grandes erros numéricos.

2.0.3 Número de condição

Esse valor é conhecido como número de condição e pode ser entendido como uma forma de estimar o quantoa matriz está perto de ser não-inversível, ou seja o quão perto suas linhas (ou colunas) estão de se tornaremlinearmente dependentes. Ele é dado por

κ(A) = ∥A∥∥A−1∥.

Vamos inicialmente calcular o número de condição das duas matrizes associados aos sistemas no planovistos anteriormente:

In [51]: A = [1 1; 1 -2]norm(A)*norm(inv(A))

Out[51]: 1.7675918792439989

In [52]: A = [1.0 1.0; 1.0 + pertubacao 1.0 - pertubacao]norm(A)*norm(inv(A))

Out[52]: 2.0000000032571724e8

Como vocês podem ver o número de condição da segunda matriz é muito grande, da ordem de 108. Issosugere que é possível que encontremos dificuldades numéricos ao calcular a fatoração LU (mesmo usandopivoteamento) dessa matriz ou ao tentar resolver um sistema linear baseado nela, como já observamos.

2.0.4 Continuando com número de condição (leitura opcional)

Falta escrever.

2.1 Métodos iterativos

Os metodos que apresentamos acima, escalonamento (eliminação de Gauss) e fatoração LU, têm comocaracterística a modificação do sistema original para colocá-lo em um formato que pode ser resolvido ra-pidamente. O grosso do trabalho, que é da ordem O( 2

3 n3), é gasto nesse processo de transformação dosistema ou da respectiva matriz. Até que ele seja terminado não se obtém nenhuma aproximação da solu-ção. Esse tipo de método tem então uma característica do tipo "tudo ou nada". Ou o usuário espera quetodo o trabalho seja feito ou ele sai sem nenhuma resposta. Esses métodos são conhecidos como métodosdiretos.

Uma alternativa ao métodos diretos são os métodos iterativos. Neles o objetivo é aproximar, o maisrapidamente possível, a resposta. O que se perde é que em geral não é possível calculá-la exatamente.Esses métodos são usados quando, por exemplo, n é muito grande e então não é possível esperar que ummétodo direto termine o seu trabalho. Outra situação onde pode ser desejável usar métodos iterativosé quando a matriz A possui muitos elementos nulos. Nesse caso dizemos que A é uma matriz esparsa.Voltaremos a comentar isso depois.

Vamos apresentar agora as ideias por trás do método iterativo mais simples. Ele se baseia em umaobservação trivial. Para fixar as ideias vamos iniciar com um sistema 2 por 2.{

2.5x − y = 1.5x − 2y = −1.

23

Page 24: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Podemos facilmente resolver o sistema e verificarque é solução é em (x, y) = (1, 1). Veja o gráfico deleabaixo

In [1]: using PyPlot

x = linspace(0.8, 2.0, 100)eq1(x) = 2.5*x - 1.5eq2(x) = 0.5*(1.0 + x)plot(x, eq1(x), color="blue")plot(x, eq2(x), color="red")

Out[1]: 1-element Array{Any,1}:PyObject <matplotlib.lines.Line2D object at 0x7efe7a9ab190>

Uma outra forma de encarar as equações do sistema é vê-las como fórmulas de como calcular umadas variáveis das soluções se conhecêssemos a outra. Isso fica claro se reorganizarmos um pouco as duasequações.

x = (1.5 + y)/2.5y = (1 + x)/2.

A ideia do método de Jacobi é melhorar uma aproximação da solução que obtivemos até o momento k,que vamos denotar por (xk, yk), usando essas duas equações como se elas estivessem partindo da soluçãoexata. Isto é fazer

24

Page 25: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

xk+1 = (1.5 + yk)/2.5

yk+1 = (1 + xk)/2.

Geometricamente a primeira equação faz é encontrar a coordenada x do ponto na reta azul que temcoordenada y = yk, ou seja a intersecção da reta azul com uma reta paralela ao eixo x que passar por(xk, yk). Já a segunda equação busca a coordenada y do ponto na reta vermelha que cruza com uma retavertical que passa também por (xk, yk).

Para entender isso melhor, imagine que temos (xk, yk) = (1.4, 1.3). O código abaixo representa as contasfeitas a apresenta o novo ponto calculado bem como o ponto de partida. Note que o novo ponto se aproximada solução que é a intersecção das retas.

In [2]: # Passo de Jacobi# Apresenta o grafico inicialplot(x, eq1(x), color="blue")plot(x, eq2(x), color="red")

# Apresenta o ponto de partida e as linhas que geram o novo pontoxk, yk = 1.4, 1.3unsx = ones(length(x))y = 0.5:0.01:3.0unsy = ones(length(y))plot(xk, yk, marker="o", color="black")

# Calcula o novo ponto e o apresentaxk1 = (1.5+ yk)/2.5yk1 = (1.0 + xk)/2deltax = xk1:0.01:xkdeltay = yk1:0.01:ykplot(deltax, yk*ones(length(deltax)), color="black", linestyle="--")plot(xk*ones(length(deltay)), deltay, color="black", linestyle="--")plot(xk1, yk1, marker="o", color="black")plot(deltax, yk1*ones(length(deltax)), color="black", linestyle="--")plot(xk1*ones(length(deltay)), deltay, color="black", linestyle="--")

25

Page 26: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Out[2]: 1-element Array{Any,1}:PyObject <matplotlib.lines.Line2D object at 0x7efe5e7e90d0>

Podemos ainda continuar fazendo isso, gerando então uma sequencia e ver se ela se aproxima ou nãoda solução:

In [6]: # Método de Jacobi# Altere esses parametros para ver o novo comportamento.# Ponto incialxk, yk = 1.8, 2.5# Numero de iteracoesmaxiter = 5

# Apresenta o grafico inicialplot(x, eq1(x), color="blue")plot(x, eq2(x), color="red")

# Apresenta o ponto de partida em verde e as linhas que geram o novo pontounsx = ones(length(x))y = 0.5:0.01:3.0unsy = ones(length(y))plot(xk, yk, marker="o", color="green")

# Calcula os novos pontos e os apresentafor i = 1:maxiter

xk1 = (1.5 + yk)/2.5

26

Page 27: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

yk1 = (1.0 + xk)/2.0deltax = xk1:0.01:xkdeltay = yk1:0.01:ykplot(deltax, yk*ones(length(deltax)), color="black", linestyle="--")plot(xk*ones(length(deltay)), deltay, color="black", linestyle="--")plot(xk1, yk1, marker="o", color="black")plot(deltax, yk1*ones(length(deltax)), color="black", linestyle="--")plot(xk1*ones(length(deltay)), deltay, color="black", linestyle="--")xk, yk = xk1, yk1

end# Apresenta o ponto final em cyanplot(xk, yk, marker="o", color="cyan")show()println("Ponto final calculado (", xk,", ", yk, ")")

Ponto final calculado (1.024, 1.016)

É interessante brincar um pouco com o código acima variando o número de passos dados e o ponto departida. Note também que o último ponto computado é impresso logo após o gráfico. Verifique como elemuda quando você muda os parâmetros sugeridos.

Vemos então que a ideia simples de Jacobi pode funcionar, pelo menos em alguns casos. Será possívelidentificar de antemão se o método funcionará ou não? Isso será o tema da subseção Análise de Conver-gência abaixo. Por enquanto vamos fazer mais um experimento.

O que ocorreria se o sistema tivesse as duas equações trocadas? Ou seja se ele fosse{x − 2y = −1

2.5x − y = 1.5.

27

Page 28: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Nesse caso as fórmulas de atualização seriam

xk+1 = −1 + 2yk

yk+1 = 2.5x − 1.5.

Podemos copiar a implementação do método acima com as devidas modificações para ver o que ocorre.Vamos agora marcar o ponto inicial na cor magenta para destacar um fenômeno interessante. Observetambém que o ponto inicial está bem mais perto da solução. Ele é (0.01, 0.01).

In [7]: # Método de Jacobi# Altere esses parametros para ver o novo comportamento.# Ponto incialxk, yk = 1.01, 1.01# Numero de iteracoesmaxiter = 5

# Apresenta o grafico inicialplot(x, eq1(x), color="blue")plot(x, eq2(x), color="red")

# Apresenta o ponto de partida e as linhas que geram o novo pontounsx = ones(length(x))y = 0.5:0.01:3.0unsy = ones(length(y))plot(xk, yk, marker="o", color="magenta")

# Calcula os novo ponto e o apresentafor i = 1:maxiter

xk1 = -1.0 + 2.0*ykyk1 = 2.5*xk - 1.5deltax = xk1:-0.01:xkdeltay = yk1:-0.01:ykplot(deltax, yk*ones(length(deltax)), color="black", linestyle="--")plot(xk*ones(length(deltay)), deltay, color="black", linestyle="--")plot(xk1, yk1, marker="o", color="black")plot(deltax, yk1*ones(length(deltax)), color="black", linestyle="--")plot(xk1*ones(length(deltay)), deltay, color="black", linestyle="--")xk, yk = xk1, yk1

end# Ponto finalplot(xk, yk, marker="o", color="cyan")show()println("Ponto final calculado (", xk,", ", yk," )")

28

Page 29: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Ponto final calculado (1.4999999999999982, 1.6249999999999978 )

O que observamos acima é um pouco surpreendente. A sequencia gerada pelo Método de Jacobi agorase afasta da solução. Isso ocorreu devido a simples troca da ordem das equações, o que mostra que o métodoé bastante sensível. Vamos entender isso melhor na seção sobre convergência abaixo. Ainda, destacamosque apesar de o método ter sido apresentado para o caso de duas equações e duas variáveis, a sua extensãopara o caso com n equações e variáveis é direta. Basta isolar a variável i usando a linha i e obtemos afórmula geral.

xk+1i =

bi − ∑i−1j=1 aijxk

j − ∑nj=i+1 aijxk

j

aii, i = 1, . . . , n. (9)

Podemos também intrduzir uma pequena variação que busca melhorar o método de Jacobi. Para issovamos escrever as fórmulas genéricas de Jacobi para um sistema de 3 variáveis e 3 equações com matrizassociada A = (aij).

xk+11 =

b1 − a12xk2 − a13xk

3a11

xk+12 =

b2 − a21xk1 − a23xk

3a22

xk+13 =

b3 − a31xk1 − a32xk

2a33

.

29

Page 30: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Observe que no momento que vamos calcular xk+13 já temos as novas aproximações das duas primeiras

coordenadas xk+11 e xk+1

2 . Se o método estiver indo bem, temos a expectativas que essas aproximações sejammelhores que os valores de xk. Então por que não aproveitá-los? Essa é a ideia do método de Gauss-Seidel.Nele as novas coordenadas já computadas são aproveitadas no cômputo da próxima coordenada. No casode 3 variáveis teríamos:

xk+11 =

b1 − a12xk2 − a13xk

3a11

xk+12 =

b2 − a21xk+11 − a23xk

3a22

xk+13 =

b3 − a31xk+11 − a32xk+1

2a33

.

Podemos também apresentar a versão geral do método de Gauss-Seidel, adaptando a fórmula geral dométodo de Jacobi acima.

xk+1i =

bi − ∑i−1j=1 aijxk+1

j − ∑nj=i+1 aijxk

j

aii, i = 1, . . . , n. (10)

Abaixo modificamos a implementação anterior do método de Jacobi para o sistema do início desta seçãode modo usar a ideia de Gauss-Seidel. Note que a aproximação da solução obtida após um número fixode iterações é melhor do que o método de Jacobi. Isso ocorre devido ao uso de informação mais recente àmedida que as coordenadas são calculadas.

In [72]: # Método de Gauss-Seidel# Altere esses parametros para ver o novo comportamento.# Ponto incialxk, yk = 1.8, 2.1# Numero de iteracoesmaxiter = 5

# Apresenta o grafico inicialplot(x, eq1(x), color="blue")plot(x, eq2(x), color="red")

# Apresenta o ponto de partida e as linhas que geram o novo pontounsx = ones(length(x))y = 0.5:0.01:3.0unsy = ones(length(y))plot(xk, yk, marker="o", color="green")

# Calcula os novo ponto e o apresentafor i = 1:maxiter

xk1 = (1.5 + yk)/2.5yk1 = (1.0 + xk1)/2.0deltax = xk1:0.01:xkdeltay = yk1:0.01:ykplot(deltax, yk*ones(length(deltax)), color="black", linestyle="--")plot(xk1, yk1, marker="o", color="black")plot(xk1*ones(length(deltay)), deltay, color="black", linestyle="--")xk, yk = xk1, yk1

endplot(xk, yk, marker="o", color="cyan")

30

Page 31: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

show()println("Ponto final calculado (", xk,", ", yk," )")

Ponto final calculado (1.000704, 1.000352 )

Porém o método sofre de problemas semelhantes ao de Jacobi. Uma simples troca da ordem das equa-ções faz com que o método se afaste da solução ao invés de se aproximar. Vamos agora começar a estudarquando podemos garantir que um método converge à solução do problema.

2.2 Convergência

Nessa seção vamos supor que a matriz do sistema

Ax = b

é inversível. Isso garante que o sistema tem solução única que vamos denotar por x∗.Como vimos, os métodos de Jacobi e Gauss-Seidel não tentam calcular uma solução diretamente.

Eles tentam melhorar uma aproximação da solução cada vez mais, gerando uma sequencia x1, x2, x2, . . ..Quando podemos dizer que a solução obtida é suficiente boa? Quando podemos dizer que um métododesses funciona?

Definição. Seja x1, x2, x2, . . ., uma sequência gerada por um método iterativo. Dizemos que o métodoconverge se existe x∗ solução do problema de interesse tal que a sequencia calculada {xk} converge para x∗.Ou seja se a distância entre xk e x∗ converge para 0 (zero).

31

Page 32: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

Nosso objetivo agora é apresentar condições que possam garantir que os métodos iterativos que estu-damos convergem à solução x∗ do sistema Ax = b. Para isso vamos começar observando que uma formainteressante de se ver um método iterativo é como uma função que é calculada em uma aproximação x doponto desejado resultando em uma nova aproximação x+ que é potencialmente melhor. Ou seja, podemosimaginar que um algoritmo pode muitas vezes ser descrito por uma função ϕ : Rn → Rn e a regra

xk+1 = ϕ(xk).

Caso tal função de iteração ϕ exista, é natural que ela tenha a propriedade de que se o ponto de partida já éa solução x∗ então a ϕ diga que "se deve ficar parado"para não perder a solução. Isto é

x∗ = ϕ(x∗).

Além disso, também é natural pedir que se o ponto não for uma solução então ϕ devolva um ponto dife-rente. Caso contrário método iterativo poderia ficar parado em cima de pontos que não são soluções. Issoem linguagem matemática é o mesmo que dizer que ϕ deve ter como único ponto fixo justamente a soluçãodo problema de interesse.

Retomando o problema de sistemas lineares, vamos tentar re-escrever os métodos de Jacobi e Gauss-Seidel descobrindo a expressão da função ϕ. Para isso é útil quebrar a matriz A do sistema que desejamosresolver

Ax = b

em três submatrizes. Vamos escrever A = L + D + U, em que L contém os elementos abaixo da diagonalde A (e tem zero na diagonal e acima dela), D contém a diagonal de A (e zero fora da diagonal) e U possuios elementos que ficam acima da diagonal.

Retomando a formula do Jacobi.

xk+1i =

bi − ∑i−1j=1 aijxk

j − ∑nj=i+1 aijxk

j

aii, i = 1, . . . , n,

podemos escrevê-la de forma mais compacta como

xk+1 = D−1(b − Lxk − Uxk).

Reorganizando os termos temosxk+1 = −D−1(L + U)xk + D−1b.

Isso sugere a função de iteraçãoϕJ(x) = −D−1(L + U)x + D−1b.

No caso do método de Gauss-Seidel a situação é semelhante, porém um pouco mais interessante.

xk+1 = D−1(b − Lxk+1 − Uxk) ⇐⇒ (11)

Dxk+1 = b − Lxk+1 − Uxk ⇐⇒ (12)

Dxk+1 + Lxk+1 = −Uxk + b ⇐⇒ (13)

(D + L)xk+1 = −Uxk + b ⇐⇒ (14)

xk+1 = −(D + L)−1Uxk + (D + L)−1b. (15)

Nesse caso a função de iteração é

ϕGS(x) = −(D + L)−1Ux + (D + L)−1b.

Nos dois casos vemos que a função de iteração pode ser escrita como

ϕ(x) = Bx + c,

32

Page 33: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

em que B é uma matriz e c um vetor constante. Também nos dois casos como x∗ é tal que Ax∗ = b temosϕ(x∗) = x∗, como gostaríamos. Vamos ver isso no caso de Gauss-Seidel

ϕGS(x∗) = −(D + L)−1Ux∗ + (D + L)−1b

= −(A − U)−1Ux∗ + (A − U)−1b

= −(A − U)−1Ux∗ + (A − U)−1 Ax∗

= (A − U)−1(−U + A)x∗

= x∗.

A pergunta sobre a convergência dos métodos pode então ser repensada da seguinte forma: se ϕ(x) tema expressão Bx + c, quando podemos garantir que o ∥xk − x∗∥ converge para 0? Para isso façamos algumasmanipulações simples

∥xk+1 − x∗∥† = ∥ϕ(xk)− x∗∥†

= ∥ϕ(xk)− ϕ(x∗)∥†

= ∥Bxk + c − Bx∗ − c∥†

= ∥B(xk − x∗)∥†

≤ ∥B∥†∥xk − x∗∥†.

Na última passagem usamos a propriedade que relaciona a norma de matrizes com a respectiva normade vetores.

Aplicando isso recursivamente vemos que

∥xk+1 − x∗∥† ≤ ∥B∥k†∥x1 − x∗∥†.

Note que isso garante que ∥xk+1 − x∗∥† → 0 sempre que ∥B∥† < 1. Podemos imediatamente enunciar oseguinte resultado:

Teorema. Considere que um sistema linear Ax = b com solução única. Considere também um métodoiterativo descrito por uma função ϕ que tenha a solução do sistema como único ponto fixo. Se ϕ é descritapor ϕ(x) = Bx + c então o método converge sempre que ∥B∥† < 1 para alguma das normas consideradas.

Obs: Note que acima não escrevemos "converge na norma ∥ · ∥†"mas simplesmente usamos "converge".Isso porque é fácil de provar, pelo menos paras as normas vistas nessa seção que se ∥xk − x∗∥† → 0 paraalguma das normas o mesmo ocorre para as outras. Isso ocorre porque é possível achar para cada par denormas uma constante, que geralmente depende da dimensão do espaço, tal que uma norma é menor doque essa constante vezes a outra.

O que esse teorema nos ensina sobre os métodos de Jacobi e Gauss-Seidel? Por exemplo, no caso dométodo de Jacobi, em que a matriz B = −D−1(L + U) podemos ver que

Teorema. A matriz associada ao método de Jacobi B = −D−1(L + U) tem norma infinito menor estritaque 1 se

|aii| >n

∑j=1,j =i

|aij|.

Prova. Lembremos que a norma infinito de uma matriz é a máxima norma 1 de suas linhas. Mas oselementos da linha i de B são exatamente

bij =

{ aijaii

, j = 1, . . . , n, I = j0, i = j.

Assim, a norma 1 da linha i de b é igual an

∑j=1i =j

∣∣∣∣ aij

aii

∣∣∣∣ < 1.

33

Page 34: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

A última desigualdade segue imediatamente da hipótese do teorema. Ou seja, todas as linhas de B temnorma 1 menor que 1 e portanto ∥B∥∞ < 1. ■

Obs: Uma matriz cujos elementos da diagonal superam em módulo somas dos módulos dos outroselementos da mesma linha é chamada de matriz diagonal dominante por linhas. O que o teorema diz é queo método de Jacobi converge se a matriz do sistema for diagonal dominante por linhas. Observe que esseresultado ajuda a entender porque a ordem das equações, que estão relacionadas às linhas da matriz, éimportante para a convergência. Se a linha escolhilda para isolar o termo xi tiver a constante que multiplicaessa variável muito pequena em módulo o método pode não convergir. Isso é exatamente o que ocorrequando trocamos as ordem das duas equações no sistema usando como exemplo anteriormente.

Acabamos essa seção com dois comentários e com um exemplo de implementação do método de Jacobi.

1. Pode-se mostrar que o critério de dominância por linhas também é válido para Gauss-Seidel.

2. O método de Gauss-Seidel é tipicamente mais rápido do que o de Jacobi. Porém ele estabelece umaordem na qual as variáveis devem ser atualizadas e por isso é de paralelização mais difícil. Nessesentido há problemas em que Jacobi ainda pode valer à pena se o ganho com seu palelismo inerente foimaior do que o ganho obtido por Gauss-Seidel por aproveitar os valores das vairáveis já atualizadas.Isso tem se tornado mais importante nos últimos anos em que o crescimento de poder computacionaltem vindo mais do aumento do número de processadores do que no aumento de velocidade de cadaunidade de processamento.

In [8]: # Implementacao inocente do método de Jacobifunction jacobi(A, b, maxiters=100, prec=1.0e-5)

# Pega a dimensão do probleman = length(b)

# Constroi as matrizes de interaçãoDinv = 1.0 ./ diag(A)LpU = copy(A)for i = 1:n

LpU[i, i] = 0.0end

# Inicializaçãoiters = 0c = Dinv .* bx = copy(c)

# Iterações de Jacobi@printf "Iter %d, Resíduo = %.2e\n" iters norm(A*x - b)while iters < maxiters && norm(A*x - b) > prec

x = -Dinv .* (LpU*x) + citers += 1@printf "Iter %d, Resíduo = %.2e\n" iters norm(A*x - b)

endreturn x

end

# Dimensão do problema de teste.n = 1000# Pega matriz e lado direitos aleatóriosA = rand(n, n)b = rand(n)# Faz a matriz ficar diagonal dominante

34

Page 35: Sistemas Lineares - ime.unicamp.brpjssilva/pdfs/notas_de... · Já para colocar um zero na posição (4,1) devemos somar à quarta 3 vezes a primeira. Mais uma vez o coeficiente

for i = 1:nA[i, i] += 1001.0

end

# Testa o métodox = jacobi(A, b)@show norm(A*x - b);

Iter 0, Resíduo = 8.03e+00Iter 1, Resíduo = 4.00e+00Iter 2, Resíduo = 2.00e+00Iter 3, Resíduo = 9.95e-01Iter 4, Resíduo = 4.96e-01Iter 5, Resíduo = 2.47e-01Iter 6, Resíduo = 1.23e-01Iter 7, Resíduo = 6.15e-02Iter 8, Resíduo = 3.07e-02Iter 9, Resíduo = 1.53e-02Iter 10, Resíduo = 7.63e-03Iter 11, Resíduo = 3.80e-03Iter 12, Resíduo = 1.90e-03Iter 13, Resíduo = 9.46e-04Iter 14, Resíduo = 4.72e-04Iter 15, Resíduo = 2.35e-04Iter 16, Resíduo = 1.17e-04Iter 17, Resíduo = 5.85e-05Iter 18, Resíduo = 2.92e-05Iter 19, Resíduo = 1.45e-05Iter 20, Resíduo = 7.25e-06norm(A * x - b) = 7.253537207638278e-6

In [ ]:

35