Departamento de Ciência da Computação --Departamento de Ciência da Computação - IME-USP

MAC 115 - Introdução à Computação para Ciências Exatas e Tecnologia

INSTITUTO DE GEOCIêNCIAS - SEGUNDO SEMESTRE DE 1998

Quarto Exercício-Programa
Data de entrega: até 27 de novembro de 1998

Prof. Ronaldo Fumio Hashimoto

SISTEMAS LINEARES



1  Introdução

O objetivo deste EP é implementar a resolução de um sistema de equações lineares aplicando o Método de conhecido como Método de Decomposição LU.


Definição: Um sistema de equações lineares (de n equações e n incógnitas) é um sistema do tipo:

ì
ï
ï
í
ï
ï
î
a0,0x0
+
a0,1x1
+
a0,2x2
+
¼
+
a0,n-1xn-1
=
y0
a1,0x0
+
a1,1x1
+
a1,2x2
+
¼
+
a1,n-1xn-1
=
y1
:
:
:
:
:
:
an-1,0x0
+
an-1,1x1
+
an-1,2x2
+
¼
+
an-1,n-1xn-1
=
yn-1
 (1)

onde os ai,j e os yi (i,j = 0,1,2,¼, n-1) são dados, e os xi (i = 0,1,2,¼,n-1) são as incógnitas do sistema. Por exemplo,

ì
ï
ï
í
ï
ï
î
2 x0
+
4 x1
+
2 x2
=
4
4 x0
+
7 x1
+
7 x2
=
13
-2 x0
-
7 x1
+
5 x2
=
7
 (*****)

é um sistema de 3 equações e 3 incógnitas.


Sejam

A = é
ê
ê
ê
ê
ê
ë
a0,0
a0,1
¼
a0,n-1
a1,0
a1,1
¼
a1,n-1
:
:
:
:
an-1,0
an-1,1
¼
an-1,n-1
ù
ú
ú
ú
ú
ú
û
x = é
ê
ê
ê
ê
ê
ë
x0
x1
:
xn-1
ù
ú
ú
ú
ú
ú
û
y = é
ê
ê
ê
ê
ê
ë
y0
y1
:
yn-1
ù
ú
ú
ú
ú
ú
û
.

Então, podemos escrever o sistema (1) como A·x = y.


Um sistema dado pode não ter solução, ou ter uma ou mais soluções (inclusive infinitas). No exemplo (*****), x0 = -2, x1 = 1 e x2 = 2 é a única solução do sistema. As vantagens de uma representação por matrizes são, além de ser uma notação mais compacta, permite trabalhar em um computador.

2  Casos Especiais: Matrizes Triangulares

Temos dois casos especiais que são de resolução imediata:


1. A matriz A é uma matriz triangular superior, isto é, ai,j = 0 se i > j. Assim, os valores abaixo da diagonal de A são todos nulos. Por exemplo, seja o sistema:

ì
ï
ï
í
ï
ï
î
x0
+
x1
+
7 x2
=
2
3 x1
+
x2
=
1
2 x2
=
2

A resolução é então trivial: da última equação achamos x2 = 1. Com x2 e a segunda equação, achamos x1 = 0. E com x1 e x2 achamos, da primeira equação, o valor de x0 = -5. Este método chama-se de ``back-substitution''.


2. A matriz A é uma matriz triangular inferior, isto é, ai,j = 0 se i < j. Assim, os valores acima da diagonal de A são todos nulos. Por exemplo, considere dado o seguinte sistema:

ì
ï
ï
í
ï
ï
î
2 x0
=
4
x0
+
x1
=
1
x1
+
3 x1
+
x2
=
3

Novamente, a resolução fica trivial: de primeira equação, x0 = 2. Com x0 e a segunda equação, obtemos x1 = -1, e finalmente, da última equação, e com os valores de x0 e x1, temos que x2 = 4. Este método chama-se de ``forward-substitution''.

