MN08: Różnice pomiędzy wersjami
m Zastępowanie tekstu – „,↵</math>” na „</math>,” |
|||
(Nie pokazano 12 wersji utworzonych przez 2 użytkowników) | |||
Linia 15: | Linia 15: | ||
macierze są co prawda wielkiego wymiaru, ale najczęściej <strong>rozrzedzone</strong>, to | macierze są co prawda wielkiego wymiaru, ale najczęściej <strong>rozrzedzone</strong>, to | ||
znaczy jest w nich bardzo dużo zer. Bardzo często zdarza się, że macierz | znaczy jest w nich bardzo dużo zer. Bardzo często zdarza się, że macierz | ||
wymiaru <math> | wymiaru <math>N</math> ma tylko <math>O(N)</math> niezerowych elementów. Wykorzytanie tej specyficznej | ||
własności macierzy nie tylko prowadzi do algorytmów istotnie szybszych od ich | własności macierzy nie tylko prowadzi do algorytmów istotnie szybszych od ich | ||
analogów dla macierzy gęstych (to znaczy takich, które (w założeniu) mają <math> | analogów dla macierzy gęstych (to znaczy takich, które (w założeniu) mają <math>N^2</math> | ||
elementów), ale wręcz są jedynym sposobem na to, by niektóre zadania w ogóle | elementów), ale wręcz są jedynym sposobem na to, by niektóre zadania w ogóle | ||
stały się rozwiązywalne przy obecnym stanie techniki obliczeniowej! | stały się rozwiązywalne przy obecnym stanie techniki obliczeniowej! | ||
Linia 35: | Linia 35: | ||
[[Image:MNsparseA.png|thumb|550px|center|Struktura niezerowych elementów macierzy bcsstk38.]] | [[Image:MNsparseA.png|thumb|550px|center|Struktura niezerowych elementów macierzy bcsstk38.]] | ||
Jej <strong>współczynnik wypełnienia</strong> (to znaczy, stosunek liczby niezerowych do wszystkich elementów macierzy) wynosi jedynie <math> | Jej <strong>współczynnik wypełnienia</strong> (to znaczy, stosunek liczby niezerowych do wszystkich elementów macierzy) wynosi jedynie <math>0.006</math>, a więc macierz jest bardzo rozrzedzona: w każdym wierszu są średnio tylko 44 niezerowe elementy. | ||
</div></div> | </div></div> | ||
Linia 45: | Linia 45: | ||
Dane pochodzą z serwisu | Dane pochodzą z serwisu | ||
[http://math.nist.gov/MatrixMarket MatrixMarket]. Jest to niezbyt duża macierz, wymiaru <math> | [http://math.nist.gov/MatrixMarket MatrixMarket]. Jest to niezbyt duża macierz, wymiaru <math>496 \times 496</math>, niesymetryczna, o elementach rzeczywistych. Źródłem tej macierzy jest pewien model ekonomiczny. | ||
[[Image:MNmbeacxc|thumb|550px|center|Struktura niezerowych elementów macierzy MBEACXC]] | [[Image:MNmbeacxc|thumb|550px|center|Struktura niezerowych elementów macierzy MBEACXC]] | ||
Linia 65: | Linia 65: | ||
===Format współrzędnych=== | ===Format współrzędnych=== | ||
Do zapamiętania macierzy <math> | Do zapamiętania macierzy <math>A</math> wymiaru <math>N\times M</math> o <math>NNZ</math> niezerowych elementów wykorzystujemy trzy wektory: <code>I</code>, | ||
<code>J</code> --- oba typu <code>int</code> --- oraz <code>V</code>, typu <code>double</code>, | <code>J</code> --- oba typu <code>int</code> --- oraz <code>V</code>, typu <code>double</code>, | ||
wszystkie o długości <math> | wszystkie o długości <math>NNZ</math>, przy czym | ||
<center><math> | <center><math> | ||
A_{I[k], J[k]} = V[k], \qquad\forall k = 0,\ldots, NNZ-1 | A_{I[k], J[k]} = V[k], \qquad\forall k = 0,\ldots, NNZ-1</math></center> | ||
</math></center> | |||
[[Image:MNaij-matrix-format.png|thumb|550px|center|Format AIJ]] | [[Image:MNaij-matrix-format.png|thumb|550px|center|Format AIJ]] | ||
Linia 88: | Linia 87: | ||
Pokażemy jak w Octave wprowadzić macierz rozrzedzoną. | Pokażemy jak w Octave wprowadzić macierz rozrzedzoną. | ||
<div style="font-family: monospace; white-space: pre; border-style: dashed; border-width: thin; border-color: black; margin: 1em; padding:1em; color: #444; background-color:#fdfdfd;"><nowiki>octave:10> I = [1, 1, 1, 2, 3, 1, 4]; | <div style="font-family: monospace; white-space: pre; border-style: dashed; border-width: thin; border-color: black; margin: 1em; padding:1em; color: #444; background-color:#fdfdfd;"><realnowiki><realnowiki><realnowiki><realnowiki><nowiki>octave:10> I = [1, 1, 1, 2, 3, 1, 4]; | ||
octave:11> J = [1, 3, 2, 2, 3, 4, 4]; | octave:11> J = [1, 3, 2, 2, 3, 4, 4]; | ||
octave:12> V = [1, 2, 3, 4, 5, 6, 7]; | octave:12> V = [1, 2, 3, 4, 5, 6, 7]; | ||
Linia 106: | Linia 105: | ||
octave:15> spy(A); | octave:15> spy(A); | ||
</nowiki></div> | </nowiki></realnowiki></realnowiki></realnowiki></realnowiki></div> | ||
Strukturę jej niezerowych elementów ukaże nam polecenie <code style="color: #006">spy(A)</code>. Tak właśnie zostały wygenerowane obrazki macierzy w niniejszym wykładzie. | Strukturę jej niezerowych elementów ukaże nam polecenie <code style="color: #006">spy(A)</code>. Tak właśnie zostały wygenerowane obrazki macierzy w niniejszym wykładzie. | ||
Linia 123: | Linia 122: | ||
Podobnie jak w przypadku formatu współrzędnych, macierz w formacie CSC jest | Podobnie jak w przypadku formatu współrzędnych, macierz w formacie CSC jest | ||
przechowywana w postaci trzech wektorów: <code>AV</code> jest wektorem typu | przechowywana w postaci trzech wektorów: <code>AV</code> jest wektorem typu | ||
<code>double</code> o długości <math> | <code>double</code> o długości <math>NNZ</math>, zawierającym <strong>kolejne</strong> niezerowe elementy | ||
macierzy <math> | macierzy <math>A</math> wpisywane <strong>kolumnami</strong>, <code>AI</code> jest wektorem typu <code>int</code> | ||
o długości <math> | o długości <math>NNZ</math>, zawierającym numery wierszy macierzy <math>A</math> odpowiadających | ||
elementom z <code>AV</code>. Natomiast zamiast tablicy <code>J</code>, jak to było w | elementom z <code>AV</code>. Natomiast zamiast tablicy <code>J</code>, jak to było w | ||
formacie współrzędnych, mamy krótszy wektor typu <code>int</code>, <code>AP</code>, o | formacie współrzędnych, mamy krótszy wektor typu <code>int</code>, <code>AP</code>, o | ||
długości <math> | długości <math>M</math>, zawierający na <math>j</math>-tym miejscu indeks pozycji w <code>AV</code>, od | ||
którego rozpoczynają się w <code>AV</code> elementy <math> | którego rozpoczynają się w <code>AV</code> elementy <math>j</math>-tej kolumny macierzy <math>A</math>. | ||
[[Image:MNcsc-matrix-format.png|thumb|550px|center|Format CSC]] | [[Image:MNcsc-matrix-format.png|thumb|550px|center|Format CSC]] | ||
Mamy więc zależność, przy założeniu, że <math> | Mamy więc zależność, przy założeniu, że <math>AP[0]=0</math>, | ||
<center><math> | <center><math> | ||
A_{AI[AP[j]+k],j+1} = AV[AP[j]+k], \qquad j = 0,\ldots,M-1, \, k = | A_{AI[AP[j]+k],j+1} = AV[AP[j]+k], \qquad j = 0,\ldots,M-1, \, k = | ||
0,\ldots,AP[j+1]-1 | 0,\ldots,AP[j+1]-1</math></center> | ||
</math></center> | |||
Taki (z drobnymi modyfikacjami) format macierzy wykorzystują np. pakiety ARPACK | Taki (z drobnymi modyfikacjami) format macierzy wykorzystują np. pakiety ARPACK | ||
Linia 145: | Linia 143: | ||
Znacznie mniej uniwersalny niż poprzednie i dlatego rzadziej spotykany. Kolejne | Znacznie mniej uniwersalny niż poprzednie i dlatego rzadziej spotykany. Kolejne | ||
diagonale macierzy przechowujemy w kolejnych wierszach macierzy <math> | diagonale macierzy przechowujemy w kolejnych wierszach macierzy <math>P\times N</math>, | ||
gdzie <math> | gdzie <math>P</math> jest liczbą niezerowych diagonal w <math>A\in R^{N\times N}</math>. | ||
Szczególnie wygodny do reprezentacji macierzy taśmowych. Wykorzystywany m.in. | Szczególnie wygodny do reprezentacji macierzy taśmowych. Wykorzystywany m.in. | ||
Linia 161: | Linia 159: | ||
Zajmiemy się teraz zadaniem rozwiązywania układu równań liniowych | Zajmiemy się teraz zadaniem rozwiązywania układu równań liniowych | ||
<center><math> | <center><math> | ||
Ax = b | Ax = b</math>,</center> | ||
</math></center> | |||
ale w sytuacji, gdy macierz <math> | ale w sytuacji, gdy macierz <math>A</math> jest rozrzedzona i dużego wymiaru. Dokonamy przeglądu kilku rodzajów algorytmów mających na celu wykorzystanie rozrzedzenia macierzy dla obniżenia kosztu wyznaczenia rozwiązania układu. | ||
Należy pamiętać, że z reguły najlepsze wyniki uzyskuje się, gdy konkretny | Należy pamiętać, że z reguły najlepsze wyniki uzyskuje się, gdy konkretny | ||
Linia 174: | Linia 171: | ||
===Macierze taśmowe=== | ===Macierze taśmowe=== | ||
Macierz <math> | Macierz <math>A</math> taka, że dla <math>|i-j| \geq d</math>, <math>a_{ij} = 0</math>, nazywamy macierzą taśmową | ||
z rozstępem <math> | z rozstępem <math>d</math>, o szerokości pasma <math>2d+1</math>. | ||
Łatwo sprawdzić, że algorytm eliminacji Gaussa (bez wyboru elementu głównego) | Łatwo sprawdzić, że algorytm eliminacji Gaussa (bez wyboru elementu głównego) | ||
nie spowoduje dodatkowego wypełnienia w takiej macierzy (a więc da się wykonać w | nie spowoduje dodatkowego wypełnienia w takiej macierzy (a więc da się wykonać w | ||
miejscu). W przypadku konieczności wyboru elementu głównego, pesymistyczne | miejscu). W przypadku konieczności wyboru elementu głównego, pesymistyczne | ||
oszacowanie rozstępu macierzy rozkładu LU jest równe <math> | oszacowanie rozstępu macierzy rozkładu LU jest równe <math>\max\{2d,N\}</math> --- tak | ||
więc, dla niezbyt dużych <math> | więc, dla niezbyt dużych <math>d</math> wciąż wynikowa macierz jest taśmowa. | ||
W szczególności, gdy macierz jest taśmowa z pasmem o rozstępie <math> | W szczególności, gdy macierz jest taśmowa z pasmem o rozstępie <math>d</math> i jednocześnie | ||
diagonalnie dominująca, wtedy rozkład LU takiej macierzy da się wykonać w | diagonalnie dominująca, wtedy rozkład LU takiej macierzy da się wykonać w | ||
miejscu kosztem <math> | miejscu kosztem <math>O(d^2\,N)</math>, czyli liniowym względem <math>N</math>. | ||
W [http://www.netlib.org/lapack LAPACKu] zaimplementowano szybki ''solver'' równań z macierzami taśmowymi, | W [http://www.netlib.org/lapack LAPACKu] zaimplementowano szybki ''solver'' równań z macierzami taśmowymi, | ||
Linia 194: | Linia 191: | ||
Szczególnym przypadkiem macierzy taśmowych są macierze trójdiagonalne, tzn. taśmowe o | Szczególnym przypadkiem macierzy taśmowych są macierze trójdiagonalne, tzn. taśmowe o | ||
rozstępie <math> | rozstępie <math>d=1</math>: | ||
<center><math> | <center><math> | ||
T = | |||
\begin{pmatrix} | \begin{pmatrix} | ||
a_1 & c_1 & & & \\ | a_1 & c_1 & & & \\ | ||
Linia 207: | Linia 204: | ||
</math></center> | </math></center> | ||
Zadanie rozwiązywania równań z taką macierzą | Zadanie rozwiązywania równań z taką macierzą, | ||
<center><math> | <center><math> | ||
T x = e | |||
</math></center> | </math></center> | ||
Linia 217: | Linia 214: | ||
{{stwierdzenie||| | {{stwierdzenie||| | ||
Jeśli macierz <math> | Jeśli macierz <math>T</math> ma <strong>słabo dominującą diagonalę</strong>, tzn. | ||
<center><math> | <center><math>|a_i|\,\ge\,|b_i|\,+\,|c_i|,\qquad 1\le i\le N</math>,</center> | ||
</math></center> | |||
(<math> | (<math>b_1=0=c_N</math>) i przynajmniej dla jednego indeksu "<math>i</math>" mamy powyżej | ||
ostrą nierówność "<math> | ostrą nierówność "<math>></math>", to algorytm przeganiania jest wykonalny bez | ||
przestawień wierszy. Ponadto wymaga on <math> | przestawień wierszy. Ponadto wymaga on <math>7N</math> operacji arytmetycznych, | ||
a więc jest prawie optymalny. | a więc jest prawie optymalny. | ||
}} | }} | ||
{{algorytm|Metoda przeganiania|Metoda przeganiania| | {{algorytm|Metoda przeganiania (w miejscu)|Metoda przeganiania| | ||
< | <Source> | ||
for (i = 2; i <= N; i++) | for (i = 2; i <= N; i++) | ||
{ | { | ||
<math> | <math>l</math> = <math>b_i</math>/<math>a_{i-1}</math>; | ||
<math> | <math>a_i</math> = <math>a_i</math> - <math>l</math> * <math>c_{i-1}</math>; | ||
<math> | <math>e_i</math> = <math>e_i</math> - <math>l</math> * <math>e_{i-1}</math>; | ||
} | } | ||
<math> | <math>x_N</math> = <math>e_N</math>/<math>a_N</math>; | ||
for (i = N-1; i >= 1; i--) | for (i = N-1; i >= 1; i--) | ||
<math> | <math>x_i</math> = (<math>e_i</math> - <math>c_i</math> * <math>x_{i+1}</math>)/<math>a_i</math>; | ||
</ | </Source>}} | ||
==Metody bezpośrednie== | ==Metody bezpośrednie== | ||
Linia 250: | Linia 245: | ||
Rozważmy układ równań z macierzą diagonalnie dominującą postaci | Rozważmy układ równań z macierzą diagonalnie dominującą postaci | ||
<center><math> | <center><math>A = \begin{pmatrix} | ||
* & * & * & \cdots & * \\ | * & * & * & \cdots & * \\ | ||
* & * & & & \\ | * & * & & & \\ | ||
Linia 259: | Linia 254: | ||
</math></center> | </math></center> | ||
gdzie <math> | gdzie <math>*</math> oznacza jakiś niezerowy element. | ||
Łatwo sprawdzić, że chociaż wyjściowa macierz jest rozrzedzona, to zastosowanie do niej eliminacji Gaussa powoduje, że w wyniku | Łatwo sprawdzić, że chociaż wyjściowa macierz jest rozrzedzona, to zastosowanie do niej eliminacji Gaussa powoduje, że w wyniku | ||
dostajemy <strong>gęste</strong> czynniki rozkładu. | dostajemy <strong>gęste</strong> czynniki rozkładu. | ||
Linia 265: | Linia 260: | ||
Tymczasem wystarczy odwrócić kolejność równań i numerację niewiadomych (co dla | Tymczasem wystarczy odwrócić kolejność równań i numerację niewiadomych (co dla | ||
macierzy jest równoznaczne z odwróceniem porządku wierszy i kolumn, korzystając | macierzy jest równoznaczne z odwróceniem porządku wierszy i kolumn, korzystając | ||
z pewnej (jakiej?) macierzy permutacji <math> | z pewnej (jakiej?) macierzy permutacji <math>P</math>): | ||
<center><math> | <center><math>\widetilde{A} = PAP^T = \begin{pmatrix} | ||
* & & & & *\\ | * & & & & *\\ | ||
& \ddots & & & \vdots\\ | & \ddots & & & \vdots\\ | ||
Linia 304: | Linia 299: | ||
</pre></div> | </pre></div> | ||
Octave domyślnie przyłoży do <math> | Octave domyślnie przyłoży do <math>A</math> reordering <code style="color: #006">colamd</code> i następnie skorzysta z biblioteki UMFPACK, by rozwiązać taki układ. Dodatkowo, badane jest wcześniej, czy macierz nie jest przypadkiem taśmowa o wąskiej wstędze: jeśli jest, to korzysta się z LAPACKa. | ||
(Jak widzisz, operator rozwiązywania układu równań jest mocno przeciążony: działa i na macierzach kwadratowych, i na prostokątnych, i na rozrzedzonych --- na każdym rodzaju w inny sposób. Nie dziwi Cię chyba, dlaczego wygodnie było napisać Octave w C++?) | (Jak widzisz, operator rozwiązywania układu równań jest mocno przeciążony: działa i na macierzach kwadratowych, i na prostokątnych, i na rozrzedzonych --- na każdym rodzaju w inny sposób. Nie dziwi Cię chyba, dlaczego wygodnie było napisać Octave w C++?) | ||
Linia 321: | Linia 316: | ||
wierszy poradzi sobie algorytm rozkładu Cholesky'ego. | wierszy poradzi sobie algorytm rozkładu Cholesky'ego. | ||
[[Image:MNsparsechol.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math> | [[Image:MNsparsechol.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>L</math> wykonanego | ||
standardowym algorytmem. Czas rozkładu: 0.892013]] | standardowym algorytmem. Czas rozkładu: 0.892013]] | ||
[[Image:MNsparsecholcolamd.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math> | [[Image:MNsparsecholcolamd.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>L</math> z reorderingiem | ||
COLAMD. Czas rozkładu: 0.813038]] | COLAMD. Czas rozkładu: 0.813038]] | ||
[[Image:MNsparsecholsymamd.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math> | [[Image:MNsparsecholsymamd.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>L</math> z reorderingiem | ||
SYMAMD. Czas rozkładu: 0.487683s. Prawie dwa razy | SYMAMD. Czas rozkładu: 0.487683s. Prawie dwa razy | ||
szybciej niż bez reorderingu, chociaż i tak wskutek wzrostu wypełnienia macierzy | szybciej niż bez reorderingu, chociaż i tak wskutek wzrostu wypełnienia macierzy | ||
w dolnym trójkącie mamy aż 2 procent niezerowych elementów.]] | w dolnym trójkącie mamy aż 2 procent niezerowych elementów.]] | ||
[[Image:MNsparsecholsymrcm.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math> | [[Image:MNsparsecholsymrcm.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>L</math> z odwrotnym reorderingiem | ||
Cuthill-McKee. Czas rozkładu: 0.845928]] | Cuthill-McKee. Czas rozkładu: 0.845928]] | ||
[[Image:MNsparsecholcolperm.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math> | [[Image:MNsparsecholcolperm.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>L</math> z jeszcze | ||
innym (bardzo tanim, ale jak widać czasem zupełnie złym) reorderingiem. Czas rozkładu: 5.947936]] | innym (bardzo tanim, ale jak widać czasem zupełnie złym) reorderingiem. Czas rozkładu: 5.947936]] | ||
Na zakończenie popatrzmy, jak ważne jest spostrzeżenie symetrii macierzy: | Na zakończenie popatrzmy, jak ważne jest spostrzeżenie symetrii macierzy: | ||
[[Image:MNsparseLlu.png|thumb|550px|center|Rozkład LU, czynnik <math> | [[Image:MNsparseLlu.png|thumb|550px|center|Rozkład LU, czynnik <math>L</math> (bez reorderingu). Czas rozkładu LU: 1.696018s. Nieakceptowalny, podobnie | ||
jak drastyczne wypełnienie macierzy.]] | jak drastyczne wypełnienie macierzy.]] | ||
[[Image:MNsparseUlu.png|thumb|550px|center|Rozkład LU, czynnik <math> | [[Image:MNsparseUlu.png|thumb|550px|center|Rozkład LU, czynnik <math>U</math> (bez reorderingu)]] | ||
Jak widać, w naszym przypadku standardowe algorytmy (COLAMD i SYMAMD) poradziły sobie całkiem nieźle, chociaż wypełnienie i tak znacząco wzrosło. Zapewne, dla tej macierzy, która jest specyficznego typu --- pochodzi z dyskretyzacji równania różniczkowego --- algorytm ND mógłby tu jeszcze lepiej zadziałać. | Jak widać, w naszym przypadku standardowe algorytmy (COLAMD i SYMAMD) poradziły sobie całkiem nieźle, chociaż wypełnienie i tak znacząco wzrosło. Zapewne, dla tej macierzy, która jest specyficznego typu --- pochodzi z dyskretyzacji równania różniczkowego --- algorytm ND mógłby tu jeszcze lepiej zadziałać. | ||
Linia 356: | Linia 351: | ||
Najprostsze metody iteracyjne (najprostsze w analizie i implementacji, ale --- | Najprostsze metody iteracyjne (najprostsze w analizie i implementacji, ale --- | ||
jak można się domyślić --- w praktyce najmniej efektywne) polegają na rozkładzie | jak można się domyślić --- w praktyce najmniej efektywne) polegają na rozkładzie | ||
macierzy na część "łatwo odwracalną", <math> | macierzy na część "łatwo odwracalną", <math>M</math>, i "resztę", <math>Z</math>. Dokładniej, | ||
jeśli <math> | jeśli <math>M</math> jest nieosobliwa, to równanie <math>Ax = b</math> można zapisać jako | ||
zadanie punktu stałego | zadanie punktu stałego | ||
<center><math> | <center><math>Mx = Zx + b</math>,</center> | ||
</math></center> | |||
gdzie <math> | gdzie <math>Z=M-A</math>. Inaczej: | ||
<center><math> | <center><math>x = M^{-1}(Zx + b)</math>,</center> | ||
</math></center> | |||
i zastosować doń [[MN02#Iteracja prosta Banacha|metodę iteracji prostej Banacha]]: | i zastosować doń [[MN02#Iteracja prosta Banacha|metodę iteracji prostej Banacha]]: | ||
<center><math> | <center><math>x_{k+1} = M^{-1}(Zx_k + b)</math></center> | ||
</math></center> | |||
Takie metody nazywamy stacjonarnymi metodami iteracyjnymi. Aby przeanalizować zbieżność takiej metody, warto rozpatrzyć przypadek ogólniejszy | Takie metody nazywamy stacjonarnymi metodami iteracyjnymi. Aby przeanalizować zbieżność takiej metody, warto rozpatrzyć przypadek ogólniejszy | ||
<center><math> | <center><math> | ||
x_k\,=\,B x_{k-1}\,+\, c | x_k\,=\,B x_{k-1}\,+\, c</math>,</center> | ||
</math></center> | |||
dla pewnej macierzy <math> | dla pewnej macierzy <math>B</math> oraz wektora <math>c</math>. (Dla stacjonarnej metody iteracyjnej, <math>B=M^{-1}Z</math> oraz <math>c=M^{-1}b</math>.) | ||
W tym przypadku | W tym przypadku | ||
<center><math> | <center><math>x_k- x^*\,=\,B^k( x_0- x^*), | ||
</math></center> | </math></center> | ||
a stąd i z nierówności <math> | a stąd i z nierówności <math>\|B^k\|\le\|B\|^k</math>, mamy | ||
<center><math> | <center><math>\| x_k- x^*\|\,\le\, | ||
\|B\|^k\| x_0- x^*\|. | \|B\|^k\| x_0- x^*\|. | ||
</math></center> | </math></center> | ||
Warunkiem dostatecznym zbieżności iteracji prostych | Warunkiem dostatecznym zbieżności iteracji prostych | ||
jest więc <math> | jest więc <math>\|B\|<1</math>. Okazuje się, że warunkiem koniecznym i dostatecznym | ||
zbieżności tej iteracji dla dowolnego wektora startowego <math> | zbieżności tej iteracji dla dowolnego wektora startowego <math>x_0</math> jest | ||
<center><math> | <center><math>\rho = \max\{ |\lambda| : \lambda \mbox{ jest wartością własną } B\} < 1</math></center> | ||
</math></center> | |||
Tak więc, metody oparte na iteracji prostej będą zbieżne liniowo z ilorazem | Tak więc, metody oparte na iteracji prostej będą zbieżne liniowo z ilorazem | ||
<math> | <math>\rho</math>. | ||
Zaletą stacjonarnych metod iteracyjnych jest również ich prostota, | Zaletą stacjonarnych metod iteracyjnych jest również ich prostota, | ||
Linia 407: | Linia 397: | ||
===Metoda Jacobiego=== | ===Metoda Jacobiego=== | ||
Biorąc <math> | Biorąc <math>M = \mbox{diag} (A)</math>, gdzie <math>\mbox{diag} (A)</math> jest macierzą diagonalną składającą się | ||
z wyrazów stojących na głównej przekątnej macierzy | z wyrazów stojących na głównej przekątnej macierzy | ||
<math> | <math>A</math>, układ <math>A x= b</math> jest równoważny układowi | ||
<center><math> | <center><math>M x = Z x + b</math>,</center> | ||
</math></center> | |||
a stąd (o ile na przekątnej macierzy <math> | a stąd (o ile na przekątnej macierzy <math>A</math> nie mamy zera) | ||
otrzymujemy metodę iteracyjną | otrzymujemy metodę iteracyjną | ||
<center><math> | <center><math>x_k\,=\,B x_{k-1}\,+\, c, | ||
</math></center> | </math></center> | ||
gdzie <math> | gdzie <math>B=M^{-1}Z</math> i <math>c=M^{-1} b</math>, zwaną | ||
<strong>metodą Jacobiego</strong>. | <strong>metodą Jacobiego</strong>. | ||
Rozpisując ją po współrzędnych dostajemy (numer iteracji wyjątkowo zaznaczamy w postaci ''górnego'' indeksu) układ rozszczepionych równań: | Rozpisując ją po współrzędnych dostajemy (numer iteracji wyjątkowo zaznaczamy w postaci ''górnego'' indeksu) układ rozszczepionych równań: | ||
<center><math> | <center><math>x^{(k)}_i = \frac{1}{a_{ii}} \left( b_i - \sum_{j\neq i} a_{ij}x^{(k-1)}_j \right)</math>,</center> | ||
</math></center> | |||
co znaczy dokładnie tyle, że w <math> | co znaczy dokładnie tyle, że w <math>i</math>-tym równaniu wyjściowego układu przyjmujemy za współrzędne <math>x</math> wartości z poprzedniej iteracji i na tej podstawie wyznaczamy wartość <math>x_i</math>. | ||
{{twierdzenie|O zbieżności metody Jacobiego|O zbieżności metody Jacobiego| | {{twierdzenie|O zbieżności metody Jacobiego|O zbieżności metody Jacobiego| | ||
W metodzie Jacobiego warunek dostateczny zbieżności, | W metodzie Jacobiego warunek dostateczny zbieżności, | ||
<math> | <math>\|B\|<1</math>, jest spełniony np. wtedy, gdy macierz <math>A</math> ma | ||
dominującą przekątną, tzn. gdy | dominującą przekątną, tzn. gdy | ||
<center><math> | <center><math> | ||
|a_{i,i}|\,>\,\sum_{j\neq i}|a_{i,j}|,\qquad \forall i = 1,\ldots, N | |a_{i,i}|\,>\,\sum_{j\neq i}|a_{i,j}|,\qquad \forall i = 1,\ldots, N</math></center> | ||
</math></center> | |||
}} | }} | ||
{{dowod||| | {{dowod||| | ||
Rzeczywiście, ponieważ wyraz <math> | Rzeczywiście, ponieważ wyraz <math>(i,j)</math> macierzy <math>M^{-1}Z</math> | ||
wynosi <math> | wynosi <math>0</math> dla <math>i=j</math> oraz <math>a_{i,j}/a_{i,i}</math> dla <math>i\neq j</math>, a więc | ||
<center><math>\ | <center><math>\begin{align} \|M^{-1}Z\|_\infty \;=\; \max_{1\le i\le N} | ||
\sum_{j=1,j\ne i}^N{|a_{i,j}|}/{|a_{i,i}|} | \sum_{j=1,j\ne i}^N{|a_{i,j}|}/{|a_{i,i}|} \\ | ||
&& =\;\max_{1\le i\le N} | && =\;\max_{1\le i\le N} | ||
\sum_{j=1}^N{|a_{i,j}|}/{|a_{i,i}|}\,-\,1\;<\;1, | \sum_{j=1}^N{|a_{i,j}|}/{|a_{i,i}|}\,-\,1\;<\;1, | ||
\ | \end{align}</math></center> | ||
przy czym ostatnia nierówność wynika z warunku diagonalnej dominacji. | przy czym ostatnia nierówność wynika z warunku diagonalnej dominacji. | ||
Linia 459: | Linia 446: | ||
<div class="solution" style="margin-left,margin-right:3em;"> | <div class="solution" style="margin-left,margin-right:3em;"> | ||
Macierz <math> | Macierz <math>N\times N</math>, zwana <strong>macierzą jednowymiarowego laplasjanu</strong> | ||
<center><math> | <center><math> | ||
L = \begin{pmatrix} | L = \begin{pmatrix} | ||
2 & -1 & & \\ | 2 & -1 & & \\ | ||
Linia 472: | Linia 459: | ||
numerycznych. Ta macierz jest macierzą taśmową, symetryczną i dodatnio | numerycznych. Ta macierz jest macierzą taśmową, symetryczną i dodatnio | ||
określoną, więc układ równań z tą macierzą można bez trudu rozwiązać metodami | określoną, więc układ równań z tą macierzą można bez trudu rozwiązać metodami | ||
bezpośrednimi, kosztem <math> | bezpośrednimi, kosztem <math>O(N)</math>. Stosując do niej metodę Jacobiego mamy <math>M = 2I</math> oraz <math>Z = L - M</math>. Obliczając | ||
normę macierzy iteracji Jacobiego dostajemy <math> | normę macierzy iteracji Jacobiego dostajemy <math>||M^{-1}Z||_\infty | ||
= 1</math>, co nie rozstrzyga jeszcze o jej zbieżności lub niezbieżności. | = 1</math>, co nie rozstrzyga jeszcze o jej zbieżności lub niezbieżności. | ||
Potrzebna będzie bardziej subtelna analiza. Okazuje się, że są znane wzory na wartości własne macierzy <math> | Potrzebna będzie bardziej subtelna analiza. Okazuje się, że są znane wzory na wartości własne macierzy <math>L</math>: | ||
<center><math> | <center><math>\lambda_j = 4\sin^2 \left(\frac{j \pi }{2(N+1)} \right)</math>,</center> | ||
</math></center> | |||
dla <math> | dla <math>1 \leq j \leq N</math>. W konsekwencji, wartościami własnymi <math>M^{-1}Z = \frac{1}{2}Z = \frac{1}{2}L - I</math> są liczby <math>\mu_i = \frac{1}{2} \lambda_i - 1</math>. Ponieważ <math>0 < \mu_i < 1</math>, znaczy to, że metoda Jacobiego jest zbieżna dla macierzy <math>L</math>. | ||
Z drugiej strony, nie dajmy się zwieść optymizmowi matematyka (''"nie martw się, jest zbieżny..."''): nietrudno sprawdzić, że <math> | Z drugiej strony, nie dajmy się zwieść optymizmowi matematyka (''"nie martw się, jest zbieżny..."''): nietrudno sprawdzić, że <math>||Z||_2 = 1 - O(N^{-2}) < 1</math>, co oznacza, że metoda Jacobiego --- choć zbieżna --- dla dużych <math>N</math> staje się | ||
zbieżna tak wolno, że w praktyce bezużyteczna! | zbieżna tak wolno, że w praktyce bezużyteczna! | ||
</div></div> | </div></div> | ||
Linia 493: | Linia 479: | ||
--> | --> | ||
Heurystyka tej metody opiera się na zmodyfikowaniu metody Jacobiego tak, by w każdym momencie iteracji korzystać z najbardziej "aktualnych" współrzędnych przybliżenia rozwiązania <math> | Heurystyka tej metody opiera się na zmodyfikowaniu metody Jacobiego tak, by w każdym momencie iteracji korzystać z najbardziej "aktualnych" współrzędnych przybliżenia rozwiązania <math>x</math>. | ||
Rzeczywiście, przecież rozwiązując równanie metody Jacobiego: | Rzeczywiście, przecież rozwiązując równanie metody Jacobiego: | ||
<center><math> | <center><math>x^{(k)}_i = \frac{1}{a_{ii}} \left( b_i - \sum_{j\neq i} a_{ij}x^{(k-1)}_j \right)</math>,</center> | ||
</math></center> | |||
nietrudno zauważyć, że w części sumy moglibyśmy odwoływać się do "dokładniejszych" wartości <math> | nietrudno zauważyć, że w części sumy moglibyśmy odwoływać się do "dokładniejszych" wartości <math>x^{(k)}_j</math>: dla <math>j < i</math>, tzn. | ||
<center><math> | <center><math>x^{(k)}_i = \frac{1}{a_{ii}} \left( b_i - \sum_{j< i} a_{ij}x^{(k)}_j - \sum_{j>i} a_{ij}x^{(k-1)}_j \right)</math></center> | ||
</math></center> | |||
W języku rozkładu macierzy <math> | W języku rozkładu macierzy <math>A = M - Z</math> i iteracji <math>x_{k+1} = M^{-1}(Zx_k + b)</math> mamy więc <math>M = \mbox{tril} (A)</math> (dolny trójkąt macierzy <math>A</math>). | ||
{{twierdzenie|O zbieżności metody Gaussa-Seidela|O zbieżności metody Gaussa-Seidela| | {{twierdzenie|O zbieżności metody Gaussa-Seidela|O zbieżności metody Gaussa-Seidela| | ||
Jeśli macierz <math> | Jeśli macierz <math>A</math> jest diagonalnie dominująca, to metoda Gaussa--Seidela jest zbieżna dla dowolnego wektora startowego <math>x_0</math>. | ||
}} | }} | ||
Inny wariant tej metody dostalibyśmy, biorąc za <math> | Inny wariant tej metody dostalibyśmy, biorąc za <math>M</math> górny trójkąt macierzy <math>A</math>. | ||
Metoda Gaussa--Seidela jest w wielu przypadkach rzeczywiście szybciej zbieżna od metody Jacobiego, np. tak jest w przypadku macierzy jednowymiarowego Laplasjanu. Wciąż jednak, dodajmy, dla zadań bardzo źle uwarunkowanych jej zbieżność jest zbyt wolna by ją stosować jako samodzielną metodę. | Metoda Gaussa--Seidela jest w wielu przypadkach rzeczywiście szybciej zbieżna od metody Jacobiego, np. tak jest w przypadku macierzy jednowymiarowego Laplasjanu. Wciąż jednak, dodajmy, dla zadań bardzo źle uwarunkowanych jej zbieżność jest zbyt wolna by ją stosować jako samodzielną metodę. | ||
Linia 525: | Linia 509: | ||
===Złożoność stacjonarnych metod iteracyjnych=== | ===Złożoność stacjonarnych metod iteracyjnych=== | ||
Zastanówmy się teraz nad złożonością metod iteracyjnych. Ponieważ możemy jedynie znaleźć pewne przybliżenie rozwiązania dokładnego <math> | Zastanówmy się teraz nad złożonością metod iteracyjnych. Ponieważ możemy jedynie znaleźć pewne przybliżenie rozwiązania dokładnego <math>x^*</math>, przez złożoność metody będziemy rozumieli koszt kombinatoryczny obliczenia <math>x_k</math> z zadaną dokładnością <math>\epsilon>0</math>. Dla uproszczenia założymy, że medoda jest zbieżna liniowo z ilorazem <math>\rho</math>. Zauważmy, że aby zredukować błąd początkowy do <math>\epsilon>0</math>, wystarczy wykonać <math>k=k(\epsilon)</math> iteracji, gdzie <math>k</math> spełnia | ||
<center><math> | <center><math>\rho^k\| x_0- x^*\|\,\le\,\epsilon</math>,</center> | ||
</math></center> | |||
czyli | czyli | ||
<center><math> | <center><math>k\,\ge\,\frac{\log(1/\epsilon) - \log(1/\| x_0- x^*\|)}{\log(1/\rho)}</math></center> | ||
</math></center> | |||
Liczba ta zależy więc w istotny sposób od błędu początkowego i (przede wszystkim) od współczynnika redukcji błędu <math> | Liczba ta zależy więc w istotny sposób od błędu początkowego i (przede wszystkim) od współczynnika redukcji błędu <math>\rho</math>, natomiast zależność od dokładności <math>\epsilon</math> i wymiaru <math>N</math> układu jest dużo mniej istotna (w zadaniach praktycznych -- takich jak jednowymiarowy laplasjan --- jednak często | ||
okazuje się, że... <math> | okazuje się, że... <math>\rho</math> zależy od <math>N</math>!). | ||
Zakładając, że koszt jednej iteracji wynosi <math> | Zakładając, że koszt jednej iteracji wynosi <math>c=c(N)</math> (<math>c(N)</math> jest tym mniejszy, im mniejsza jest liczba niezerowych elementów macierzy <math>A</math>), złożoność metody jest proporcjonalna do | ||
<center><math> | <center><math>c(N)\,\frac{\log(1/\epsilon)}{\log(1/\rho)}. | ||
</math></center> | </math></center> | ||
Stąd oczywisty wniosek (prawdziwy nie tylko dla metod stacjonarnych), że metody iteracyjne warto stosować zamiast metod bezpośrednich w przypadku, gdy | Stąd oczywisty wniosek (prawdziwy nie tylko dla metod stacjonarnych), że metody iteracyjne warto stosować zamiast metod bezpośrednich w przypadku, gdy | ||
* wymiar <math> | * wymiar <math>N</math> układu <math>A x= b</math> jest "duży", oraz | ||
* macierz <math> | * macierz <math>A</math> układu jest "rozrzedzona", tzn. ma stosunkowo niewielką liczbę elementów niezerowych, np. proporcjonalną do <math>N</math>. | ||
Układy o tych własnościach powstają często przy numerycznym rozwiązywaniu równań różniczkowych cząstkowych. | Układy o tych własnościach powstają często przy numerycznym rozwiązywaniu równań różniczkowych cząstkowych. | ||
==Metody przestrzeni Kryłowa== | ==Metody przestrzeni Kryłowa== | ||
Zupełnie inny pomysł na realizację metody iteracyjnej przedstawiają metody przestrzeni Kryłowa, gdzie kolejne przybliżenie <math> | Zupełnie inny pomysł na realizację metody iteracyjnej przedstawiają metody przestrzeni Kryłowa, gdzie kolejne przybliżenie <math>x_k</math> dobiera się w taki sposób, by minimalizowało pewną miarę błędu na podprzestrzeni Kryłowa | ||
<center><math> | <center><math>K_k = \mbox{span} \{r,Ar,\ldots, A^{k-1}r \}</math>,</center> | ||
</math></center> | |||
gdzie <math> | gdzie <math>r = b-Ax_0</math> jest ''residuum'' na początku iteracji. (Zwróć uwagę, że przestrzeń Kryłowa jest rozpięta przez kolejne wektory [[MN13#Metoda potęgowa|metody potęgowej]]] --- to nie przypadek!). W zależności od wyboru sposobu miary błędu, dostajemy inną metodę iteracyjną, takie jak CG, GMRES, PCR, BiCG, i inne. Tutaj omówimy pokrótce tylko najpopularniejszą: CG. | ||
===CG=== | ===CG=== | ||
Metoda <strong>gradientów sprzężonych</strong>, w skrócie CG (''conjugate gradients''), działa przy założeniu, że <math> | Metoda <strong>gradientów sprzężonych</strong>, w skrócie CG (''conjugate gradients''), działa przy założeniu, że <math>A</math> jest <strong>symetryczna i dodatnio określona</strong>. | ||
Kolejne przybliżenie <math> | Kolejne przybliżenie <math>x_k</math> ma minimalizować błąd w normie energetycznej | ||
indukowanej przez <math> | indukowanej przez <math>A</math>, | ||
<center><math> | <center><math>||x_k -x||_A = \sqrt{(x_k -x)^TA(x_k -x)} | ||
</math></center> | </math></center> | ||
na przestrzeni afinicznej <math> | na przestrzeni afinicznej <math>x_0 + K_k</math>. Okazuje się (co ''nie jest'' oczywiste --- trzeba skorzystać z rozmaitych własności ortogonalności generowanych wektorów), że takie zadanie minimalizacji daje się bardzo efektywnie rozwiązać, skąd dostajemy bardzo zwarty algorytm: | ||
{{algorytm|Metoda CG|Metoda CG| | {{algorytm|Metoda CG|Metoda CG| | ||
< | <Source>r = b-A*x; | ||
<math> | <math>\rho_0</math> = <math>||r||_2^2</math>; <math>\beta</math> = 0; k = 1; | ||
while (!stop) | while (!stop) | ||
{ | { | ||
p = r + <math> | p = r + <math>\beta</math>*p; | ||
w = A*p; | w = A*p; | ||
<math> | <math>\alpha</math> = <math>\rho_{k-1}</math>/<math>p^Tw</math>; | ||
x = x + <math> | x = x + <math>\alpha</math>*p; | ||
r = r - <math> | r = r - <math>\alpha</math>*w; | ||
<math> | <math>\rho_k</math> = <math>||r||_2^2</math>; | ||
<math> | <math>\beta</math> = <math>\frac{\rho_{k}}{\rho_{k-1}}</math>; | ||
k++; | k++; | ||
} | } | ||
</ | </Source>}} | ||
Jak widać, całą iterację da się wykonać przechowując w pamięci tylko kilka wektorów (a nie, jak możnaby się obawiać, całą przestrzeń <math> | Jak widać, całą iterację da się wykonać przechowując w pamięci tylko kilka wektorów (a nie, jak możnaby się obawiać, całą przestrzeń <math>K_k</math>), a najdroższym jej elementem jest mnożenie macierzy przez wektor. | ||
{{twierdzenie|O zbieżności CG jako metody bezpośredniej|O zbieżności CG jako metody bezpośredniej| | {{twierdzenie|O zbieżności CG jako metody bezpośredniej|O zbieżności CG jako metody bezpośredniej| | ||
Niech <math> | Niech <math>A\in R^{N\times N}</math> będzie symetryczna i dodatnio określona. Algorytm CG znajdzie dokładne rozwiązanie po co najwyżej <math>N</math> iteracjach. | ||
}} | }} | ||
Powyższe twierdzenie, choć teoretycznie interesujące, ma małą wartość praktyczną z dwóch powodów: | Powyższe twierdzenie, choć teoretycznie interesujące, ma małą wartość praktyczną z dwóch powodów: | ||
* dla bardzo dużych <math> | * dla bardzo dużych <math>N</math>, wykonanie <math>N</math> iteracji może być wciąż zbyt kosztownym zadaniem; | ||
* ponieważ w arytmetyce skończonej precyzji ortogonalność --- z której w bardzo istotny sposób korzysta się przy wyprowadzeniu algorytmu --- pogarsza się z iteracji na iterację i w konsekwencji, po wielu iteracjach, jakość <math> | * ponieważ w arytmetyce skończonej precyzji ortogonalność --- z której w bardzo istotny sposób korzysta się przy wyprowadzeniu algorytmu --- pogarsza się z iteracji na iterację i w konsekwencji, po wielu iteracjach, jakość <math>x_k</math> przestaje się poprawiać. | ||
Dlatego wygodniej potraktować CG jako metodę iteracyjną. Zachodzi bowiem | Dlatego wygodniej potraktować CG jako metodę iteracyjną. Zachodzi bowiem | ||
Linia 601: | Linia 582: | ||
{{twierdzenie|Zbieżność CG jako metody iteracyjnej|Zbieżność CG jako metody iteracyjnej| | {{twierdzenie|Zbieżność CG jako metody iteracyjnej|Zbieżność CG jako metody iteracyjnej| | ||
Po <math> | Po <math>k</math> iteracjach metody CG, | ||
<center><math> | <center><math>||x_k - x||_A \leq 2 \, \left( \frac{\sqrt{ \mbox{cond} (A)} - 1}{\sqrt{ \mbox{cond} (A)} +1}\right)^k \, ||x_0 - x||_A</math>,</center> | ||
</math></center> | |||
gdzie <math> | gdzie <math>\mbox{cond} (A) = ||A||_2||A^{-1}||_2</math>. | ||
}} | }} | ||
Linia 621: | Linia 601: | ||
Dlatego bardzo korzystne może być wstępne przetransformowanie układu | Dlatego bardzo korzystne może być wstępne przetransformowanie układu | ||
<center><math> | <center><math>Ax = b | ||
</math></center> | </math></center> | ||
z macierzą o niekorzystnych własnościach, do układu | z macierzą o niekorzystnych własnościach, do układu | ||
<center><math> | <center><math>MAx = Mb</math>,</center> | ||
</math></center> | |||
gdzie macierz <math> | gdzie macierz <math>MA</math> ma znacznie korzystniejsze własności z punktu widzenia używanej metody iteracyjnej. W przypadku macierzy symetrycznych widzieliśmy, że kluczowe znaczenie dla zbieżności metody miał rozkład wartości własnych: jeśli wartości własne były bardzo rozrzucone po prostej, to uwarunkowanie było bardzo duże i w konsekwencji zbieżność powolna. Aby zbieżność była szybsza, kluczowe jest, by: | ||
* wartości własne <math> | * wartości własne <math>MA</math> były upakowane w klastrach | ||
* najlepiej wszystkie w (małym) otoczeniu wartości 1 | * najlepiej wszystkie w (małym) otoczeniu wartości 1 | ||
Jeśli więc chcielibyśmy przekształcić macierz tak, by metoda iteracyjna dla <math> | Jeśli więc chcielibyśmy przekształcić macierz tak, by metoda iteracyjna dla <math>MA</math> zbiegała szybko, musimy w jakiś sposób "ścisnąć" spektrum macierzy <math>A</math> w okolice jedności. Taką operację nazywamy <strong>ściskaniem</strong> (''preconditioning''), a macierz <math>M</math> --- <strong>macierzą ściskającą</strong>. | ||
Aby całość miała sens, macierz ściskająca <math> | Aby całość miała sens, macierz ściskająca <math>M</math> powinna: | ||
* być łatwa w konstrukcji, | * być łatwa w konstrukcji, | ||
* być tania w mnożeniu przez wektor (głównym elementem każdej metody iteracyjnej jest mnożenie macierzy przez wektor: <math> | * być tania w mnożeniu przez wektor (głównym elementem każdej metody iteracyjnej jest mnożenie macierzy przez wektor: <math>M\cdot (A \cdot x)</math>), | ||
* macierz <math> | * macierz <math>MA</math> powinna mieć znacznie korzystniejsze własności z punktu widzenia używanej metody iteracyjnej. | ||
Kilka ekstremalnych propozycji na macierz | Kilka ekstremalnych (lecz wątpliwej jakości) "propozycji" na macierz ściskającą to <math>M = I</math> (łatwa w | ||
konstrukcji i tania w mnożeniu, ale niestety nic nie polepsza...) oraz | konstrukcji i tania w mnożeniu, ale niestety nic nie polepsza...) oraz | ||
<math> | <math>M=A^{-1}</math> (rewelacyjnie poprawia zbieżność metody iteracyjnej, dając zbieżność | ||
w jednej iteracji, ale bardzo droga w konstrukcji i mnożeniu). Widać więc, że | w jednej iteracji, ale bardzo droga w konstrukcji i mnożeniu). Widać więc, że | ||
należy poszukiwać czegoś pośredniego, co niskim kosztem przybliża działanie | należy poszukiwać czegoś pośredniego, co niskim kosztem przybliża działanie | ||
Linia 657: | Linia 636: | ||
Okazuje się, że zarówno CG jak i GMRES da się zaimplementować tak, by w jednej | Okazuje się, że zarówno CG jak i GMRES da się zaimplementować tak, by w jednej | ||
iteracji było konieczne tylko jedno mnożenie przez macierz | iteracji było konieczne tylko jedno mnożenie przez macierz ściskającą. | ||
==Literatura== | ==Literatura== |
Aktualna wersja na dzień 21:44, 11 wrz 2023
Wielkie układy równań liniowych
<<< Powrót do strony głównej przedmiotu Metody numeryczne
Wraz z coraz większymi modelami pojawiającymi się w praktyce obliczeniowej, coraz częściej zachodzi potrzeba rozwiązywania zadań algebry liniowej, w której macierze są co prawda wielkiego wymiaru, ale najczęściej rozrzedzone, to znaczy jest w nich bardzo dużo zer. Bardzo często zdarza się, że macierz wymiaru ma tylko niezerowych elementów. Wykorzytanie tej specyficznej własności macierzy nie tylko prowadzi do algorytmów istotnie szybszych od ich analogów dla macierzy gęstych (to znaczy takich, które (w założeniu) mają elementów), ale wręcz są jedynym sposobem na to, by niektóre zadania w ogóle stały się rozwiązywalne przy obecnym stanie techniki obliczeniowej!
Jednym ze szczególnie ważnych źródeł układów równań z macierzami rozrzedzonymi są np. równania różniczkowe cząstkowe (a więc np. modele pogody, naprężeń w konstrukcji samochodu, przenikania kosmetyków do głębszych warstw skóry, itp.).
Modele wielostanowych systemów kolejkowych (np. routera obsługującego wiele komputerów) także prowadzą do gigantycznych układów równań z macierzami rozrzedzonymi o specyficznej strukturze.
Z reguły zadania liniowe wielkiego wymiaru będą miały strukturę macierzy rozrzedzonej, gdyż najczęściej związki pomiędzy niewiadomymi w równaniu nie dotyczą wszystkich, tylko wybranej grupy.
Przykład: Macierz z kolekcji Boeinga
Spójrzmy na macierz sztywności dla modelu silnika lotniczego, wygenerowaną swego czasu w zakładach Boeinga i pochodzącą z dyskretyzacji pewnego równania różniczkowego cząstkowego. Pochodzi z kolekcji Tima Davisa. Jest to mała macierz, wymiaru 8032 (w kolekcji spotkasz równania z milionem i więcej niewiadomych).

Jej współczynnik wypełnienia (to znaczy, stosunek liczby niezerowych do wszystkich elementów macierzy) wynosi jedynie , a więc macierz jest bardzo rozrzedzona: w każdym wierszu są średnio tylko 44 niezerowe elementy.
Reprezentacja macierzy rzadkich
Zacznijmy od sposobu przechowywania macierzy rozrzedzonych. Naturalnie, nie ma sensu przechowywać wszystkich zerowych jej elementów: wystarczy ograniczyć się do zachowania tych niezerowych! W ten sposób zmniejszamy zarówno wymagania pamięciowe, jak i liczbę operacji zmiennoprzecinkowych potrzebnych do prowadzenia działań na macierzy (np. w przypadku mnożenia macierzy przez wektor, nie będziemy mnożyć przez zera!).
Format współrzędnych
Do zapamiętania macierzy wymiaru o niezerowych elementów wykorzystujemy trzy wektory: I
,
J
--- oba typu int
--- oraz V
, typu double
,
wszystkie o długości , przy czym

W tym formacie wprowadzane są macierze rzadkie do Octave'a i MATLABa:
A = sparse(I,J,V,N,N);
Jednak wewnętrznie przechowywane są w innym formacie, o którym poniżej.
Przykład
Pokażemy jak w Octave wprowadzić macierz rozrzedzoną.
Strukturę jej niezerowych elementów ukaże nam polecenie spy(A)
. Tak właśnie zostały wygenerowane obrazki macierzy w niniejszym wykładzie.
Format spakowanych kolumn (wierszy)
Format współrzędnych nie narzucał żadnego uporządkowania elementów macierzy --- można było je umieszczać w dowolnej kolejności. Narzucenie sensownego porządku mogłoby wspomóc realizację wybranych istotnych operacji na macierzy, na przykład, aby wygodnie było realizować działanie (prawostronnego) mnożenia macierzy przez wektor, dobrze byłoby przechowywać elementy macierzy wierszami. Tak właśnie jest zorganizowany format spakowanych wierszy (Compressed Sparse Row, CSR). Analogicznie jest zdefiniowany format spakowanych kolumn (Compressed Sparse Column, CSC), którym zajmiemy się bliżej.
Podobnie jak w przypadku formatu współrzędnych, macierz w formacie CSC jest
przechowywana w postaci trzech wektorów: AV
jest wektorem typu
double
o długości , zawierającym kolejne niezerowe elementy
macierzy wpisywane kolumnami, AI
jest wektorem typu int
o długości , zawierającym numery wierszy macierzy odpowiadających
elementom z AV
. Natomiast zamiast tablicy J
, jak to było w
formacie współrzędnych, mamy krótszy wektor typu int
, AP
, o
długości , zawierający na -tym miejscu indeks pozycji w AV
, od
którego rozpoczynają się w AV
elementy -tej kolumny macierzy .

Mamy więc zależność, przy założeniu, że ,
Taki (z drobnymi modyfikacjami) format macierzy wykorzystują np. pakiety ARPACK i UMFPACK (a także, wewnętrznie, Octave i MATLAB).
Format diagonalny
Znacznie mniej uniwersalny niż poprzednie i dlatego rzadziej spotykany. Kolejne diagonale macierzy przechowujemy w kolejnych wierszach macierzy , gdzie jest liczbą niezerowych diagonal w .
Szczególnie wygodny do reprezentacji macierzy taśmowych. Wykorzystywany m.in.
przez funkcję LAPACKa DGBSV
służącą rozwiązywaniu równań z macierzami
taśmowymi.
Uwagi praktyczne
Mnożenie macierzy w formacie AIJ przez wektor jest kilka razy wolniejsze w porównaniu do macierzy w formacie CSC/CSR (z tych dwóch oczywiście (dlaczego?) CSR jest najszybszy). Co więcej, okazuje się, że w typowych implementacjach, mnożenie macierzy rozrzedzonej (reprezentowanej np. w formacie CSC) przez wektor jest mało efektywne, mniej więcej na poziomie dziesięciu procent możliwości obliczeniowych procesora.
Jeśli już poważnie myśleć o przyspieszeniu mnożenia macierzy przez wektor (np. gdy chcemy stosować iteracyjną metodę rozwiązywania układu równań z tą macierzą), warto rozważyć inne formaty --- łączące w sobie podział macierzy na bloki (tak, jak w algorytmach BLAS) i przechowywanie (w zasadzie) tylko niezerowych elementów macierzy.
Macierze specjalne
Zajmiemy się teraz zadaniem rozwiązywania układu równań liniowych
ale w sytuacji, gdy macierz jest rozrzedzona i dużego wymiaru. Dokonamy przeglądu kilku rodzajów algorytmów mających na celu wykorzystanie rozrzedzenia macierzy dla obniżenia kosztu wyznaczenia rozwiązania układu.
Należy pamiętać, że z reguły najlepsze wyniki uzyskuje się, gdy konkretny algorytm dobierze się do konkretnej macierzy. W zastosowaniach pojawiają się m.in. macierze rzadkie o bardzo szczególnej strukturze, dla nich warto stosować wyspecjalizowane algorytmy.
Macierze taśmowe
Macierz taka, że dla , , nazywamy macierzą taśmową z rozstępem , o szerokości pasma .
Łatwo sprawdzić, że algorytm eliminacji Gaussa (bez wyboru elementu głównego) nie spowoduje dodatkowego wypełnienia w takiej macierzy (a więc da się wykonać w miejscu). W przypadku konieczności wyboru elementu głównego, pesymistyczne oszacowanie rozstępu macierzy rozkładu LU jest równe --- tak więc, dla niezbyt dużych wciąż wynikowa macierz jest taśmowa.
W szczególności, gdy macierz jest taśmowa z pasmem o rozstępie i jednocześnie diagonalnie dominująca, wtedy rozkład LU takiej macierzy da się wykonać w miejscu kosztem , czyli liniowym względem .
W LAPACKu zaimplementowano szybki solver równań z macierzami taśmowymi,
DGBSV
, ale wymagający specjalnego sposobu
przechowywania macierzy, wykorzystującego format diagonalny.
Macierze trójdiagonalne
Szczególnym przypadkiem macierzy taśmowych są macierze trójdiagonalne, tzn. taśmowe o rozstępie :
Zadanie rozwiązywania równań z taką macierzą,
jest bardzo często spotykane, więc warto przytoczyć algorytm w całej okazałości --- popularnie zwany algorytmem przeganiania (niektóre źródła nazywają go algorytmem Thomasa).
Zacznijmy jednak od stwierdzenia, kiedy macierz trójdiagonalna nie wymaga wyboru elementu głównego:
Stwierdzenie
Jeśli macierz ma słabo dominującą diagonalę, tzn.
() i przynajmniej dla jednego indeksu "" mamy powyżej ostrą nierówność "", to algorytm przeganiania jest wykonalny bez przestawień wierszy. Ponadto wymaga on operacji arytmetycznych, a więc jest prawie optymalny.
Algorytm Metoda przeganiania (w miejscu)
for (i = 2; i <= N; i++)
{
<math>l</math> = <math>b_i</math>/<math>a_{i-1}</math>;
<math>a_i</math> = <math>a_i</math> - <math>l</math> * <math>c_{i-1}</math>;
<math>e_i</math> = <math>e_i</math> - <math>l</math> * <math>e_{i-1}</math>;
}
<math>x_N</math> = <math>e_N</math>/<math>a_N</math>;
for (i = N-1; i >= 1; i--)
<math>x_i</math> = (<math>e_i</math> - <math>c_i</math> * <math>x_{i+1}</math>)/<math>a_i</math>;
Metody bezpośrednie
Przykład: Strzałka Wilkinsona
Rozważmy układ równań z macierzą diagonalnie dominującą postaci
gdzie oznacza jakiś niezerowy element. Łatwo sprawdzić, że chociaż wyjściowa macierz jest rozrzedzona, to zastosowanie do niej eliminacji Gaussa powoduje, że w wyniku dostajemy gęste czynniki rozkładu.
Tymczasem wystarczy odwrócić kolejność równań i numerację niewiadomych (co dla macierzy jest równoznaczne z odwróceniem porządku wierszy i kolumn, korzystając z pewnej (jakiej?) macierzy permutacji ):
Wtedy okazuje się, że rozkład naszej macierzy nie powoduje już wypełnienia czynników rozkładu!
Właśnie na tym polega główny problem w rozwiązywaniu układów z macierzami rzadkimi metodami bezpośrednimi: jak maksymalnie wykorzystać rozrzedzenie macierzy tak, by czynniki rozkładu były możliwie mało wypełnione. Albowiem wiedząc to będziemy mogli ograniczyć się jedynie do fizycznego wyznaczenia wartości niezerowych elementów macierzy rozkładu. Ponadto wymagania pamięciowe algorytmu nie będą istotnie wykraczać ponad ilość pamięci potrzebnej na przechowanie danych (tzn. macierzy).
W ogólnym przypadku rozwiązanie takiego zadania jest trudne i większość algorytmów opiera się na pewnych heurystykach, które jednak w praktyce warto wspomóc wcześniejszą analizą konkretnego układu równań jaki mamy rozwiązać. Najczęściej dąży się do takiego przenumerowania równań i niewiadomych, by w efekcie z góry przewidzieć, gdzie wystąpią zera w macierzach rozkładu --- i, by takich zer było jak najwięcej (by wypełnienie było jak najmniejsze)! Na architekturach z pamięcią hierarchiczną dąży się także do tego, by w trakcie rozkładu można było korzystać z BLAS Level 3, a więc permutacje wierszy i kolumn macierzy muszą to także brać pod uwagę.
Stosuje się kilka strategii wyznaczania korzystnych permutacji (reorderingu), z których warto wymienić
- przybliżone algorytmy minimalnego stopnia (approximate minimum degree, AMD), np. AMD;
- techniki podziału grafów na (prawie) rozłączne składowe nested dissection, ND, np. METIS.
Używają ich biblioteki takie jak UMFPACK, czy HSL.
W Octave mamy do dyspozycji także kilka procedur generujących takie permutacje, w tym: colamd
(AMD dla macierzy niesymetrycznych) oraz symamd
(AMD dla macierzy symetrycznych). Większy wybór oferuje MATLAB, jednak należy bezwzględnie pamiętać o jednym: nie ma uniwersalnej metody reorderingu i dla konkretnej macierzy może istnieć specjalna metoda, która da oszałamiające rezultaty, podczas gdy standardowe podejścia nie dadzą efektu.
Przykład: Rozwiązywanie układu z macierzą rozrzedzoną w Octave
Najprostszy sposób na wykorzystanie metody bezpośredniego rozwiązywania układu z macierzą rzadką to zastosowanie znanego nam operatora do macierzy typu rozrzedzonego:
A = sparse(...); x = A \ b;
Octave domyślnie przyłoży do reordering colamd
i następnie skorzysta z biblioteki UMFPACK, by rozwiązać taki układ. Dodatkowo, badane jest wcześniej, czy macierz nie jest przypadkiem taśmowa o wąskiej wstędze: jeśli jest, to korzysta się z LAPACKa.
(Jak widzisz, operator rozwiązywania układu równań jest mocno przeciążony: działa i na macierzach kwadratowych, i na prostokątnych, i na rozrzedzonych --- na każdym rodzaju w inny sposób. Nie dziwi Cię chyba, dlaczego wygodnie było napisać Octave w C++?)
Przykład: Wypełnienie pewnej macierzy w zależności od użytego reorderingu
Rozważmy ponownie macierz pochodzącą z kolekcji Tima Davisa. Jest to macierz symetryczna, dodatnio określona, wymiaru 8032, o 355460 elementach niezerowych i, w konsekwencji, o wypełnieniu około 0.6 procent.

Zobaczymy, jak w zależności od użytego algorytmu permutacji kolumn i wierszy poradzi sobie algorytm rozkładu Cholesky'ego.





Na zakończenie popatrzmy, jak ważne jest spostrzeżenie symetrii macierzy:


Jak widać, w naszym przypadku standardowe algorytmy (COLAMD i SYMAMD) poradziły sobie całkiem nieźle, chociaż wypełnienie i tak znacząco wzrosło. Zapewne, dla tej macierzy, która jest specyficznego typu --- pochodzi z dyskretyzacji równania różniczkowego --- algorytm ND mógłby tu jeszcze lepiej zadziałać.
Stacjonarne metody iteracyjne
Gdy macierz jest rozrzedzona, mnożenie takiej macierzy przez wektor jest bardzo tanie (koszt jest proporcjonalny do liczby niezerowych elementów macierzy). Dlatego, jeśli możemy zadowolić się rozwiązaniem przybliżonym układu, a w zamian osiągnąć je tanim kosztem, warto rozważyć metody iteracyjne.
Najprostsze metody iteracyjne (najprostsze w analizie i implementacji, ale --- jak można się domyślić --- w praktyce najmniej efektywne) polegają na rozkładzie macierzy na część "łatwo odwracalną", , i "resztę", . Dokładniej, jeśli jest nieosobliwa, to równanie można zapisać jako zadanie punktu stałego
gdzie . Inaczej:
i zastosować doń metodę iteracji prostej Banacha:
Takie metody nazywamy stacjonarnymi metodami iteracyjnymi. Aby przeanalizować zbieżność takiej metody, warto rozpatrzyć przypadek ogólniejszy
dla pewnej macierzy oraz wektora . (Dla stacjonarnej metody iteracyjnej, oraz .)
W tym przypadku
a stąd i z nierówności , mamy
Warunkiem dostatecznym zbieżności iteracji prostych jest więc . Okazuje się, że warunkiem koniecznym i dostatecznym zbieżności tej iteracji dla dowolnego wektora startowego jest
Tak więc, metody oparte na iteracji prostej będą zbieżne liniowo z ilorazem .
Zaletą stacjonarnych metod iteracyjnych jest również ich prostota, przez co są one łatwe do zaprogramowania, co łatwo zobaczyć na przykładach metod: Jacobiego i Gaussa--Seidela, które teraz omówimy.
Metoda Jacobiego
Biorąc , gdzie jest macierzą diagonalną składającą się z wyrazów stojących na głównej przekątnej macierzy , układ jest równoważny układowi
a stąd (o ile na przekątnej macierzy nie mamy zera) otrzymujemy metodę iteracyjną
gdzie i , zwaną metodą Jacobiego.
Rozpisując ją po współrzędnych dostajemy (numer iteracji wyjątkowo zaznaczamy w postaci górnego indeksu) układ rozszczepionych równań:
co znaczy dokładnie tyle, że w -tym równaniu wyjściowego układu przyjmujemy za współrzędne wartości z poprzedniej iteracji i na tej podstawie wyznaczamy wartość .
Twierdzenie O zbieżności metody Jacobiego
W metodzie Jacobiego warunek dostateczny zbieżności, , jest spełniony np. wtedy, gdy macierz ma dominującą przekątną, tzn. gdy
Dowód
Rzeczywiście, ponieważ wyraz macierzy wynosi dla oraz dla , a więc
przy czym ostatnia nierówność wynika z warunku diagonalnej dominacji.

Przykład: Macierz laplasjanu
Macierz , zwana macierzą jednowymiarowego laplasjanu
pojawia się w bardzo wielu zastosowaniach, także jako podzadanie w algorytmach numerycznych. Ta macierz jest macierzą taśmową, symetryczną i dodatnio określoną, więc układ równań z tą macierzą można bez trudu rozwiązać metodami bezpośrednimi, kosztem . Stosując do niej metodę Jacobiego mamy oraz . Obliczając normę macierzy iteracji Jacobiego dostajemy , co nie rozstrzyga jeszcze o jej zbieżności lub niezbieżności.
Potrzebna będzie bardziej subtelna analiza. Okazuje się, że są znane wzory na wartości własne macierzy :
dla . W konsekwencji, wartościami własnymi są liczby . Ponieważ , znaczy to, że metoda Jacobiego jest zbieżna dla macierzy .
Z drugiej strony, nie dajmy się zwieść optymizmowi matematyka ("nie martw się, jest zbieżny..."): nietrudno sprawdzić, że , co oznacza, że metoda Jacobiego --- choć zbieżna --- dla dużych staje się zbieżna tak wolno, że w praktyce bezużyteczna!
Metoda Gaussa-Seidela
Heurystyka tej metody opiera się na zmodyfikowaniu metody Jacobiego tak, by w każdym momencie iteracji korzystać z najbardziej "aktualnych" współrzędnych przybliżenia rozwiązania .
Rzeczywiście, przecież rozwiązując równanie metody Jacobiego:
nietrudno zauważyć, że w części sumy moglibyśmy odwoływać się do "dokładniejszych" wartości : dla , tzn.
W języku rozkładu macierzy i iteracji mamy więc (dolny trójkąt macierzy ).
Twierdzenie O zbieżności metody Gaussa-Seidela
Jeśli macierz jest diagonalnie dominująca, to metoda Gaussa--Seidela jest zbieżna dla dowolnego wektora startowego .
Inny wariant tej metody dostalibyśmy, biorąc za górny trójkąt macierzy .
Metoda Gaussa--Seidela jest w wielu przypadkach rzeczywiście szybciej zbieżna od metody Jacobiego, np. tak jest w przypadku macierzy jednowymiarowego Laplasjanu. Wciąż jednak, dodajmy, dla zadań bardzo źle uwarunkowanych jej zbieżność jest zbyt wolna by ją stosować jako samodzielną metodę.
Uwaga
Obie metody, Jacobiego i (zwłaszcza) Gaussa--Seidela stosuje się także czasem w prostych algorytmach rozwiązywania układów równań nieliniowych: ich zaletą jest to, że głównym składnikiem iteracji jest rozwiązywanie skalarnego równania nieliniowego na każdym kroku metody.
Złożoność stacjonarnych metod iteracyjnych
Zastanówmy się teraz nad złożonością metod iteracyjnych. Ponieważ możemy jedynie znaleźć pewne przybliżenie rozwiązania dokładnego , przez złożoność metody będziemy rozumieli koszt kombinatoryczny obliczenia z zadaną dokładnością . Dla uproszczenia założymy, że medoda jest zbieżna liniowo z ilorazem . Zauważmy, że aby zredukować błąd początkowy do , wystarczy wykonać iteracji, gdzie spełnia
czyli
Liczba ta zależy więc w istotny sposób od błędu początkowego i (przede wszystkim) od współczynnika redukcji błędu , natomiast zależność od dokładności i wymiaru układu jest dużo mniej istotna (w zadaniach praktycznych -- takich jak jednowymiarowy laplasjan --- jednak często okazuje się, że... zależy od !).
Zakładając, że koszt jednej iteracji wynosi ( jest tym mniejszy, im mniejsza jest liczba niezerowych elementów macierzy ), złożoność metody jest proporcjonalna do
Stąd oczywisty wniosek (prawdziwy nie tylko dla metod stacjonarnych), że metody iteracyjne warto stosować zamiast metod bezpośrednich w przypadku, gdy
- wymiar układu jest "duży", oraz
- macierz układu jest "rozrzedzona", tzn. ma stosunkowo niewielką liczbę elementów niezerowych, np. proporcjonalną do .
Układy o tych własnościach powstają często przy numerycznym rozwiązywaniu równań różniczkowych cząstkowych.
Metody przestrzeni Kryłowa
Zupełnie inny pomysł na realizację metody iteracyjnej przedstawiają metody przestrzeni Kryłowa, gdzie kolejne przybliżenie dobiera się w taki sposób, by minimalizowało pewną miarę błędu na podprzestrzeni Kryłowa
gdzie jest residuum na początku iteracji. (Zwróć uwagę, że przestrzeń Kryłowa jest rozpięta przez kolejne wektory metody potęgowej] --- to nie przypadek!). W zależności od wyboru sposobu miary błędu, dostajemy inną metodę iteracyjną, takie jak CG, GMRES, PCR, BiCG, i inne. Tutaj omówimy pokrótce tylko najpopularniejszą: CG.
CG
Metoda gradientów sprzężonych, w skrócie CG (conjugate gradients), działa przy założeniu, że jest symetryczna i dodatnio określona.
Kolejne przybliżenie ma minimalizować błąd w normie energetycznej indukowanej przez ,
na przestrzeni afinicznej . Okazuje się (co nie jest oczywiste --- trzeba skorzystać z rozmaitych własności ortogonalności generowanych wektorów), że takie zadanie minimalizacji daje się bardzo efektywnie rozwiązać, skąd dostajemy bardzo zwarty algorytm:
Algorytm Metoda CG
r = b-A*x;
<math>\rho_0</math> = <math>||r||_2^2</math>; <math>\beta</math> = 0; k = 1;
while (!stop)
{
p = r + <math>\beta</math>*p;
w = A*p;
<math>\alpha</math> = <math>\rho_{k-1}</math>/<math>p^Tw</math>;
x = x + <math>\alpha</math>*p;
r = r - <math>\alpha</math>*w;
<math>\rho_k</math> = <math>||r||_2^2</math>;
<math>\beta</math> = <math>\frac{\rho_{k}}{\rho_{k-1}}</math>;
k++;
}
Jak widać, całą iterację da się wykonać przechowując w pamięci tylko kilka wektorów (a nie, jak możnaby się obawiać, całą przestrzeń ), a najdroższym jej elementem jest mnożenie macierzy przez wektor.
Twierdzenie O zbieżności CG jako metody bezpośredniej
Niech będzie symetryczna i dodatnio określona. Algorytm CG znajdzie dokładne rozwiązanie po co najwyżej iteracjach.
Powyższe twierdzenie, choć teoretycznie interesujące, ma małą wartość praktyczną z dwóch powodów:
- dla bardzo dużych , wykonanie iteracji może być wciąż zbyt kosztownym zadaniem;
- ponieważ w arytmetyce skończonej precyzji ortogonalność --- z której w bardzo istotny sposób korzysta się przy wyprowadzeniu algorytmu --- pogarsza się z iteracji na iterację i w konsekwencji, po wielu iteracjach, jakość przestaje się poprawiać.
Dlatego wygodniej potraktować CG jako metodę iteracyjną. Zachodzi bowiem
Twierdzenie Zbieżność CG jako metody iteracyjnej
Po iteracjach metody CG,
gdzie .
GMRES
Metoda GMRES (Generalized Minimum RESidual) nie wymaga ani symetrii, ani dodatniej określoności macierzy, jest więc bardziej uniwersalna, choć też bardziej kosztowna od CG. Jej szczegółowe omówienie, w tym --- oszacowania szybkości zbieżności --- wykracza niestety poza ramy niniejszego wykładu.
Ściskanie macierzy
Zbieżność wszystkich poznanych metod iteracyjnych zależy od własności spektralnych macierzy układu. Pojawiające się w zastosowaniach macierze często mają niekorzystne własności spektralne (np. bardzo duży wskaźnik uwarunkowania), przez co metody iteracyjne zbiegają na nich bardzo wolno.
Dlatego bardzo korzystne może być wstępne przetransformowanie układu
z macierzą o niekorzystnych własnościach, do układu
gdzie macierz ma znacznie korzystniejsze własności z punktu widzenia używanej metody iteracyjnej. W przypadku macierzy symetrycznych widzieliśmy, że kluczowe znaczenie dla zbieżności metody miał rozkład wartości własnych: jeśli wartości własne były bardzo rozrzucone po prostej, to uwarunkowanie było bardzo duże i w konsekwencji zbieżność powolna. Aby zbieżność była szybsza, kluczowe jest, by:
- wartości własne były upakowane w klastrach
- najlepiej wszystkie w (małym) otoczeniu wartości 1
Jeśli więc chcielibyśmy przekształcić macierz tak, by metoda iteracyjna dla zbiegała szybko, musimy w jakiś sposób "ścisnąć" spektrum macierzy w okolice jedności. Taką operację nazywamy ściskaniem (preconditioning), a macierz --- macierzą ściskającą.
Aby całość miała sens, macierz ściskająca powinna:
- być łatwa w konstrukcji,
- być tania w mnożeniu przez wektor (głównym elementem każdej metody iteracyjnej jest mnożenie macierzy przez wektor: ),
- macierz powinna mieć znacznie korzystniejsze własności z punktu widzenia używanej metody iteracyjnej.
Kilka ekstremalnych (lecz wątpliwej jakości) "propozycji" na macierz ściskającą to (łatwa w konstrukcji i tania w mnożeniu, ale niestety nic nie polepsza...) oraz (rewelacyjnie poprawia zbieżność metody iteracyjnej, dając zbieżność w jednej iteracji, ale bardzo droga w konstrukcji i mnożeniu). Widać więc, że należy poszukiwać czegoś pośredniego, co niskim kosztem przybliża działanie macierzy odwrotnej.
Dlatego jednym z powszechniej stosowanych (aczkolwiek wciąż nie najbardziej skutecznych) sposobów ściskania są te oparte na zastosowaniu jednego kroku klasycznej metody iteracyjnej.

Inne sposoby ściśnięcia macierzy wykorzystują np. techniki tzw. niepełnego rozkładu macierzy, albo --- w specyficznych przypadkach --- tzw. metody wielosiatkowe.
Okazuje się, że zarówno CG jak i GMRES da się zaimplementować tak, by w jednej iteracji było konieczne tylko jedno mnożenie przez macierz ściskającą.
Literatura
W celu dogłębnego zapoznania się z omawianym na wykładzie materiałem, przeczytaj rozdział 4.6 i 4.7 w
- D. Kincaid, W. Cheney Analiza numeryczna, Wydawnictwa Naukowo-Techniczne, Warszawa 2006, ISBN 83-204-3078-X.
Tym razem wymienione rozdziały nie wystarczą do dogłębnego zrozumienia omawianych treści. Warto więc sięgnąć po jeden z podręczników
- C. T. Kelley, Iterative Solution of Systems of Linear and Nonlinear Equations, SIAM, 1995,
- Y. Saad, Iterative Methods for Sparse Linear Systems, PWS, 1996.