Lab 03: Układy liniowe – metody bezpośrednie
W
PROWADZENIEEliminacja Gaussa. Metoda eliminacji Gaussa prowadzi do powstania równoważnego układu równań, ale z macierzą trójkątną. Jeżeli stosujemy eliminacje w kolumnach to będzie to macierz trójkątna górna:
11 1 12 2 1 1 11 1 12 2 1 1
21 1 22 2 2 2 eliminacja 22 2 2 2
1 1 2 2
n n n n
n n n n
n n nn n n nn n n
a x a x a x b a x a x a x b
a x a x a x b a x a x b
a x a x a x b a x b
+ + + = + + + =
+ + + = + + =
⎯⎯⎯⎯→
+ + + = =
(1)
Rozwiązanie układu z macierzą trójkątną jest już łatwe – omawialiśmy to na ćwiczeniach 2 (lab02).
Zasadniczym krokiem w metodzie eliminacji jest uzyskanie zer pod elementem na przekątnej (poniżej jest zapis dla samej macierzy, a nie układy ze zmiennymi): i-ty wiersz mnożymy przez aj i, /ai i, i odejmujemy od wiersza j-tego dla j= +i 1, , .n
1,1 1,2 1,
, ,
1, 1,
, ,
0 0
0 0
n
i i i n
i i i n
n i n n
a a a
a a
a a
a a
+ +
(2)
Aby jednak zagwarantować, że ai i, 0 oraz poprawić stabilność numeryczną, zanim dokonamy eliminacji wyszukujemy w kolumnie
, 1,
, i i i i
n i
a a
a
+
(3)
elementu największego co do wartości bezwzględnej, a następnie zamieniamy wiersz i-ty z tym wierszem, w którym jest element największy. jest to tzw. częściowy wybór elementu głównego. W praktyce jednak lepiej zamiast zamieniać wiersze (dużo operacji kopiowania w pamięci) można zapamiętać te zamiany w odpowiedniej jednowymiarowej tablicy permutacji wierszy.
Rozkład LU. Rozkład LU polega na tym, że macierzy A zostaje wyrażona w postaci iloczynu dwóch macierzy L i U, gdzie L jest trójkątną dolną, a U – trójkątną górną. Ponadto przyjmujemy, że L ma jedynki na przekątnej: lii =1. Tak naprawdę, to w ogólności otrzymany rozkład jest z dokładnością do ewentualnej permutacji wierszy macierzy A, zatem
.
PA=LU (4)
gdzie macierz kwadratowa P dokonuje permutacji wierszy w macierzy A oraz
Lab 03: Układy liniowe – metody bezpośrednie
11 12 1
21 22 2
31 32 33 3
1 2 , 1
1 0 0
1 0 0
1 , 0 .
0
1 0 0 0
n n n
n n n n nn
u u u
l u u
l l
L U u u
l l l − u
= =
(5)
Macierz permutacjiP ma tylko elementy 0 i 1, ponadto w każdym wierszu i w każdej kolumnie jedynka występuje dokładnie raz. Na przykład dla n=4 macierz permutacji może wyglądać tak
0 0 1 0 0 1 0 0 0 0 0 1 .
1 0 0 0 P
=
Jeżeli pomnożymy dowolną macierz przez powyższą, to widać zamianę wierszy:
11 12 13 14 31 32 33 34
21 22 23 23 21 22 23 24
31 32 33 34 41 42 43 44
41 42 43 44 11 12 13 14
0 0 1 0 0 1 0 0 0 0 0 1 .
1 0 0 0
a a a a a a a a
a a a a a a a a
PA a a a a a a a a
a a a a a a a a
= =
W szczególnym przypadka, gdy P będzie macierzą jednostkową, to nie wystąpią żadne zamiany wierszy.
Zauważmy, że taki sposób kodowania permutacji wierszy nie jest efektywny z punktu widzenie implementacji komputerowej (praktycznie same zera w pamięci). Można tego uniknąć zapamiętując kolejność wierszy w wektorze (tablicy jednowymiarowej). Dla naszego przykładu będzie to
3 2 . 4 1 p
=
Uwaga: nasze indeksy są z zakresu {1, 2, , }.n W języku C trzeba pamiętać o numerowaniu od zera:
{0, 1, ,n−1}.
Z
ADANIAOgólne informacje:
1) Rozwiązanie składa się krótkiego pliku pdf oraz kodów źródłowych, które kompilują się na serwerze taurus kompilatorem gcc.
2) Wszystkie pliki mają być zarchiwizowane do jednego pliku formatu ZIP. Nazwa archiwum:
lab03_naziwsko_imię.zip
3) Dołączony opis w pdf zwiera na początku dane studenta (imię, nazwisko, grupa, kierunek, rok studiów) oraz jednostronicowy opis problemu/problemów numerycznych implementowanych w programach. Można posłużyć się materiałami z wykładów i z ćwiczeń.
4) Każdy kod źródłowy ma mieć nazwę: nazwisko_imię_labxx_zadanie_y.cpp, gdzie xx to numer ćwiczeń (te mają xx=03, a y to numer zadania).
5) Rozwiązane zadania wysyłamy jako załącznik do emaila na adres: szyszkin@agh.edu.pl.
Lab 03: Układy liniowe – metody bezpośrednie
6) Temat listu: Met_Numer_Lab03_Nazwisko_Imię
7) Termin: 7 dni od opublikowanie zadań. W tym przypadku jest to 31.03.2023.
Zadanie 1. Przeanalizować implementację eliminacji Gaussa znajdująca się w pliku gauss.cpp.
Zmodyfikować program tak aby:
(i) Dane były odczytywane z pliku. Format pliku a11 a12 … a1n b1
a21 a22 … a2n b2
…
an1 an2 … ann bn
(ii) W programie jest zrealizowany wybór elementu głównego (ang. pivot) w kolumnie (zatem jest to częściowy wybór elementu głównego), a następnie – jeżeli stwierdzono, że jest on poniżej przekątnej – wykonywana jest fizyczna zamiana wierszy. Jest to nieefektywne – należy wprowadzić tablica (wektor) p[n], który będzie przechowywała informację o zamianie wierszy w formie permutacji indeksów 0, 1, 2, …, n-1.
Zadanie 2. Napisać program, który wykorzysta bibliotekę GSL do rozkładu LU. Wykorzystać w tym celu funkcje biblioteczną:
gsl_linalg_LU_decomp Poniżej jest fragment kodu, który należy zmodyfikować:
(i) Dodać fragment kodu, który będzie wykonywał mnożenie L*U. Porównać z macierzą A.
(ii) Dodać fragment, który będzie rozwiązywał wczytany układ równań z pliku Ab.txt dokonując najpierw rozkładu LU funkcją biblioteczną, a następnie rozwiązywał uzyskany układ równań liniowych. Na koniec program powinien wypisać rozwiązanie na ekranie i zapisać do pliku tekstowego x.txt.
Deklaracje na początku programu:
#include <stdio.h>
#include "/usr/include/gsl/gsl_linalg.h"
int n, i, j, k, s, pi;
double val, sum, Lik;
FILE *fp;
n = 8;
gsl_matrix *A = gsl_matrix_calloc(n,n);
gsl_matrix *LU = gsl_matrix_calloc(n,n);
gsl_permutation *p = gsl_permutation_calloc(n);
double x[n], q[n];
//Wczytywanie, rozkład i wypisanie rozkładu:
if ((fp = fopen("A.txt", "rt")) == NULL) { printf ("\n*** (A.txt) ***\n");
return 1;
}
printf("\n*** Macierz A ***\n");
for (i=0; i < n; i++) { for(j=0; j < n; j++) {
fscanf(fp, "%lf", &val);
gsl_matrix_set(A,i,j,val);
Lab 03: Układy liniowe – metody bezpośrednie
printf("%.4lf ", gsl_matrix_get(A,i,j));
}
printf("\n");
}
fclose(fp);
gsl_linalg_LU_decomp(A, p, &s);
printf("\n*** Rozkład LU macierzy A ***\n");
for (i=0; i < n; i++) {
for (j=0; j < n; j++) printf("%.4lf ", gsl_matrix_get(A,i,j));
printf("\n");
}