3  Método de Decomposição LU

Dada uma matriz A, vamos tentar achar (se for possível) uma matriz L triangular inferior e uma matriz U triangular superior tais que A = LU. Nesse caso,


Ax = y


como A = LU, temos:


(LU)x = y


e podemos fazer:


L(Ux) = y


Fazendo Ux = z, temos:


Lz = y e Ux = z.


Dessa forma, resolver o sistema Ax = y equivale a resolver dois sistemas lineares (triangulares) simples: primeiramente o sistema (triangular inferior) Lz = y por ``forward-substitution'' e depois o sistema (triangular superior) Ux = z por ``back-substitution''.

3.1  Cálculo da matriz triangular inferior L

Dada uma matriz A = (ai,j), queremos obter a partir dela uma matriz L com zeros acima da diagonal. Para isso, vamos começar ``zerar'' gradualmente os elementos a0,1, a0,2, ¼ , a0,n-1. Seja l tal que a0,1-la0,0 = 0. Então l = a0,1/a0,0 (assumir a0,0 não nulo). Calculamos, então, os novos valores para a segunda coluna da seguinte forma: a primeira coluna menos l vezes a segunda coluna. Ou seja,

é
ê
ê
ê
ê
ê
ë
a¢0,1
a¢1,1
:
a¢n-1,1
ù
ú
ú
ú
ú
ú
û
= é
ê
ê
ê
ê
ê
ë
a0,1
a1,1
:
an-1,1
ù
ú
ú
ú
ú
ú
û
- l· é
ê
ê
ê
ê
ê
ë
a0,0
a1,0
:
an-1,0
ù
ú
ú
ú
ú
ú
û

Isto é,

a¢j,1 = aj,1-laj,0, j = 0, 1, ¼ , n-1

Claramente, obtemos a¢0,1 = 0 (pela escolha do l). Repetimos o procedimento para a terceira coluna, isto é, para ``zerar'' a0,2, recalculamos a terceira coluna a partir da primeira. Seja l¢ = a0,1/a0,0. Então

é
ê
ê
ê
ê
ê
ë
a¢0,2
a¢1,2
:
a¢n-1,2
ù
ú
ú
ú
ú
ú
û
= é
ê
ê
ê
ê
ê
ë
a0,2
a1,2
:
an-1,2
ù
ú
ú
ú
ú
ú
û
- l¢· é
ê
ê
ê
ê
ê
ë
a0,0
a1,0
:
an-1,0
ù
ú
ú
ú
ú
ú
û

Ou seja,

a¢j,2 = aj,2-l¢aj,0, j = 0, 1, ¼ , n-1



Claramente, obtemos a¢0,2 = 0 (pela escolha do l¢). Repetindo esse processo, vamos ``zerar'' todos elementos a0,1, a0,2, ¼ , a0,n-1, obtendo:

A = é
ê
ê
ê
ê
ê
ë
a0,0
a0,1
a0,2
¼
a0,n-1
a1,0
a1,1
a1,2
¼
a1,n-1
:
:
:
:
:
an-1,0
an-1,1
an-1,2
¼
an-1,n-1
ù
ú
ú
ú
ú
ú
û
Þ é
ê
ê
ê
ê
ê
ë
a0,0
0
0
¼
0
a1,0
a¢1,1
a¢1,2
¼
a¢1,n-1
:
:
:
:
:
an-1,0
a¢n-1,1
a¢n-1,2
¼
a¢n-1,n-1
ù
ú
ú
ú
ú
ú
û

Devemos prosseguir para ``zerar'' a segunda linha. Para ``zerar'' a¢1,2, recalculamos a terceira coluna a partir da segunda (utilizando a coluna já modificada no passo anterior!). Seja b = a¢1,2/a¢1,1 (assumir a¢1,1 não nulo). Então:

é
ê
ê
ê
ê
ê
ë
a¢¢0,2
a¢¢1,2
:
a¢¢n-1,2
ù
ú
ú
ú
ú
ú
û
= é
ê
ê
ê
ê
ê
ë
0 = a¢0,2
a¢1,2
:
a¢n-1,2
ù
ú
ú
ú
ú
ú
û
- b· é
ê
ê
ê
ê
ê
ë
0 = a¢0,1
a¢1,1
:
a¢n-1,1
ù
ú
ú
ú
ú
ú
û

Ou seja,

a¢¢j,2 = a¢j,2-ba¢j,1, j = 1, 2, ¼ , n-1

Assim, obteremos a¢¢1,2 = 0.


Da mesma forma, para obtermos a¢¢1,3 = 0, recalculamos a quarta coluna a partir da segunda. Seja b¢ = a¢1,3/a¢1,1. Então:

é
ê
ê
ê
ê
ê
ë
a¢¢0,3
a¢¢1,3
:
a¢¢n-1,3
ù
ú
ú
ú
ú
ú
û
= é
ê
ê
ê
ê
ê
ë
0 = a¢0,3
a¢1,3
:
a¢n-1,3
ù
ú
ú
ú
ú
ú
û
- b¢· é
ê
ê
ê
ê
ê
ë
0 = a¢0,1
a¢1,1
:
a¢n-1,1
ù
ú
ú
ú
ú
ú
û

Ou seja,

a¢¢j,3 = a¢j,3-b¢a¢j,1, j = 1, 2, ¼ , n-1

Seguindo este procedimento, vamos ``zerar'' todos os elementos a¢1,2, a¢1,3, ¼ , a¢1,n-1, obtendo:

é
ê
ê
ê
ê
ê
ê
ê
ë
a0,0
0
0
¼
0
a1,0
a¢1,1
a¢1,2
¼
a¢1,n-1
a2,0
a¢2,1
a¢2,2
¼
a¢2,n-1
:
:
:
:
:
an-1,0
a¢n-1,1
a¢n-1,2
¼
a¢n-1,n-1
ù
ú
ú
ú
ú
ú
ú
ú
û
Þ é
ê
ê
ê
ê
ê
ê
ê
ë
a0,0
0
0
¼
0
a1,0
a¢1,1
0
¼
0
a2,0
a¢2,1
a¢¢2,2
¼
a¢¢2,n-1
:
:
:
:
:
an-1,0
a¢n-1,1
a¢¢n-1,2
¼
a¢¢n-1,n-1
ù
ú
ú
ú
ú
ú
ú
ú
û

Prosseguimos assim para a terceira linha, zerando a¢¢2,3, a¢¢2,4, ¼ , a¢¢2,n-1, sempre usando a terceira coluna. Depois, a quarta linha usando a quarta coluna. Seguindo esse processo para as demais linhas, até obter uma matriz L diagonal inferior.

L = é
ê
ê
ê
ê
ê
ê
ê
ë
a0,0
0
0
¼
0
a1,0
a¢1,1
0
¼
0
a2,0
a¢2,1
a¢¢2,2
¼
0
:
:
:
:
:
an-1,0
a¢n-1,1
a¢¢n-1,2
¼
a¢¼¢n-1,n-1
ù
ú
ú
ú
ú
ú
ú
ú
û

3.2  Cálculo da matriz triangular superior U

A matriz U é obtida simplesmente armazenando os coeficientes usados em cada passo do procedimento (anterior) para obter a matriz L, da seguinte forma:

ui,j = a¢¼¢i,j/a¢¼¢i,i, i = 1, 2, ¼ , n-1 e j > i.

(coeficientes utilizados no procedimento anterior!)



Definimos ui,i = 1 e ui,j = 0, para i=1, 2, ¼, n-1 e j < i. Assim obteremos a matriz:

U = é
ê
ê
ê
ê
ê
ê
ê
ë
1
u0,1
u0,2
¼
u0,n-1
0
1
u1,2
¼
u1,n-1
0
0
1
¼
u2,n-1
:
:
:
:
:
0
0
0
¼
1
ù
ú
ú
ú
ú
ú
ú
ú
û

Pode-se verificar que A = LU, e que a decomposição é única.


Observação: Se em algum momento a¢¼¢i,i = 0, o método deve parar.



4  Um exemplo de cálculo de L e U

Considere o nosso sistema de equações (exemplo (*****) da  Seção 1):

é
ê
ê
ê
ê
ë
2
4
2
4
7
7
-2
-7
5
ù
ú
ú
ú
ú
û

Primeiro passo, zerar a0,1 e a0,2, isto é, 4 e 2. Para isso, primeiro calculamos

l = a0,1/a0,0 = 4/2 = 2, e recalculamos a segunda coluna:


a¢0,1 = 0,

a¢1,1 = a1,1-la1,0 = 7-2·4 = -1,

a¢2,1 = a2,1-la2,0 = -7-2·(-2) = -3.


Para zerar a0,2, calculamos l¢ = a0,2/a0,0 = 2/2 = 1, e assim, recalculamos a terceira coluna (a partir da primeira):


a¢0,2 = 0,

a¢1,2 = a1,2-la1,0 = 7-1·4 = 3,

a¢2,2 = a2,2-la2,0 = 5-1·(-2) = 7.


Os multiplicadores são l = 2 e l¢ = 1, assim u0,1 = 2 e u0,2 = 1 (como U tem 1 na diagonal, u0,0 = 1). A matriz depois deste passo será:

é
ê
ê
ê
ê
ë
2
0
0
4
-1
3
-2
-3
7
ù
ú
ú
ú
ú
û

Segundo passo, zerar o resto da segunda linha, isto é, a¢1,2 = 3. Para isso, calculamos l = a¢1,2/a¢1,1 = 3/(-1) = -3 (agora usamos a segunda coluna!). Assim, recalculamos a terceira coluna:


a¢¢1,2 = 0,

a¢¢2,2 = a¢2,2-la¢2,1 = 7-(-3)·(-3) = -2.


O multiplicador foi l = -3, e assim u1,2 = -3. Uma vez que U é triangular superior e tem em sua diagonal, então devemos ter u1,0 = 0 e u1,1 = 1.


Agora acabou o processo, u2,0 = u2,1 = 0 e u2,2 = 1, e obtemos:

L = é
ê
ê
ê
ê
ë
2
0
0
4
-1
0
-2
-3
-2
ù
ú
ú
ú
ú
û
e U = é
ê
ê
ê
ê
ë
1
2
1
0
1
-3
0
0
1
ù
ú
ú
ú
ú
û

Dessa forma, basta resolvermos:

Lz = é
ê
ê
ê
ê
ë
4
13
7
ù
ú
ú
ú
ú
û
obtendo (confira!) z = é
ê
ê
ê
ê
ë
2
-5
2
ù
ú
ú
ú
ú
û

E finalmente, resolvendo:

Uy = z = é
ê
ê
ê
ê
ë
2
-5
2
ù
ú
ú
ú
ú
û
obtemos (confira!) y = é
ê
ê
ê
ê
ë
-2
1
2
ù
ú
ú
ú
ú
û

Observe que, como os computadores tem uma precisão limitada, necessariamente vamos ter erros de arredondamento nos cálculos, e então uma solução para o sistema Ax = y não vai ser exata. Seja x a solução encontrada pelo seu programa. O erro pode ser medido achando-se a diferença entre o vetor Ax e y. A diferença é calculada da seguinte forma:

Erro = ||Ax - y||, onde

||v || = max {|vi| : 0 £ i £ n-1}.

5  O problema a ser resolvido!

Fazer um programa em Linguagem C tal que, lida uma matriz real quadrada A de ordem n e um real vetor y de n elementos, resolva (se for possível) o sistema linear Ax = y, seguindo os seguintes passos:


1. Achar uma decomposição A = LU;

2. Resolver (por forward-substitution) Lz = y;

3. Resolver (por back-substitution) Ux = z;

4. Achar o erro Erro = ||Ax - y|| da solução encontrada x, onde

||v|| = max{|vi| : 0 £ i £ n-1}.

5. Imprimir A, L e U, z, x e o erro E.

6  O que você DEVE fazer e utilizar

Para isso, você deve definir as seguintes funções:


void copy_mat (int n, double A[][MAX_MAT], double B[][MAX_MAT]);


Copia a matriz quadrada A de ordem n na matriz B quadrada, também de ordem n.

int calc_lu (double A[][MAX_MAT], double LU[][MAX_MAT]);


Esta função obtêm L e U. Inicialmente devemos ter L = A. Não use nenhuma matriz auxiliar nesta função! Na matriz LU deve ficar a matriz L na parte inferior de LU e a matriz U (sem a diagonal de 1) na parte superior de LU. Para o exemplo (*****), teríamos a matriz LU como:

LU = é
ê
ê
ê
ê
ë
2
2
1
4
-1
-3
-2
-3
-2
ù
ú
ú
ú
ú
û

Observação: Se na execução de calc_lu achamos algum li,i = 0, então a função deve retornar um valor especial para permitir ao programa principal detectar tal situação, imprimindo na tela uma mensagem de erro.

void prod (int n, double A[][MAX_MAT], double x[], double y[]);

Calcula o produto da matriz An×n pelo vetor xn×1, guardando o resultado em yn×1, ou seja,

yi = n-1
å
j = 0 
ai,j·xj

void forw_subst (int n, double LU[][MAX_MAT], double y[], double z[]);

Resolve Lz = y por forward-substitution, onde L é a parte inferior de LU.

void back_subst (int n, double LU[][MAX_MAT], double z[], double x[]);

Resolve Ux = z por back-substitution, onde U é a parte superior (sem considerar a diagonal) de LU, sendo que cada elemento de sua diagonal de U deve valer 1.

double norma (int n, double x[]);

Devolve o valor de ||x ||. Você pode usar a função fabs (double a) da biblioteca de C para calcular o valor absoluto de a.

void imprime_vet (int n, double v[]);

Imprime o vetor x com n elementos.

void imprime_mat (int n, double A[][MAX_MAT]);

Imprime a matriz quadrada A de ordem n.

7  Faça um teste!

Imprima a saída do seu programa para a seguinte entrada:


A: uma matriz 10×10 (obs.: .7030 representa 0.7030);


y: um vetor de 10 elementos.


A = é
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ë
.7030
.5285
.3878
.9448
.1504
.9178
.7069
.0043
.5185
.2803
.1430
.3107
.2793
.4607
.6701
.2666
.7078
.4957
.0668
.8159
.1617
.5881
.0783
.9402
.3438
.9701
.4366
.0799
.5440
.3719
.4853
.5181
.3697
.3216
.5417
.2467
.5824
.1631
.3897
.6861
.8602
.4308
.2539
.4604
.5228
.8440
.7517
.9033
.2158
.3102
.8133
.2588
.6718
.5171
.8292
.6940
.9915
.7830
.3878
.0093
.5568
.3702
.6762
.6614
.0150
.4558
.6957
.7467
.6269
.1038
.7390
.3930
.5139
.4018
.2742
.8171
.2795
.4364
.6591
.5210
.3160
.4469
.7286
.6056
.6430
.0221
.7539
.0063
.7093
.7759
.1353
.4759
.7208
.9865
.5461
.1607
.1712
.5848
.5387
.2207
ù
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
û
y = é
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ê
ë
.0553
.0706
.1603
.7238
.2970
.0506
.4778
.4572
.5200
.4465
ù
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
ú
û


File translated from TEX by TTH, version 1.67.
With personal mofications.
Last modified: Tue Nov 24 10:25:52 EDT 1998