Przykre testy: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Przykry (dyskusja | edycje)
mNie podano opisu zmian
Przykry (dyskusja | edycje)
mNie podano opisu zmian
Linia 6: Linia 6:
-->
-->
   
   
=Równania nieliniowe=
=Wielkie układy równań liniowych=
{{powrot |Metody numeryczne |do strony g��wnej przedmiotu Metody numeryczne}}


W wielu zadaniach, m.in. matematyki stosowanej, spotykamy się z problemem
Wraz z coraz większymi modelami pojawiającymi się w praktyce obliczeniowej,
rozwiązania skalarnego równania nieliniowego postaci <math>\displaystyle f(x) = 0</math>. Oto kilka przykładów:
coraz częściej zachodzi potrzeba rozwiązywania zadań algebry liniowej, w której
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
wymiaru <math>\displaystyle N</math> ma tylko <math>\displaystyle O(N)</math> 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ą <math>\displaystyle N^2</math>
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. <strong>równania różniczkowe cząstkowe</strong> (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.


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<span  style="font-variant:small-caps;">Przykład</span>  
<span  style="font-variant:small-caps;">Przykład: Macierz z kolekcji Boeinga</span>  
<div class="solution" style="margin-left,margin-right:3em;">
<div class="solution" style="margin-left,margin-right:3em;">


Równanie Keplera
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 [http://www.cise.ufl.edu/research/sparse/matrices/Boeing  kolekcji Tima
 
Davisa]. Jest to mała macierz, wymiaru 8032 (w kolekcji spotkasz równania z milionem i więcej niewiadomych).
<center><math>\displaystyle f(x) \equiv x - \epsilon \sin(x) - M = 0
</math></center>


jest bardzo ważne w astronomii, jego rozwiązanie pozwala wyznaczyć przyszłe położenie planety. Parametr <math>\displaystyle \epsilon</math> odpowiada ekscentryczności orbity i przyjmuje wartości z przedziału <math>\displaystyle [0,1]</math>. Poza paru prostymi przypadkami, w ogólności równanie Keplera nie daje się rozwiązać w terminach funkcji elementarnych.  
[[Image:MNsparseA.png|thumb|550px|center|Struktura niezerowych elementów macierzy bcsstk38.]]


[[grafika:Kepler.jpg|thumb|right||Johann Kepler<br> [[Biografia Kepler|Zobacz biografię]]]]
Jej <strong>współczynnik wypełnienia</strong> (to znaczy, stosunek liczby niezerowych do wszystkich elementów macierzy) wynosi jedynie <math>\displaystyle 0.006</math>, a więc macierz jest bardzo rozrzedzona: w każdym wierszu są średnio tylko 44 niezerowe elementy.
</div></div>


</div></div>
<!--


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<span  style="font-variant:small-caps;">Przykład</span>  
<span  style="font-variant:small-caps;">Przykład: Macierz MBEACXC</span>  
<div class="solution" style="margin-left,margin-right:3em;">
<div class="solution" style="margin-left,margin-right:3em;">


Znajdowanie miejsc zerowych wielomianu
Dane pochodzą z serwisu
[http://math.nist.gov/MatrixMarket  MatrixMarket]. Jest to niezbyt duża macierz, wymiaru <math>\displaystyle 496 \times 496</math>, niesymetryczna, o elementach rzeczywistych. Źródłem tej macierzy jest pewien model ekonomiczny.


<center><math>\displaystyle f(x) \equiv a_nx^n + \ldots + a_1x + a_0 = 0.
[[Image:MNmbeacxc|thumb|550px|center|Struktura niezerowych elementów macierzy MBEACXC]]
</math></center>


Bardzo wiele modeli matematycznych wymaga rozwiązania równania z wielomianową nieliniowością. Piękne [[MN14|kwadratury]] (Gaussa) opierają się na węzłach będących zerami pewnego wielomianu. Wielomiany są bardzo szczególnymi funkcjami i dla nich istnieje szereg wyspecjalizowanych metod znajdowania ich pierwiastków, m.in. metoda Laguerre'a, metoda Bairstow'a (o nich tu nie będziemy mówić), a także zaskakujące metody sprowadzające zadanie poszukiwania miejsc zerowych wielomianu do zupełnie innego zadania matematycznego  --- o nich jednak będzie mowa dopiero w wykładzie dotyczącym [[MN13|znajdowania wartości własnych macierzy]].
Tylko pozornie macierz ta wydaje się dość gęsta, w rzeczywistości jej współczynnik wypełnienia wynosi około 20 procent.  
</div></div>
</div></div>


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
-->
<span style="font-variant:small-caps;">Przykład</span>
   
<div class="solution" style="margin-left,margin-right:3em;">
==Reprezentacja macierzy rzadkich==


Obliczanie pierwiastka kwadratowego z zadanej liczby <math>\displaystyle a</math>, czyli sposób na implementację funkcji "<code>sqrt()</code>". Można to zadanie wyrazić, jako rozwiązywanie równania
Zacznijmy od sposobu przechowywania macierzy rozrzedzonych. Naturalnie, nie ma
sensu przechowywać wszystkich <strong>zerowych</strong> 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!).  


<center><math>\displaystyle f(x) \equiv x^2 - a = 0.
====Format współrzędnych====
</math></center>


Szybkie algorytmy wyznaczania pierwiastka kwadratowego były znane już starożytnym. W wykładzie zrozumiemy, dlaczego <strong>metoda Herona</strong>,  
Do zapamiętania macierzy <math>\displaystyle A</math> wymiaru <math>\displaystyle N\times M</math> o <math>\displaystyle 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>,
wszystkie o długości <math>\displaystyle NNZ</math>, przy czym


<center><math>\displaystyle  
<center><math>\displaystyle  
x_{k+1} = \frac{1}{2}\left(x_k + \frac{a}{x_k}\right)
A_{I[k], J[k]} = V[k], \qquad\forall k = 0,\ldots, NNZ-1.
</math></center>
</math></center>
   
   
daje bardzo dobre przybliżenie <math>\displaystyle \sqrt{a}</math> już po kilku iteracjach.
[[Image:MNaij-matrix-format.png|thumb|550px|center|Format AIJ]]
</div></div>
 
W tym formacie wprowadzane są macierze rzadkie do Octave'a i MATLABa:
 
<div style="margin: 1em; padding:1em; color: #006; background-color:#fcfcfc;"><pre>A = sparse(I,J,V,N,N);
</pre></div>  
Jednak wewnętrznie przechowywane są w innym formacie, o którym [[#Format spakowanych kolumn (wierszy)|poniżej]].


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
Linia 60: Linia 85:
<div class="solution" style="margin-left,margin-right:3em;">
<div class="solution" style="margin-left,margin-right:3em;">


Implementacja wyznaczania odwrotności liczby <math>\displaystyle a</math> (<strong>bez</strong> dzielenia!) jest możliwa, gdy odpowiednią metodą będziemy poszukiwać rozwiązania równania
Pokażemy jak w Octave rozwiązywać układ równań z macierzą rozrzedzoną.


<center><math>\displaystyle f(x) \equiv \frac{1}{x} - a = 0.
<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];
</math></center>
octave:11> J = [1, 3, 2, 2, 3, 4, 4];
octave:12> V = [1, 2, 3, 4, 5, 6, 7];
octave:13> N = 4;
octave:14> A = sparse(I,J,V,N,N)
A =
 
Compressed Column Sparse (rows = 4, cols = 4, nnz = 7)
 
  (1, 1) ->  1
  (1, 2) -> 3
  (2, 2) ->  4
  (1, 3) ->  2
  (3, 3) ->  5
  (1, 4) ->  6
  (4, 4) ->  7
</nowiki></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.


To zadanie jest ważne praktycznie, np. tak można poprawić precyzję
[http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/21928.pdf  funkcji wektorowych stosowanych w niektórych procesorach AMD]. Okazuje się, że instrukcja procesora służąca do równoległego obliczania odwrotności sekwencji liczb umieszczonych w 128-bitowym rejestrze wektorowym daje wynik z małą precyzją (oczywiście po to, by wykonywała się szybciej!). Jeśli taka dokładność wyniku nie odpowiada nam, możemy ją --- zgodnie z manualem procesora --- poprawić, rozwiązując właśnie takie równanie jak powyżej, metodą korzystającą wyłącznie z (wektorowych) operacji mnożenia i dodawania.
</div></div>
</div></div>


==Bisekcja==
====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: <code>AV</code> jest wektorem typu
<code>double</code> o długości <math>\displaystyle NNZ</math>, zawierającym <strong>kolejne</strong> niezerowe elementy
macierzy <math>\displaystyle A</math> wpisywane <strong>kolumnami</strong>, <code>AI</code> jest wektorem typu <code>int</code>
o długości <math>\displaystyle NNZ</math>, zawierającym numery wierszy macierzy <math>\displaystyle A</math> odpowiadających
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
długości <math>\displaystyle M</math>, zawierający na <math>\displaystyle j</math>-tym miejscu indeks pozycji w <code>AV</code>, od
którego rozpoczynają się w <code>AV</code> elementy <math>\displaystyle j</math>-tej kolumny macierzy <math>\displaystyle A</math>.


<strong>Metoda bisekcji</strong>, czyli <strong>połowienia</strong>, często stosowana w innych
[[Image:MNcsc-matrix-format.png|thumb|550px|center|Format CSC]]
działach informatyki, jest dość
naturalną metodą obliczania zer skalarnych funkcji
ciągłych określonych na danym przedziale <math>\displaystyle [a,b]</math>
i zmieniających znak. Dokładniej, rozpatrzmy klasę
funkcji


Mamy więc zależność, przy założeniu, że <math>\displaystyle AP[0]=0</math>,
<center><math>\displaystyle  
<center><math>\displaystyle  
  F\,=\,\{\,f\in C([a,b])\,:\;f(a)\cdot f(b) < 0\,\},
A_{AI[AP[j]+k],j+1} = AV[AP[j]+k], \qquad j = 0,\ldots,M-1, \, k =
0,\ldots,AP[j+1]-1.
</math></center>
</math></center>


to znaczy <math>\displaystyle f \in F</math> przyjmują w krańcach przedziału wartości przeciwnego znaku.
Taki (z drobnymi modyfikacjami) format macierzy wykorzystują np. pakiety ARPACK
Oczywiście, każda funkcja <math>\displaystyle f\in F</math> ma, na mocy twierdzenia Darboux, co najmniej jedno zero w <math>\displaystyle [a,b]</math>. Startując z przedziału <math>\displaystyle [a,b]</math>, w kolejnych krokach metody bisekcji obliczamy informację o wartości <math>\displaystyle f</math> w środku przedziału, co pozwala nam w następnym kroku zmniejszyć o połowę przedział, w którym na pewno znajduje się zero funkcji.  
i UMFPACK (a także, wewnętrznie, Octave i MATLAB).
 
====Format diagonalny====


Bisekcję realizuje następujący ciąg
Znacznie mniej uniwersalny niż poprzednie i dlatego rzadziej spotykany. Kolejne
poleceń, po wykonaniu którego <math>\displaystyle x</math> jest przybliżeniem
diagonale macierzy przechowujemy w kolejnych wierszach macierzy <math>\displaystyle P\times N</math>,
zera funkcji <math>\displaystyle f</math> z zadaną dokładnością <math>\displaystyle \epsilon</math>.  
gdzie <math>\displaystyle P</math> jest liczbą niezerowych diagonal w <math>\displaystyle A\in R^{N\times N}</math>.
<div style="margin: 1em; padding:1em; color: #000; background-color:#fcfcfc;"><pre>[Metoda bisekcji]
 
lewy = a; prawy = b;
Szczególnie wygodny do reprezentacji macierzy taśmowych. Wykorzystywany m.in.
flewy = f(lewy); fprawy = f(prawy);
przez funkcję LAPACKa <code style="color: #903">DGBSV</code> służącą rozwiązywaniu równań z macierzami
x = (a+b)/2; /* przybliżenie rozwiązania */
taśmowymi.
e = (b-a)/2; /* przedział lokalizujący rozwiązanie dokładne */
 
while (e > <math>\displaystyle \epsilon</math>)
====Uwagi praktyczne====
{
 
fx = f(x);  /* reszta */
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.
if ( signbit(fx) != signbit(flewy) )
 
{
Jeśli już ''poważnie'' myśleć o przyspieszeniu mnożenia macierzy przez wektor (np. gdy chcemy stosować [[#Stacjonarne metody iteracyjne|iteracyjną metodę rozwiązywania układu równań]] z tą macierzą), warto rozważyć [http://bebop.cs.berkeley.edu/pubs/vuduc2003-dissertation.pdf inne formaty] --- łączące w sobie podział macierzy na bloki (tak, jak w algorytmach BLAS) i przechowywanie (w zasadzie) tylko niezerowych elementów macierzy.
prawy = x;
 
fprawy = fx;
==Macierze specjalne==
}
else
{
lewy = x;
flewy = fx;
}
x = (lewy+prawy)/2; e = e/2;
}
</pre></div>
   
(funkcja języka C <code>signbit</code> bada znak liczby rzeczywistej).
Z konstrukcji metody łatwo wynika, że po wykonaniu
<math>\displaystyle k</math> obrotów pętli <code>while</code> (czyli po obliczeniu <math>\displaystyle k+2</math> wartości funkcji)
otrzymujemy <math>\displaystyle x</math>, które odległe jest od pewnego rozwiązania <math>\displaystyle x^*</math> o co najwyżej


Zajmiemy się teraz zadaniem rozwiązywania układu równań liniowych
<center><math>\displaystyle  
<center><math>\displaystyle  
  |x-x^*|\,\le\,\Big(\frac 12\Big)^k
Ax = b,
                  \Big(\frac{b-a}{2}\Big).
</math></center>
</math></center>


Metoda bisekcji jest więc zbieżna <strong>liniowo</strong> z
ale w sytuacji, gdy macierz <math>\displaystyle 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.
ilorazem <math>\displaystyle 1/2</math>. Choć ta zbieżność nie jest
imponująca, bisekcja ma kilka istotnych zalet. Oprócz
jej prostoty, należy podkreślić fakt, że bisekcja jest
w pewnym sensie uniwersalna. Jeśli tylko dysponujemy dwoma punktami <math>\displaystyle a</math> i <math>\displaystyle b</math>
takimi, że <math>\displaystyle f</math> przyjmuje w nich wartości przeciwnych znaków, to metoda bisekcji
z pewnością znajdzie miejsce zerowe funkcji, choćby początkowa długość
przedziału <math>\displaystyle |b-a|</math> była bardzo duża: zbieżność metody bisekcji jest <strong>globalna</strong>. Co ważniejsze, dla zbieżności metody bisekcji
wystarcza jedynie <strong>ciągłość</strong> funkcji. Poza tym
możemy łatwo kontrolować <strong>błąd bezwzględny aproksymacji miejsca zerowego</strong>. Konsekwencją
powyższego oszacowania błędu jest bowiem następujący wniosek.  


{{wniosek|||
Należy pamiętać, że z reguły najlepsze wyniki uzyskuje się, gdy konkretny
Dla znalezienia zera <math>\displaystyle x^*</math> z dokładnością
algorytm dobierze się do konkretnej macierzy. W zastosowaniach pojawiają się
<math>\displaystyle \epsilon>0</math>, wystarczy obliczyć w metodzie bisekcji
m.in. macierze rzadkie o bardzo szczególnej strukturze, dla nich warto stosować
wyspecjalizowane algorytmy.


<center><math>\displaystyle k\,=\,k(\epsilon)\,=\,
====Macierze  taśmowe====
    \Big\lceil{\log_2\frac{(b-a)}{\epsilon}}\Big\rceil - 1
 
</math></center>
Macierz <math>\displaystyle A</math> taka, że dla <math>\displaystyle |i-j| \geq d</math>, <math>\displaystyle a_{ij} = 0</math>, nazywamy macierzą taśmową
z rozstępem <math>\displaystyle d</math>, o szerokości pasma <math>\displaystyle 2d+1</math>.
 
Ł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 <math>\displaystyle \max\{2d,N\}</math> --- tak
więc, dla niezbyt dużych <math>\displaystyle d</math> wciąż wynikowa macierz jest taśmowa. 


wartości funkcji.  
W szczególności, gdy macierz jest taśmowa z pasmem o rozstępie <math>\displaystyle d</math> i jednocześnie
}}
diagonalnie dominująca, wtedy rozkład LU takiej macierzy da się wykonać w
miejscu kosztem <math>\displaystyle O(d\,N)</math>, czyli liniowym.


==Iteracja prosta Banacha==
W [http://www.netlib.org/lapack  LAPACKu] zaimplementowano szybki ''solver'' równań z macierzami taśmowymi,
<code style="color: #006">DGBSV</code>, ale wymagający specjalnego sposobu
przechowywania macierzy, wykorzystującego format diagonalny.


Zupełnie inne, i jak się okaże --- przy odrobinie sprytu bardzo skuteczne ---
====Macierze trójdiagonalne====
podejście do wyznaczania miejsca zerowego jest oparte na <strong>metodzie Banacha</strong>. Dla większej ogólności, będziemy zakładać teraz, że <math>\displaystyle f: D\rightarrow R^N</math> i <math>\displaystyle D</math> jest otwartym, niepustym podzbiorem <math>\displaystyle R^N</math>.


Najpierw nasze równanie nieliniowe
Szczególnym przypadkiem macierzy taśmowych są macierze trójdiagonalne, tzn. taśmowe o
rozstępie <math>\displaystyle d=1</math>:


<center><math>\displaystyle  
<center><math>\displaystyle  
f(x) = 0
A =  
\begin{pmatrix}
a_1 & c_1 &  &  & \\
b_2 & a_2 & c_2      &  & \\
  &  b_3 & a_3  & \ddots &  \\
  & & \ddots & \ddots  & c_{N-1}\\
  &  &      & b_N  & a_N
\end{pmatrix}
</math></center>
</math></center>


przekształcamy (dobierając odpowiednią funkcję <math>\displaystyle \phi</math>) do równania równoważnego
Zadanie rozwiązywania równań z taką macierzą
(tzn. mającego te same rozwiązania)
 
<center><math>\displaystyle  
<center><math>\displaystyle  
  x\,=\,\phi( x).
Ax = e
</math></center>
</math></center>


Taki <math>\displaystyle x</math>, dla którego zachodzi powyższa równość, nazywamy <strong>punktem stałym</strong> odwzorowania <math>\displaystyle \phi</math>.
jest bardzo  często spotykane, więc warto przytoczyć algorytm w całej okazałości --- popularnie zwany <strong>algorytmem przeganiania</strong> (niektóre źródła nazywają go ''algorytmem Thomasa'').
 
Zacznijmy jednak od stwierdzenia, kiedy macierz trójdiagonalna  nie wymaga wyboru elementu głównego:


Następnie, startując z pewnego przybliżenia
{{stwierdzenie|||
początkowego <math>\displaystyle x_0 \in D</math>, konstruujemy ciąg kolejnych
Jeśli macierz <math>\displaystyle A</math> ma <strong>słabo dominującą diagonalę</strong>, tzn.
przybliżeń <math>\displaystyle x_k</math> według wzoru


<center><math>\displaystyle x_k\,=\,\phi( x_{k-1}),\qquad k\ge 1.
<center><math>\displaystyle |a_i|\,\ge\,|b_i|\,+\,|c_i|,\qquad 1\le i\le N,
</math></center>
</math></center>


[[grafika:Banach.jpg|thumb|right||Stefan Banach<br> [[Biografia Banach|Zobacz biografię]]]]
(<math>\displaystyle b_1=0=c_N</math>) i przynajmniej dla jednego indeksu "<math>\displaystyle i</math>" mamy powyżej
ostrą nierówność "<math>\displaystyle ></math>", to algorytm przeganiania jest wykonalny bez
przestawień wierszy. Ponadto wymaga on <math>\displaystyle 7N</math> operacji arytmetycznych,
a więc jest prawie optymalny.
}}


{{twierdzenie|Banacha, o kontrakcji|Banacha, o kontrakcji|
{{algorytm|Metoda przeganiania|Metoda przeganiania|
<pre><math>\displaystyle d_1</math> = <math>\displaystyle a_1</math>;
<math>\displaystyle f_1</math> = <math>\displaystyle e_1</math>;
for (i = 2; i <= N; i++)
{
<math>\displaystyle l</math> = <math>\displaystyle b_i</math>/<math>\displaystyle a_{i-1}</math>;
<math>\displaystyle d_i</math> = <math>\displaystyle a_i</math> - <math>\displaystyle l</math> * <math>\displaystyle c_{i-1}</math>;
<math>\displaystyle f_i</math> = <math>\displaystyle e_i</math> - <math>\displaystyle l</math> * <math>\displaystyle f_{i-1}</math>;
}
<math>\displaystyle x_1</math> = <math>\displaystyle f_N</math>;
for (i = N-1; i >= 1; i--)
<math>\displaystyle x_i</math> = <math>\displaystyle f_i</math> - <math>\displaystyle c_i</math> * <math>\displaystyle x_{i+1}</math>;
</pre>}}


Niech <math>\displaystyle D_0</math> będzie domkniętym
==Metody bezpośrednie==
podzbiorem dziedziny <math>\displaystyle D</math>,


<center><math>\displaystyle \overline D_0\,=\,D_0\subset D,
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
</math></center>
<span  style="font-variant:small-caps;">Przykład: Strzałka Wilkinsona</span>  
<div class="solution" style="margin-left,margin-right:3em;">


w którym <math>\displaystyle \phi</math> jest odwzorowaniem zwężającym.
Rozważmy układ równań z macierzą diagonalnie dominującą postaci
To znaczy, <math>\displaystyle \phi(D_0)\subset D_0</math>, oraz istnieje stała
<math>\displaystyle 0\le L<1</math> taka, że


<center><math>\displaystyle \|\phi( x)-\phi( y)\|\,\le\,L\,\| x- y\|,
<center><math>\displaystyle A = \begin{pmatrix}
     \qquad\forall x, y\in D_0. 
* & * & * & \cdots & * \\
* & * &        &  & \\
* &  & *      &  &  \\
\vdots & & & \ddots  & \\
* &  &     &  & *
\end{pmatrix}
</math></center>
</math></center>


Wtedy równanie
gdzie <math>\displaystyle *</math> oznacza jakiś niezerowy element.
Ł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.
 
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 <math>\displaystyle P</math>):


<center><math>\displaystyle  
<center><math>\displaystyle \widetilde{A} = PAP^T = \begin{pmatrix}
  x\,=\,\phi( x).
* &        &  & & *\\
  &  \ddots  & & & \vdots\\
  &      & * &  & * \\
    &        &  &  * & * \\
* & \cdots & * & * & *
\end{pmatrix}
</math></center>
</math></center>


ma dokładnie jedno
Wtedy okazuje się, że rozkład naszej macierzy nie powoduje już ''wypełnienia'' czynników rozkładu!
rozwiązanie <math>\displaystyle  x^*</math>, oraz
</div></div>
 
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 <strong>niezerowych</strong> 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).


<center><math>\displaystyle x^*\,=\,\lim_{k\to\infty} x_k,
W ogólnym przypadku rozwiązanie takiego zadania jest trudne i większość
</math></center>
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ę.


dla dowolnego przybliżenia początkowego
Stosuje się kilka strategii wyznaczania korzystnych permutacji
<math>\displaystyle x_0\in D_0</math>.  
(''reorderingu''), z których warto wymienić
}}
* przybliżone algorytmy minimalnego stopnia (''approximate minimum degree, AMD''), np. [http://www.cise.ufl.edu/research/sparse/amd AMD];
* techniki podziału grafów na (prawie) rozłączne składowe ''nested dissection, ND'', np. [http://glaros.dtc.umn.edu/gkhome/views/metis  METIS].
Używają ich biblioteki takie jak [http://www.cise.ufl.edu/research/sparse/umfpack  UMFPACK], czy [http://www.cse.clrc.ac.uk/nag/hsl  HSL].


{{dowod|||
W Octave mamy do dyspozycji także kilka procedur generujących takie permutacje, w tym: <code style="color: #006">colamd</code> (AMD dla macierzy niesymetrycznych) oraz <code style="color: #006">symamd</code> (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.
Wobec


<center><math>\displaystyle \aligned \| x_k- x_{k-1}\| &= \|\phi( x_{k-1})-\phi( x_{k-2})\| \,\le\,L\,\| x_{k-1}- x_{k-2}\| \\
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
&\le &\cdots\;\le\;L^{k-1}\| x_1- x_0\|,
<span  style="font-variant:small-caps;">Przykład</span>  
\endaligned</math></center>
<div class="solution" style="margin-left,margin-right:3em;">


dla <math>\displaystyle k\ge s</math> mamy
Najprostszy sposób na wykorzystanie metody bezpośredniego rozwiązywania układu z macierzą rzadką to zastosowanie znanego nam operatora do macierzy typu rozrzedzonego:


<center><math>\displaystyle \aligned \| x_k- x_s\| &&\le \sum_{j=s+1}^k\| x_j- x_{j-1}\| \,\le\,\sum_{j=s+1}^k L^{j-1}\| x_1- x_0\| \\
<div style="margin: 1em; padding:1em; color: #006; background-color:#fcfcfc;"><pre>A = sparse(...);
&&= L^s(1+L+\cdots+L^{k-s-1})\| x_1- x_0\| \,\le\,\frac{L^s}{1-L}\| x_1- x_0\|.
x = A \ b;
\endaligned</math></center>
</pre></div>
   
Octave domyślnie przyłoży do <math>\displaystyle 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: jeśli jest, to korzysta się z LAPACKa.


Ciąg <math>\displaystyle \{ x_k\}_k</math> jest więc ciągiem Cauchy'ego.
(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++?)
Stąd istnieje granica
<math>\displaystyle \alpha=\lim_{k\to\infty} x_k</math>, która należy do
<math>\displaystyle D_0</math>, wobec domkniętości tego zbioru. Ponieważ
lipschitzowskość <math>\displaystyle \phi</math> implikuje jej ciągłość,  
mamy też 


<center><math>\displaystyle \phi(\alpha)\,=\,\phi\Big(\lim_{k\to\infty} x_k\Big)
</div></div>
  \,=\,\lim_{k\to\infty}\phi( x_k)
  \,=\,\lim_{k\to\infty} x_k\,=\,\alpha,
</math></center>


tzn. <math>\displaystyle \alpha</math> jest punktem stałym odwzorowania <math>\displaystyle \phi</math>.
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
Dla jednoznaczności zauważmy, że jeśliby istniał
<span  style="font-variant:small-caps;">Przykład: Wypełnienie pewnej macierzy w zależności od użytego algorytmu</span>  
drugi, różny od <math>\displaystyle \alpha</math>, punkt stały <math>\displaystyle \beta</math>,
<div class="solution" style="margin-left,margin-right:3em;">
to mielibyśmy


<center><math>\displaystyle \|\alpha-\beta\|\,=\,
Rozważmy [[#Macierz z kolekcji Boeinga|ponownie]] macierz pochodzącą z kolekcji [http://www.cise.ufl.edu/research/sparse/matrices/Boeing  Tima Davisa]. Jest to macierz symetryczna, dodatnio określona, wymiaru 8032, o 355460 elementach niezerowych i, w konsekwencji, wypełnieniu około 0.6 procent.  
  \|\phi(\alpha)-\phi(\beta)\|
  \,\le\,L\,\|\alpha-\beta\|.  
</math></center>


Stąd <math>\displaystyle 1<L</math>, co jest sprzeczne z założeniem, że
[[Image:MNsparseA.png|thumb|550px|center|Struktura niezerowych elementów macierzy.]]
<math>\displaystyle \phi</math> jest zwężająca. }}


Z powyższych rozważań otrzymujemy natychmiastowy
Zobaczymy, jak w zależności od użytego algorytmu permutacji kolumn i
wniosek dotyczący zbieżności iteracji prostych.  
wierszy poradzi sobie algorytm rozkładu Cholesky'ego.


{{wniosek|||
[[Image:MNsparsechol.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>\displaystyle L</math> wykonanego
Przy założeniach [[#Banacha, o kontrakcji|twierdzenia Banacha]],
standardowym algorytmem. Czas rozkładu: 0.892013]]
metoda iteracji prostych jest zbieżna co
najmniej liniowo z ilorazem <math>\displaystyle L</math>, tzn.


<center><math>\displaystyle \| x_k- x^*\|\,\le\,L^k\,\| x_0- x^*\|.
[[Image:MNsparsecholcolamd.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>\displaystyle L</math> z reorderingiem
</math></center>
COLAMD. Czas rozkładu: 0.813038]]


}}
[[Image:MNsparsecholsymamd.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>\displaystyle L</math> z reorderingiem
SYMAMD. Czas rozkładu: 0.487683s. Prawie dwa razy
szybciej niż bez reorderingu, chociaż i tak wskutek wzrostu wypełnienia macierzy
w dolnym trójkącie mamy aż 2 procent niezerowych elementów.]]


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
[[Image:MNsparsecholsymrcm.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>\displaystyle L</math> z odwrotnym reorderingiem
<span  style="font-variant:small-caps;">Przykład</span>  
Cuthill-McKee. Czas rozkładu: 0.845928]]
<div class="solution" style="margin-left,margin-right:3em;">


Dla ilustracji, rozpatrzmy
[[Image:MNsparsecholcolperm.png|thumb|550px|center|Czynnik rozkładu Cholesky'ego <math>\displaystyle L</math> z jeszcze
równanie Keplera, gdy <math>\displaystyle \epsilon < 1</math>:  
innym (bardzo tanim, ale jak widać czasem zupełnie złym) reorderingiem. Czas rozkładu: 5.947936]]


<center><math>\displaystyle
Na zakończenie popatrzmy, jak ważne jest spostrzeżenie symetrii macierzy:
  x\,=\,M+\epsilon\sin(x), \qquad \mbox{dla} \qquad x\in R.
</math></center>


[[Image:MNrownaniekeplera.png|thumb|550px|center|Graficzna ilustracja równania Keplera dla <math>\displaystyle M=1</math> i <math>\displaystyle \epsilon = \frac{1}{4}</math>.]]
[[Image:MNsparseLlu.png|thumb|550px|center|Rozkład LU, czynnik <math>\displaystyle L</math> (bez reorderingu). Czas rozkładu LU: 1.696018s. Nieakceptowalny, podobnie
jak drastyczne wypełnienie macierzy.]]


W tym przypadku <math>\displaystyle \phi(x)=M+\epsilon\,\sin(x)</math>. Zauważmy, że w
[[Image:MNsparseUlu.png|thumb|550px|center|Rozkład LU, czynnik <math>\displaystyle U</math> (bez reorderingu)]]
funkcja <math>\displaystyle \phi</math> jest zwężająca ze stałą


<center><math>\displaystyle L \leq \max_{x} |\phi'(x)| \leq \epsilon < 1.
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ć.
</math></center>


Ponieważ obrazem prostej przy przekształceniu <math>\displaystyle \phi</math> jest odcinek <math>\displaystyle D = [M-\epsilon, M+\epsilon]</math>, to znaczy, że <math>\displaystyle \phi</math> --- ograniczona do <math>\displaystyle D</math> --- spełnia założenia [[#Banacha, o kontrakcji|twierdzenia Banacha o kontrakcji]].
Stąd istnieje dokładnie jedno rozwiązanie naszego równania
w przedziale <math>\displaystyle D</math>. Rozwiązanie to może
być aproksymowane z dowolnie małym błędem przy pomocy
iteracji prostych, startując z dowolnego przybliżenia
początkowego <math>\displaystyle x_0\in D</math>. Jednak, gdy <math>\displaystyle \epsilon \approx 1</math>, zbieżność może być bardzo powolna... (Wkrótce przekonasz się, że są szybsze metody).
</div></div>
</div></div>


Zaletą iteracji prostych jest fakt, że zbieżność
==Stacjonarne metody iteracyjne==
nie zależy od wymiaru <math>\displaystyle n</math> zadania, ale tylko od stałej
 
Lipschitza <math>\displaystyle L</math> (jednak w praktyce czasem sama stała Lipschitza może zależeć od
Gdy macierz jest rozrzedzona, mnożenie takiej macierzy przez wektor jest bardzo tanie (koszt jest proporcjonalny do liczby niezerowych elementów macierzy).
wymiaru zadania...). Metoda Banacha ma szczególne zastosowanie w
Dlatego, jeśli możemy zadowolić się <strong>rozwiązaniem przybliżonym</strong> układu, a w zamian osiągnąć je tanim kosztem, warto rozważyć metody iteracyjne.
przypadku, gdy funkcja <math>\displaystyle \phi</math> jest zwężająca na całym
zbiorze <math>\displaystyle D</math>, tzn. <math>\displaystyle D_0=D</math>. Jeśli ponadto <math>\displaystyle D</math> ma
skończoną średnicę, <math>\displaystyle  \mbox{diam} (D) < +\infty</math>, to dla
osiągnięcia <math>\displaystyle \epsilon</math>-aproksymacji zera funkcji <math>\displaystyle f</math>
wystarczy wykonać


<center><math>\displaystyle k\,=\,k(\epsilon)\,=\,\Big\lceil\frac
Najprostsze metody iteracyjne (najprostsze w analizie i implementacji, ale ---
  {\log(\| x_0- x^*\|/\epsilon)}{\log(1/L)}\Big\rceil
jak można się domyślić --- w praktyce najmniej efektywne) polegają na rozkładzie
  \,=\,\Big\lceil\frac
macierzy na część "łatwo odwracalną", <math>\displaystyle M</math>, i "resztę", <math>\displaystyle Z</math>. Dokładniej,
  {\log( \mbox{diam} (D)/\epsilon)}{\log(1/L)}\Big\rceil
jeśli <math>\displaystyle M</math> jest nieosobliwa, to równanie <math>\displaystyle Ax = b</math> można zapisać jako
zadanie punktu stałego
 
<center><math>\displaystyle Mx = Nx + b,
</math></center>
</math></center>


iteracji, niezależnie od <math>\displaystyle x_0</math>. Metody zbieżne dla
gdzie <math>\displaystyle Z=M-A</math>. Inaczej:
dowolnego przybliżenia początkowego nazywamy
<strong>zbieżnymi globalnie</strong>. Obie przedstawione dotychczas metody: bisekcji i
Banacha, przy rozsądnych
założeniach, są zbieżne globalnie.


Okazuje się, że metoda iteracji prostej może być --- w bardzo szczególnych
<center><math>\displaystyle x = M^{-1}(Zx + b),
przypadkach --- zbieżna szybciej niż liniowo. Z taką sytuacją będziemy mieli do czynienia, gdy rozpatrzymy metodę Newtona.
</math></center>


==Metoda Newtona==
i zastosować doń [[MN02#Iteracja prosta Banacha|metodę iteracji prostej Banacha]]:


Zarówno metoda Banacha, jak i bisekcja, są zbieżnie liniowo, co w praktyce może
<center><math>\displaystyle x_{k+1} = M^{-1}(Zx_k + b).
okazać się zbieżnością dość powolną (np. dla metody zbieżnej liniowo z ilorazem
</math></center>
<math>\displaystyle 1/2</math> dopiero po piątej iteracji dostajemy kolejną
dokładną cyfrę wyniku). Wykorzystując więcej informacji o funkcji <math>\displaystyle f</math>, której
miejsca zerowego poszukujemy, możemy istotnie przyspieszyć zbieżność metody.
Ceną, jaką przyjdzie nam zapłacić, będzie utrata globalnej zbieżności.


W dalszych rozważaniach będziemy zakładać dla
Takie metody nazywamy stacjonarnymi metodami iteracyjnymi. Aby przeanalizować zbieżność takiej metody, warto rozpatrzyć przypadek ogólniejszy
uproszczenia, że dziedzina <math>\displaystyle D=R</math>.


Idea <strong>metody Newtona</strong> opiera się na popularnym wśród inżynierów pomyśle <strong>linearyzacji</strong>: zamiast szukać miejsca zerowego skomplikowanej <math>\displaystyle f</math>, przybliżmy ją
<center><math>\displaystyle
linią prostą, a dla niej już umiemy znaleźć miejsce zerowe!
  x_k\,=\,B x_{k-1}\,+\, c,
</math></center>


[[grafika:Newton.jpg|thumb|right||Isaac Newton<br> Przypisywanie metody
dla pewnej macierzy <math>\displaystyle B</math>  oraz wektora <math>\displaystyle c</math>. (Dla stacjonarnej metody iteracyjnej, <math>\displaystyle B=M^{-1}Z</math> oraz <math>\displaystyle c=M^{-1}b</math>.)
stycznych Newtonowi jest pewną przesadą. Metodę Newtona taką, jaką znamy (z
pochodną w mianowniku), zaproponował w 1740 roku Simpson (ten od kwadratury), kilknaście lat po śmierci Newtona. Żeby było jeszcze zabawniej, odkrywcą
metody siecznych zdaje się być... Newton! Więcej na ten temat przeczytasz w
artykule T.Ypma w SIAM Review 37, 1995. [[Biografia Newton|Zobacz biografię]]]]


Startując z pewnego przybliżenia
W  tym przypadku
początkowego <math>\displaystyle x_0</math>, w kolejnych krokach metody, <math>\displaystyle k</math>-te
przybliżenie <math>\displaystyle x_k</math> jest punktem przecięcia stycznej do
wykresu <math>\displaystyle f</math> w punkcie <math>\displaystyle x_{k-1}</math>. Ponieważ równanie
stycznej wynosi <math>\displaystyle y(x)=f(x_{k-1})+f'(x_{k-1})(x-x_{k-1})</math>,
otrzymujemy wzór


{{algorytm|Metoda Newtona (stycznych)||
<center><math>\displaystyle x_k- x^*\,=\,B^k( x_0- x^*),
<pre>for k = 1,2,...
</math></center>
<math>\displaystyle x_k\,=\,x_{k-1}\,-\,\frac{f(x_{k-1})}{f'(x_{k-1})}</math>;
</pre>}}


Oczywiście, aby metoda Newtona była dobrze zdefiniowana,
a stąd i z nierówności <math>\displaystyle \|B^k\|\le\|B\|^k</math>, mamy
musimy założyć, że <math>\displaystyle f'(x_{k-1})</math> istnieje i nie
jest zerem.


<!--  
<center><math>\displaystyle \| x_k- x^*\|\,\le\,
[[Image:MNnewtononestep.png|thumb|550px|center|Metoda Newtona: pierwszy krok]]
          \|B\|^k\| x_0- x^*\|.  
-->
</math></center>
<div><flash>file=Newtononestep.swf|width=550|height=300</flash> <div.thumbcaption>Postęp iteracji Newtona</div></div>


Zauważmy, że metodę Newtona można traktować jako
Warunkiem dostatecznym zbieżności iteracji prostych
szczególny przypadek iteracji prostych, gdzie
jest więc <math>\displaystyle \|B\|<1</math>. Okazuje się, że warunkiem koniecznym i dostatecznym
zbieżności tej iteracji dla dowolnego wektora startowego <math>\displaystyle x_0</math> jest


<center><math>\displaystyle \phi(x)\,=\,x-\frac{f(x)}{f'(x)}.  
<center><math>\displaystyle \rho = \max\{ |\lambda| : \lambda  \mbox{ jest wartością własną } B\} < 1.
</math></center>
</math></center>


Widać też, że nie jest ona zbieżna globalnie.
Tak więc, metody oparte na iteracji prostej będą zbieżne liniowo z ilorazem
<math>\displaystyle \rho</math>.
 
Zaletą stacjonarnych metod iteracyjnych jest również ich prostota,
przez co są one łatwe do zaprogramowania, co łatwo zobaczyć na przykładach metod: [[#Metoda Jacobiego|Jacobiego]] i [[#Metoda Gaussa-Seidela|Gaussa--Seidela]], które teraz omówimy.  


Metoda Newtona i jej podobne należą do
====Metoda Jacobiego====
grupy metod <strong>zbieżnych lokalnie</strong>. Znaczy to, że
zbieżność ciągu <math>\displaystyle \{x_k\}_k</math> do zera danej funkcji <math>\displaystyle f</math>
jest zapewniona jedynie wtedy, gdy przybliżenia początkowe
zostały wybrane dostatecznie blisko <math>\displaystyle x^*</math>.


Nawet jeśli pochodna w <math>\displaystyle x_{k-1}</math> się nie zeruje,  
Biorąc <math>\displaystyle M =  \mbox{diag} (A)</math>, gdzie <math>\displaystyle \mbox{diag} (A)</math> jest macierzą diagonalną składającą się
ciąg <math>\displaystyle \{x_k\}_k</math> może nie zbiegać do zera funkcji <math>\displaystyle f</math>.
z wyrazów stojących na głównej przekątnej macierzy
Okazuje się jednak, że jeśli
<math>\displaystyle A</math>, układ <math>\displaystyle A x= b</math> jest równoważny układowi
wystartujemy dostatecznie blisko rozwiązania <math>\displaystyle x^*</math>, to
metoda Newtona jest zbieżna. Dokładniej, załóżmy
najpierw, że


<center><math>\displaystyle f(x^*)=0\quad \mbox{ oraz } \quad f'(x^*)\,\ne\,0.
<center><math>\displaystyle M x = Z x + b,
</math></center>
</math></center>


Ponadto załóżmy, że <math>\displaystyle f</math> jest dwukrotnie
a stąd (o ile na przekątnej macierzy <math>\displaystyle A</math> nie mamy zera)  
różniczkowalna w sposób ciągły, <math>\displaystyle f\in C^2(D)</math>.
otrzymujemy metodę iteracyjną
Rozwijając <math>\displaystyle \phi</math> w szereg Taylora w punkcie <math>\displaystyle x^*</math>,
otrzymujemy  


<center><math>\displaystyle x_k-x^*\,=\,\phi(x_{k-1})-\phi(x^*)\,=\,
<center><math>\displaystyle x_k\,=\,B x_{k-1}\,+\, c,  
  (x_{k-1}-x^*)\phi'(x^*)+(x_{k-1}-x^*)^2\phi''(\xi_k)/2,  
</math></center>
</math></center>


gdzie <math>\displaystyle \min(x^*,x_{k-1})\le\xi_k\le\max(x^*,x_{k-1})</math>.
gdzie <math>\displaystyle B=-M^{-1}Z</math> i <math>\displaystyle  c=M^{-1} b</math>, zwaną
Wobec tego, że <math>\displaystyle \phi'(x^*)=f(x)f''(x)/(f'(x))^2=0</math> i
<strong>metodą Jacobiego</strong>.
<math>\displaystyle \phi''(\xi_k)=f''(\xi_k)/f'(\xi_k)</math>, mamy
 
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>\displaystyle x^{(k)}_i = \frac{1}{a_{ii}} \left( b_i - \sum_{j\neq i} a_{ij}x^{(k-1)}_j \right),
</math></center>
 
co znaczy dokładnie tyle, że w <math>\displaystyle i</math>-tym równaniu wyjściowego układu przyjmujemy za współrzędne <math>\displaystyle x</math> wartości z poprzedniej iteracji i na tej podstawie wyznaczamy wartość <math>\displaystyle x_i</math>.
 
W metodzie Jacobiego warunek dostateczny zbieżności,
<math>\displaystyle \|B\|<1</math>, jest spełniony np. wtedy, gdy macierz <math>\displaystyle A</math> ma
dominującą przekątną, tzn. gdy


<center><math>\displaystyle  
<center><math>\displaystyle  
   x_k-x^*\,=\,(x_{k-1}-x^*)^2\frac{f''(\xi_k)}{2f'(\xi_k)}.
   |a_{i,i}|\,>\,\sum_{j\neq i}|a_{i,j}|,\qquad \forall i = 1,\ldots, N.
</math></center>
</math></center>


Zdefiniujmy liczbę
Rzeczywiście, ponieważ wyraz <math>\displaystyle (i,j)</math> macierzy <math>\displaystyle M^{-1}Z</math>
wynosi <math>\displaystyle 0</math> dla <math>\displaystyle i=j</math> oraz <math>\displaystyle a_{i,j}/a_{i,i}</math> dla <math>\displaystyle i\neq j</math>, a więc


<center><math>\displaystyle R_f\,=\,\sup_{r\ge 0}\sup_{\{x:|x-x^*|\le r\}}
<center><math>\displaystyle \aligned \lefteqn{\|M^{-1}Z\|_\infty \;=\; \max_{1\le i\le N}
  \Big|\frac{2(x-x^*)f''(x)}{f'(x)}\Big|\,<\,1.
  \sum_{j=1,j\ne i}^N{|a_{i,j}|}/{|a_{i,i}|} } \\
</math></center>
    && =\;\max_{1\le i\le N}
      \sum_{j=1}^N{|a_{i,j}|}/{|a_{i,i}|}\,-\,1\;<\;1,
\endaligned</math></center>
 
przy czym ostatnia nierówność wynika z warunku diagonalnej dominacji.


Oczywiście <math>\displaystyle R_f>0</math>. Dla <math>\displaystyle x_{k-1}</math> spełniającego 
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<math>\displaystyle |x_{k-1}-x^*|\le R<R_f</math>, mamy z poprzedniej równości
<span  style="font-variant:small-caps;">Przykład: Macierz laplasjanu</span>  
<div class="solution" style="margin-left,margin-right:3em;">


<center><math>\displaystyle |x_k-x^*|\,\le\,q\,|x_{k-1}-x^*|,
Macierz <math>\displaystyle N\times N</math>, zwana <strong>macierzą jednowymiarowego laplasjanu</strong>
<center><math>\displaystyle  
L = \begin{pmatrix}
2 & -1 &      &  \\
-1 & 2 & \ddots & \\
    & \ddots & \ddots & -1 \\
    &      &  -1 & 2
\end{pmatrix}  
</math></center>
</math></center>


gdzie <math>\displaystyle q<1</math> i <math>\displaystyle q</math> zależy tylko od <math>\displaystyle R</math>.  
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 <math>\displaystyle O(N)</math>. Stosując do niej metodę Jacobiego mamy <math>\displaystyle M = 2I</math> oraz <math>\displaystyle Z = L - M</math>. Obliczając
normę macierzy iteracji Jacobiego dostajemy <math>\displaystyle ||M^{-1}Z||_\infty
= 1</math>, co nie rozstrzyga jeszcze o jej zbieżności lub niezbieżności.


Niech teraz <math>\displaystyle x^*</math> będzie zerem <math>\displaystyle m</math>-krotnym,
Potrzebna będzie bardziej subtelna analiza, Okazuje się, że są znane wzory na wartości własne macierzy <math>\displaystyle L</math>:


<center><math>\displaystyle f(x^*)=f'(x^*)=\cdots =f^{(m-1)}(x^*)=0\ne f^{(m)}(x^*),
<center><math>\displaystyle \lambda_j = 4\sin^2 \left(\frac{j \pi }{2(N+1)} \right),
</math></center>
</math></center>


gdzie <math>\displaystyle m\ge 2</math>, oraz niech <math>\displaystyle f</math> będzie <math>\displaystyle m</math>-krotnie
dla <math>\displaystyle 1 \leq j \leq N.</math>
różniczkowalna w sposób ciągły. Wtedy


<center><math>\displaystyle \aligned x_k-x^* &= (x_{k-1}-x^*)\,-\,\frac{(x_{k-1}-x^*)^m
W konsekwencji, wartościami własnymi <math>\displaystyle M^{-1}Z = \frac{1}{2}Z = \frac{1}{2}L -
  \frac{f^{(m)} (\eta_k^{(1)})}{m!}}{(x_{k-1}-x^*)^{m-1}
I</math> są liczby <math>\displaystyle \mu_i = \frac{1}{2} \lambda_i - 1</math>. Ponieważ <math>\displaystyle 0 < \mu_i < 1</math>, znaczy to, że metoda Jacobiego jest zbieżna dla macierzy <math>\displaystyle L</math>.
  \frac{f^{(m-1)}(\eta_k^{(2)})}{(m-1)!}} \nonumber \\
  &= (x_{k-1}-x^*)\left(1-\frac 1m\frac
      {f^{(m)}(\eta_k^{(1)})}{f^{(m)}(\eta_k^{(2)})}\right) \nonumber \\
&\approx & (x_{k-1}-x^*)\Big( 1-\frac 1m\Big),
\endaligned</math></center>


o ile <math>\displaystyle x_{k-1}</math> jest "blisko" <math>\displaystyle x^*</math>.
Z drugiej strony, nie dajmy się zwieść optymizmowi matematyka (''"nie martw się, jest zbieżny..."''): nietrudno sprawdzić, że <math>\displaystyle ||Z||_2 = 1 - O(N^{-2}) < 1</math>, co oznacza, że metoda Jacobiego --- choć zbieżna --- dla dużych <math>\displaystyle N</math> staje się
zbieżna tak wolno, że w praktyce bezużyteczna!
</div></div>


Metoda Newtona jest więc zbieżna lokalnie. Gdy <math>\displaystyle x_0</math> jest zbyt daleko od rozwiązania może zdarzyć się, że iteracja Newtona zacznie nas oddalać od miejsca zerowego, co ilustruje poniższy przykład:
====Metoda Gaussa-Seidela====


<!--  
<!--  
[[Image:MNnewtononestepdiv.png|thumb|550px|center|Metoda Newtona: jeśli startujemy zbyt daleko od miejsca zerowego <math>\displaystyle f</math>, zamiast przybliżać się do niego, zaczynamy się oddalać! (gdzie będzie <math>\displaystyle x_3</math>?...)]]
Ciekawostką jest, że Gauss nie miał z nią nic wspólnego, a Seidel był podobno jej przeciwnikiem...
-->
-->
   
   
<div><flash>file=Newtononestepdiv.swf|width=550|height=300</flash> <div.thumbcaption>Metoda Newtona: jeśli startujemy zbyt daleko od miejsca zerowego <math>\displaystyle f</math>, zamiast przybliżać się do niego, zaczynamy się oddalać! (gdzie będzie <math>\displaystyle x_3</math>?...)</div></div>
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>\displaystyle x</math>.


Z powyższego można też wywnioskować,  
Rzeczywiście, przecież rozwiązując równanie metody Jacobiego:
jaki jest charakter zbieżności metody Newtona. Dla zera
jednokrotnego <math>\displaystyle x^*</math> oraz <math>\displaystyle f''(x^*)\ne 0</math> mamy bowiem


<center><math>\displaystyle |x_k-x^*|\, \approx \,|x-x_{k-1}|^2 \frac{|f''(x^*)|}{2|f'(x^*)|}.
<center><math>\displaystyle 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>


Mówimy, że zbieżność metody Newtona, gdy <math>\displaystyle f(x^*)\neq 0</math> jest <strong>kwadratowa</strong>.  
nietrudno zauważyć, że w części sumy moglibyśmy odwoływać się do "dokładniejszych" wartości <math>\displaystyle x^{(k)}_j</math>: dla <math>\displaystyle j < i</math>, tzn.


{{stwierdzenie|||
<center><math>\displaystyle 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).
Jeśli <math>\displaystyle f(x^*)\neq 0</math> oraz
</math></center>
<math>\displaystyle f''(x^*)=0</math> to zbieżność jest nawet szybsza. Z kolei dla
zera <math>\displaystyle m</math>-krotnego (tzn. <math>\displaystyle f(x^*) = f'(x^*)= \ldots f^{(m)}(x^*)= 0</math>, <math>\displaystyle m>1</math>)  
zbieżność jest liniowa z ilorazem <math>\displaystyle (1-\frac{1}{m})</math>.
}}


Metoda Newtona jest pierwszą poznaną tutaj metodą
W języku rozkładu macierzy <math>\displaystyle A = M - Z</math> i iteracji <math>\displaystyle x_{k+1} = M^{-1}(Zx_k + b)</math> mamy więc <math>\displaystyle M =  \mbox{tril} (A)</math> (dolny trójkąt macierzy <math>\displaystyle A</math>).
iteracyjną, która jest (dla zer jednokrotnych) zbieżna
szybciej niż liniowo. Dla takich metod wprowadza się
pojęcie <strong>wykładnika zbieżności</strong>, który jest
zdefiniowany następująco.  


[[Image:MNstycznebisekcja.png|thumb|550px|center|Porównanie zbieżności metody bisekcji i stycznych
{{twierdzenie|O zbieżności metody Gaussa--Seidela|O zbieżności metody Gaussa--Seidela|
dla równania <math>\displaystyle e^x - 1 = 0</math>. Błąd kolejnych przybliżeń wyświetlany jest w skali
logarytmicznej, dzięki czemu lepiej widać różnicę między zbieżnością liniową a
kwadratową.]]


Powiemy, że metoda iteracyjna <math>\displaystyle \phi</math> jest w klasie funkcji <math>\displaystyle F</math>
Jeśli macierz <math>\displaystyle A</math> jest diagonalnie dominująca, to metoda Gaussa--Seidela jest zbieżna dla dowolnego wektora startowego <math>\displaystyle x_0</math>.
<strong>rzędu co najmniej <math>\displaystyle p\ge 1</math></strong>, gdy spełniony jest następujący
}}
warunek. Niech <math>\displaystyle f\in F</math> i <math>\displaystyle f(x^*)=0</math>. Wtedy istnieje stała
<math>\displaystyle C<\infty</math> taka, że dla dowolnych przybliżeń początkowych 
<math>\displaystyle x_0,\ldots,x_{s-1}</math> dostatecznie bliskich <math>\displaystyle x^*</math>, kolejne
przybliżenia <math>\displaystyle x_k=\phi(x_{k-1},\ldots,x_{k-s})</math> generowane
tą metodą spełniają


<center><math>\displaystyle |x_k-x^*|\,\le\,C\,|x_{k-1}-x^*|^p.
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ę.
</math></center>


Ponadto, jeśli <math>\displaystyle p=1</math> to dodatkowo żąda się, aby <math>\displaystyle C<1</math>.
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<span  style="font-variant:small-caps;">Uwaga</span>  
<div class="solution" style="margin-left,margin-right:3em;">


{{definicja|||
Obie metody, Jacobiego i (zwłaszcza) Gaussa--Seidela stosuje się także czasem w prostych algorytmach rozwiązywania <strong>układów równań nieliniowych</strong>: ich zaletą jest to, że ich głównym składnikiem jest rozwiązywanie <strong>skalarnego</strong> równania nieliniowego na każdym kroku metody.
<strong>Wykładnikiem zbieżności</strong> metody
</div></div>
iteracyjnej <math>\displaystyle \phi</math> w klasie <math>\displaystyle F</math> nazywamy liczbę <math>\displaystyle p^*</math>  
zdefiniowaną równością


<center><math>\displaystyle p^*\,=\,\sup\,\{\,p\ge 1:\,\phi
====Złożoność stacjonarnych metod iteracyjnych====
    \mbox{ jest rzędu co najmniej  }  p\,\}.
</math></center>


}}
Zastanówmy się teraz nad złożonością metod iteracyjnych. Ponieważ możemy jedynie znaleźć pewne przybliżenie rozwiązania dokładnego <math>\displaystyle  x^*</math>, przez  złożoność metody będziemy rozumieli koszt kombinatoryczny obliczenia <math>\displaystyle  x_k</math> z zadaną dokładnością <math>\displaystyle \epsilon>0</math>. Dla uproszczenia założymy, że medoda jest zbieżna liniowo z ilorazem <math>\displaystyle \rho</math>. Zauważmy, że aby zredukować błąd początkowy do  <math>\displaystyle \epsilon>0</math>, wystarczy wykonać <math>\displaystyle k=k(\epsilon)</math> iteracji, gdzie <math>\displaystyle k</math> spełnia


Możemy teraz sformułować następujące twierdzenie,  
<center><math>\displaystyle \rho^k\| x_0- x^*\|\,\le\,\epsilon,
które natychmiast wynika z poprzednich rozważań.
</math></center>


{{twierdzenie|O rzędzie zbieżności metody Newtona|O rzędzie zbieżności metody Newtona|
czyli
Wykładnik zbieżności metody Newtona
(stycznych) wynosi <math>\displaystyle p^*=2</math> w klasie funkcji o zerach
jednokrotnych, oraz <math>\displaystyle p^*=1</math> w klasie funkcji o zerach
wielokrotnych.
}}


[[Image:MNmultiplezeros.png|thumb|550px|center|Zbieżność metody Newtona dla zer wielokrotnych <math>\displaystyle f(x)
<center><math>\displaystyle k\,\ge\,\frac{\log(1/\epsilon) - \log(1/\| x_0- x^*\|)}{\log(1/\rho)}.
= (x-1)^5</math> jest liniowa z ilorazem <math>\displaystyle \frac{4}{5}</math> (końcowe załamanie wykresu
</math></center>
spowodowane jest przypadkowym trafieniem w dokładne miejsce zerowe). Metoda bisekcji nie jest na to czuła i dalej zbiega z ilorazem
<math>\displaystyle \frac{1}{2}</math>.]]


==Metoda siecznych==
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>\displaystyle \rho</math>, natomiast zależność od dokładności <math>\displaystyle \epsilon</math> i wymiaru <math>\displaystyle N</math> układu jest dużo mniej istotna (w zadaniach praktycznych -- takich jak jednowymiarowy laplasjan --- jednak często
okazuje się, że... <math>\displaystyle \rho</math> zależy od <math>\displaystyle N</math>!).


Inną znaną i często używaną metodą iteracyjną, opartą na podobnym pomyśle
Zakładając, że koszt jednej iteracji wynosi <math>\displaystyle c=c(N)</math> (<math>\displaystyle c(N)</math> jest tym mniejszy, im mniejsza jest liczba niezerowych elementów macierzy <math>\displaystyle A</math>), złożoność  metody jest proporcjonalna do
linearyzacyjnym co metoda Newtona,
jest <strong>metoda siecznych</strong>, w której zamiast przybliżenia wykresu <math>\displaystyle f</math> przez
styczną,  stosuje się  przybliżenie sieczną.
Metoda ta
wykorzystuje więc do konstrukcji <math>\displaystyle x_k</math> przybliżenia
<math>\displaystyle x_{k-1}</math> i <math>\displaystyle x_{k-2}</math>. Musimy również wybrać dwa różne
punkty startowe <math>\displaystyle x_0</math> i <math>\displaystyle x_1</math>. Ponieważ sieczna dla
<math>\displaystyle f</math> w punktach <math>\displaystyle x_{k-1}</math> i <math>\displaystyle x_{k-2}</math> ma wzór


<center><math>\displaystyle y(x)\,=\,\frac{x-x_{k-2}}{x_{k-1}-x_{k-2}}f(x_{k-1})+
<center><math>\displaystyle c(N)\,\frac{\log(1/\epsilon)}{\log(1/\rho)}.
          \frac{x-x_{k-1}}{x_{k-2}-x_{k-1}}f(x_{k-2}),
</math></center>
</math></center>


otrzymujemy
Stąd oczywisty wniosek (prawdziwy nie tylko dla metod stacjonarnych), że metody iteracyjne warto stosować zamiast metod bezpośrednich w przypadku, gdy
* wymiar <math>\displaystyle N</math> układu <math>\displaystyle A x= b</math> jest "duży", oraz
* macierz <math>\displaystyle A</math> układu jest "rozrzedzona", tzn. ma stosunkowo niewielką liczbę elementów  niezerowych, np. proporcjonalną do <math>\displaystyle N</math>.
 
Układy o tych własnościach powstają często przy numerycznym rozwiązywaniu równań różniczkowych cząstkowych.
 
==Metody przestrzeni Kryłowa==


{{algorytm|Metoda siecznych||
Zupełnie inny pomysł na realizację metody iteracyjnej przedstawiają metody przestrzeni Kryłowa, gdzie kolejne przybliżenie <math>\displaystyle x_k</math> dobiera się w taki sposób, by minimalizowało pewną miarę błędu na podprzestrzeni Kryłowa
<pre>for k = 1,2,...
<math>\displaystyle x_k\,=\,x_{k-1}\,-\,\frac{x_{k-1}-x_{k-2}} {f(x_{k-1})-f(x_{k-2})}\,f(x_{k-1})</math>;
end
</pre>}}


Zauważmy, że jeśli <math>\displaystyle x_{k-1}</math> i <math>\displaystyle x_{k-2}</math> są blisko
<center><math>\displaystyle K_k =  \mbox{span} \{r,A_r,\ldots, A^{k-1}r \},
siebie, to <math>\displaystyle x_k</math> jest podobny do tego z metody Newtona,  
bowiem wtedy iloraz różnicowy [[MN14#Różniczkowanie|przybliża pochodną]] <math>\displaystyle f</math>,
<center><math>\displaystyle
\frac{f(x_{k-1})-f(x_{k-2})}{x_{k-1}-x_{k-2}} \approx f'(x_{k-1}).
</math></center>
</math></center>
Nie wystarcza to jednak, aby osiągnąć zbieżność z wykładnikiem
<math>\displaystyle 2</math>. Można pokazać, że przy podobnych założeniach o funkcji, wykładnik zbieżności metody siecznych dla zer jednokrotnych i dostatecznie gładkich funkcji wynosi <math>\displaystyle p^*=\frac{1+\sqrt{5}}{2}=1.618\ldots</math>. Jako wariant metody Newtona, metoda siecznych jest również zbieżna lokalnie.


[[Image:MNstycznesiecznebisekcja.png|thumb|550px|center|Porównanie zbieżności metody bisekcji,
gdzie <math>\displaystyle r = b-Ax_0</math> jest ''residuum'' na początku iteracji. (Zwróć uwagę, że przestrzeń Kryłowa jest rozpięta przez kolejne wektory \link{sec:eigenvalue}{iteracji prostej}--- 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.
stycznych i siecznych
dla równania <math>\displaystyle e^x - 1 = 0</math>. Błąd kolejnych przybliżeń wyświetlany jest w skali
logarytmicznej.]]


Niewątpliwą zaletą metody siecznych jest jednak to, że <strong>nie wymaga obliczania pochodnej funkcji</strong> (bywa, że dokładne wyznaczenie pochodnej jest niemożliwe, gdy np. funkcja jest zadana zewnętrzną procedurą, do której kodu źródłowego nie mamy dostępu; zwykle też koszt obliczenia wartości pochodnej jest wyższy od kosztu obliczenia wartości funkcji). Jest to również istotne w pakietach numerycznych, gdzie czasem nie chcemy wymagać od użytkownika czegokolwiek, oprócz podania wzoru na funkcję i przybliżonej lokalizacji miejsca zerowego.
====CG====


Ponadto, często zdarza się, że wyznaczenie wartości pochodnej, <math>\displaystyle f'(x_k)</math>, jest
Metoda <strong>gradientów sprzężonych</strong>, w skrócie CG (''conjugate gradients''), działa przy założeniu, że <math>\displaystyle A</math> jest <strong>symetryczna i dodatnio określona</strong>.
tak samo, albo i bardziej kosztowne od wyznaczenia wartości <math>\displaystyle f(x_k)</math>. W takim
wypadku okazuje się, że metoda stycznych --- choć wolniej zbieżna niż metoda
stycznych --- dzięki temu, że jej iteracja wymaga jedynie wyznaczenia jednej wartości <math>\displaystyle f</math>, jest <strong>bardziej efektywna</strong> od metody Newtona: koszt osiągnięcia zadanej dokładności jest w takim przypadku mniejszy od analogicznego kosztu dla metody Newtona.


Jednak gdy żądane przez użytkownika dokładności są bardzo wielkie, a sama
Kolejne przybliżenie <math>\displaystyle x_k</math> ma minimalizować błąd w normie energetycznej
funkcja "złośliwa", metoda siecznych może cierpieć z powodu redukcji cyfr
indukowanej przez <math>\displaystyle A</math>,
przy odejmowaniu.


==Metoda Brenta==
<center><math>\displaystyle ||x_k -x||_A = \sqrt{(x_k -x)^TA(x_k -x)}
</math></center>


Naturalnie, uważny student zaczyna zadawać sobie pytanie, czy nie można w jakiś
na przestrzeni afinicznej <math>\displaystyle 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:
sposób połączyć globalnej zbieżności metody bisekcji z szybką zbieżnością
 
metody siecznych tak, by uzyskać metodę zbieżną globalnie, a jednocześnie
{{algorytm|Metoda CG|Metoda CG|
istotnie szybciej niż liniowo.
<pre>r = b-A*x;
<math>\displaystyle \rho_0</math> = <math>\displaystyle ||r||_2^2</math>; <math>\displaystyle \beta</math> = 0; k = 1;
while (!stop)
{
p = r + <math>\displaystyle \beta</math>*p;
w = A*p;
<math>\displaystyle \alpha</math> = <math>\displaystyle \rho_{k-1}</math>/<math>\displaystyle p^Tw</math>;
x = x + <math>\displaystyle \alpha</math>*p;
r = r - <math>\displaystyle \alpha</math>*w;
<math>\displaystyle \rho_k</math> = <math>\displaystyle ||r||_2^2</math>;
<math>\displaystyle \beta</math> = <math>\displaystyle \frac{\rho_{k}}{\rho_{k-1}}</math>;
k++;
}
</pre>}}


Okazuje się, że można to zrobić, wprowadzając metodę opartą na <strong>trzech</strong> punktach lokalizujących miejsce zerowe: dwóch odcinających zero tak jak
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>\displaystyle K_k</math>), a najdroższym jej elementem jest mnożenie macierzy przez wektor.
w metodzie bisekcji i trzecim, konstruowanym np. jak w metodzie stycznych. W
kolejnej iteracji wymieniamy jeden z punktów albo wedle metody
siecznych (i wtedy zapewne szybciej zbliżamy się do zera), albo wykonując bisekcję (aby zagwarantować sobie, że w wiadomym przedziale miejsce zerowe rzeczywiście się znajduje).


Ten prosty pomysł <strong>metody hybrydowej</strong> wymaga jednak subtelnego dopracowania. Zostało to zrobione w 1973 roku przez [http://www.rpbrent.com  Richarda Brenta]. Funkcja MATLABa (i Octave'a) <code style="color: #006">fzero</code> implementują właśnie metodę Brenta.
{{twierdzenie|O zbieżności CG jako metody bezpośredniej|O zbieżności CG jako metody bezpośredniej|
Autorem implementacji w Octave jest ówczesny student [http://www.mimuw.edu.pl  matematyki] na Uniwersytecie Warszawskim, Łukasz Bodzon. Fortranowski kod metody Brenta można znaleźć także w [http://www.netlib.org/go/zeroin.f  Netlibie]. Inną funkcją Octave'a służącą rozwiązywaniu równań nieliniowych jest <code style="color: #006">fsolve</code>:


<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:1> [X, MSG, INFO] = fsolve ('cos', 1)
Niech <math>\displaystyle 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>\displaystyle N</math> iteracjach.
X =  1.5708
}}
MSG =  1
INFO = solution converged within specified tolerance


octave:2> cos(X)
Powyższe twierdzenie, choć teoretycznie interesujące, ma małą wartość praktyczną z dwóch powodów:
ans =  6.1230e-17
* dla bardzo dużych <math>\displaystyle N</math>, wykonanie <math>\displaystyle N</math> iteracji może być wciąż zbyt kosztownym zadaniem;
</nowiki></div>
* 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>\displaystyle x_k</math> przestaje się poprawiać.
   
   
==Metody dla układów równań nieliniowych==
Dlatego wygodniej potraktować CG jako metodę iteracyjną. Zachodzi bowiem


Niektóre z poznanych metod można łatwo rozszerzyć na przypadek układu <math>\displaystyle N</math> równań z <math>\displaystyle N</math> niewiadomymi, to znaczy
{{twierdzenie|Zbieżność CG jako metody iteracyjnej|Zbieżność CG jako metody iteracyjnej|


<center><math>\displaystyle F(x) = 0,
Po <math>\displaystyle k</math> iteracjach metody CG,
 
<center><math>\displaystyle ||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>\displaystyle F: R^N \rightarrow R^N</math>.
gdzie <math>\displaystyle \mbox{cond} (A) = ||A||_2||A^{-1}||_2</math>.
}}


====Metoda Banacha====
====GMRES====


Jak pamiętamy, [[#Banacha, o kontrakcji|metodę Banacha]] sformułowaliśmy od razu dla zagadnienia wielowymiarowego. Analiza i własności metody są zatem już [[#Banacha, o kontrakcji|omówione]].
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 wykracza niestety poza ramy niniejszego wykładu.
====Wielowymiarowa metoda Newtona====


Okazuje się, że metodę Newtona można uogólnić na przypadek układu <math>\displaystyle N</math> równań nieliniowych z <math>\displaystyle N</math> niewiadomymi. Zapiszmy wzór na skalarną metodę Newtona odrobinę inaczej:
====Ściskanie macierzy====


<center><math>\displaystyle x_{k+1} = x_k - [F'(x_k)]^{-1}\, F(x_k).
Zbieżność wszystkich poznanych metod iteracyjnych zależy od własności
</math></center>
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.


Niezwykłe jest, że taki wzór nie tylko ma sens w przypadku, gdy <math>\displaystyle F: R^N \rightarrow R^N</math> (wtedy <math>\displaystyle F'(x_k)</math> jest macierzą Jakobianu <math>\displaystyle F</math> w punkcie <math>\displaystyle x_k</math>), ale dodatkowo ta metoda zachowuje wszystkie własności metody stycznych dla przypadku skalarnego:
Dlatego bardzo korzystne może być wstępne przetransformowanie układu


{{twierdzenie|O zbieżności wielowymiarowej metody Newtona|O zbieżności wielowymiarowej metody Newtona|
<center><math>\displaystyle Ax = b
</math></center>


Załóżmy, że <math>\displaystyle F: R^N \rightarrow R^N</math> i istnieje <math>\displaystyle x^* \in R^N</math> taki, że
z macierzą o niekorzystnych własnościach, do układu


<center><math>\displaystyle F(x^*) = 0.
<center><math>\displaystyle MAx = Mb,
</math></center>
</math></center>


Załóżmy ponadto, że <math>\displaystyle F</math> jest różniczkowalna, a jej pochodna <math>\displaystyle F': R^N \rightarrow R^{N\times N}</math> jest lipschitzowska i dodatkowo
gdzie macierz <math>\displaystyle 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>\displaystyle MA</math> 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 <math>\displaystyle MA</math> zbiegała szybko, musimy w jakiś sposób "ścisnąć" spektrum macierzy <math>\displaystyle A</math> w okolice jedności. Taką operację nazywamy <strong>ściskaniem</strong> (''preconditioning''), a macierz <math>\displaystyle M</math> --- <strong>imadłem</strong>.


<center><math>\displaystyle F'(x^*) \mbox{ jest nieosobliwa} .
Aby całość miała sens, macierz ściskająca <math>\displaystyle M</math> powinna:
</math></center>
* 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>\displaystyle M\cdot (A \cdot x)</math>),
* macierz <math>\displaystyle MA</math> powinna mieć znacznie korzystniejsze własności z punktu widzenia używanej metody iteracyjnej.
   
Kilka ekstremalnych propozycji na macierz imadła to <math>\displaystyle M = I</math> (łatwa w
konstrukcji i tania w mnożeniu, ale niestety nic nie polepsza...) oraz
<math>\displaystyle 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
należy poszukiwać czegoś pośredniego, co niskim kosztem przybliża działanie
macierzy odwrotnej.


Wówczas, jeśli tylko <math>\displaystyle x_0</math> jest dostatecznie blisko rozwiązania <math>\displaystyle x^*</math>, to ciąg kolejnych przybliżeń <math>\displaystyle x_k</math>, generowany wielowymiarową metodą Newtona, jest zbieżny do <math>\displaystyle x^*</math>. Co więcej, szybkość zbieżności jest kwadratowa.
Dlatego jednym z powszechniej stosowanych (aczkolwiek wciąż nie najbardziej skutecznych) sposobów ściskania są te oparte na zastosowaniu jednego kroku klasycznej metody iteracyjnej.
}}


====Implementacja wielowymiarowej metody Newtona====
[[Image:MNpcgconv.png|thumb|550px|center|Zbieżność metody CG bez żadnego  ściskania oraz ściśniętej
imadłem opartym na jednej iteracji (blokowej) metody Jacobiego.]]


Implementując wielowymiarową metodę Newtona, musimy dysponować nie tylko funkcją obliczającą <math>\displaystyle N</math> współrzędnych wektora wartości <math>\displaystyle F</math>, ale także funkcją wyznaczającą <math>\displaystyle N^2</math> elementów macierzy pochodnej <math>\displaystyle F</math> w zadanym punkcie <math>\displaystyle x \in R^N</math>. Zwróćmy uwagę na to, że w implementacji metody nie trzeba wyznaczać <math>\displaystyle F'(x_k)^{-1}</math>, tylko rozwiązać układ równań:
Inne sposoby ściśnięcia macierzy wykorzystują np. techniki tzw. <strong>niepełnego
rozkładu</strong> macierzy, albo --- w specyficznych przypadkach --- tzw.<strong> metody
wielosiatkowe</strong>.


{{algorytm|Wielowymiarowa metoda Newtona||
Okazuje się, że zarówno CG jak i GMRES da się zaimplementować tak, by w jednej
<pre>while (!stop)
iteracji było konieczne tylko jedno mnożenie przez macierz imadła.
{
rozwiąż (względem <math>\displaystyle s</math>) układ równań liniowych <math>\displaystyle F'(x_k)\, s = -F(x_k)</math>;
<math>\displaystyle x_{k+1}</math> = <math>\displaystyle x_k</math> + <math>\displaystyle s</math>;
}
</pre>}}
 
O tym, [[MN05|jak skutecznie rozwiązywać układy równań liniowych]], dowiesz się z kolejnych wykładów. Dowiesz się także, dlaczego ''nie należy'' w implementacji korzystać z wyznaczonej ''explicite'' macierzy odwrotnej do macierzy Jakobianu.


==Literatura==
==Literatura==


W celu dogłębnego zapoznania się z omawianym na wykładzie materiałem, przeczytaj <b>rozdział 3</b> w
W celu dogłębnego zapoznania się z omawianym na wykładzie materiałem, przeczytaj <b>rozdział 4.6 i 4.7</b> w
* D. Kincaid, W. Cheney <cite>Analiza numeryczna</cite>, Wydawnictwa Naukowo-Techniczne, Warszawa 2006, ISBN 83-204-3078-X.
* D. Kincaid, W. Cheney <cite>Analiza numeryczna</cite>, 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 podręcznik
Rozdziały 3.5 i 3.6 nie są obowiązkowe.
* <span style="font-variant:small-caps">C. T. Kelley</span>, <cite>Iterative Solution of Systems of Linear and Nonlinear Equations</cite>, SIAM, 1995, albo
 
* <span style="font-variant:small-caps">Y. Saad</span>, <cite>[http://www-users.cs.umn.edu/&nbsp;saad/books.html  Iterative Methods for Sparse Linear Systems]</cite>, PWS, 1996.
Wiele wariantów metod rozwiązywania <strong>układów</strong> równań nieliniowych jest przedstawionych w znakomitej monografii
* <span style="font-variant:small-caps">C.T.Kelley</span>, <cite>Iterative Solution of Systems of Linear and Nonlinear Equations</cite>, SIAM, 1995.
 
Opis metody Brenta znajdziesz w książce
* <span style="font-variant:small-caps">R. Brent</span>, <cite>Algorithms for Minimization Without Derivatives</cite>, Prentice-Hall, 1973.

Wersja z 15:51, 29 wrz 2006


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 N ma tylko O(N) 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ą N2 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 [http://www.cise.ufl.edu/research/sparse/matrices/Boeing kolekcji Tima Davisa]. Jest to mała macierz, wymiaru 8032 (w kolekcji spotkasz równania z milionem i więcej niewiadomych).

Struktura niezerowych elementów macierzy bcsstk38.

Jej współczynnik wypełnienia (to znaczy, stosunek liczby niezerowych do wszystkich elementów macierzy) wynosi jedynie 0.006, 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 A wymiaru N×M o NNZ niezerowych elementów wykorzystujemy trzy wektory: I, J --- oba typu int --- oraz V, typu double, wszystkie o długości NNZ, przy czym

AI[k],J[k]=V[k],k=0,,NNZ1.
Format AIJ

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 rozwiązywać układ równań z macierzą rozrzedzoną.

octave:10> I = [1, 1, 1, 2, 3, 1, 4]; octave:11> J = [1, 3, 2, 2, 3, 4, 4]; octave:12> V = [1, 2, 3, 4, 5, 6, 7]; octave:13> N = 4; octave:14> A = sparse(I,J,V,N,N) A = Compressed Column Sparse (rows = 4, cols = 4, nnz = 7) (1, 1) -> 1 (1, 2) -> 3 (2, 2) -> 4 (1, 3) -> 2 (3, 3) -> 5 (1, 4) -> 6 (4, 4) -> 7

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 NNZ, zawierającym kolejne niezerowe elementy macierzy A wpisywane kolumnami, AI jest wektorem typu int o długości NNZ, zawierającym numery wierszy macierzy A 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 M, zawierający na j-tym miejscu indeks pozycji w AV, od którego rozpoczynają się w AV elementy j-tej kolumny macierzy A.

Format CSC

Mamy więc zależność, przy założeniu, że AP[0]=0,

AAI[AP[j]+k],j+1=AV[AP[j]+k],j=0,,M1,k=0,,AP[j+1]1.

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 P×N, gdzie P jest liczbą niezerowych diagonal w ARN×N.

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

Ax=b,

ale w sytuacji, gdy macierz A 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 A taka, że dla |ij|d, aij=0, nazywamy macierzą taśmową z rozstępem d, o szerokości pasma 2d+1.

Ł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 max{2d,N} --- tak więc, dla niezbyt dużych d wciąż wynikowa macierz jest taśmowa.

W szczególności, gdy macierz jest taśmowa z pasmem o rozstępie d i jednocześnie diagonalnie dominująca, wtedy rozkład LU takiej macierzy da się wykonać w miejscu kosztem O(dN), czyli liniowym.

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 d=1:

A=(a1c1b2a2c2b3a3cN1bNaN)

Zadanie rozwiązywania równań z taką macierzą

Ax=e

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 A ma słabo dominującą diagonalę, tzn.

|ai||bi|+|ci|,1iN,

(b1=0=cN) i przynajmniej dla jednego indeksu "i" mamy powyżej ostrą nierówność ">", to algorytm przeganiania jest wykonalny bez przestawień wierszy. Ponadto wymaga on 7N operacji arytmetycznych, a więc jest prawie optymalny.

Algorytm Metoda przeganiania


<math>\displaystyle d_1</math> = <math>\displaystyle a_1</math>; 
<math>\displaystyle f_1</math> = <math>\displaystyle e_1</math>;
for (i = 2; i <= N; i++)
{
	<math>\displaystyle l</math> = <math>\displaystyle b_i</math>/<math>\displaystyle a_{i-1}</math>;
	<math>\displaystyle d_i</math> = <math>\displaystyle a_i</math> - <math>\displaystyle l</math> * <math>\displaystyle c_{i-1}</math>;
	<math>\displaystyle f_i</math> = <math>\displaystyle e_i</math> - <math>\displaystyle l</math> * <math>\displaystyle f_{i-1}</math>;
} 
<math>\displaystyle x_1</math> = <math>\displaystyle f_N</math>;
for (i = N-1; i >= 1; i--)
	<math>\displaystyle x_i</math> = <math>\displaystyle f_i</math> - <math>\displaystyle c_i</math> * <math>\displaystyle x_{i+1}</math>;

Metody bezpośrednie

Przykład: Strzałka Wilkinsona

Rozważmy układ równań z macierzą diagonalnie dominującą postaci

A=(**********)

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 P):

A~=PAPT=(**********)

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

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 A 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: 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 algorytmu

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, wypełnieniu około 0.6 procent.

Struktura niezerowych elementów macierzy.

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

Czynnik rozkładu Cholesky'ego L wykonanego standardowym algorytmem. Czas rozkładu: 0.892013
Czynnik rozkładu Cholesky'ego L z reorderingiem COLAMD. Czas rozkładu: 0.813038
Czynnik rozkładu Cholesky'ego L z reorderingiem SYMAMD. Czas rozkładu: 0.487683s. Prawie dwa razy szybciej niż bez reorderingu, chociaż i tak wskutek wzrostu wypełnienia macierzy w dolnym trójkącie mamy aż 2 procent niezerowych elementów.
Czynnik rozkładu Cholesky'ego L z odwrotnym reorderingiem Cuthill-McKee. Czas rozkładu: 0.845928
Czynnik rozkładu Cholesky'ego L z jeszcze 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:

Rozkład LU, czynnik L (bez reorderingu). Czas rozkładu LU: 1.696018s. Nieakceptowalny, podobnie jak drastyczne wypełnienie macierzy.
Rozkład LU, czynnik U (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ć.

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ą", M, i "resztę", Z. Dokładniej, jeśli M jest nieosobliwa, to równanie Ax=b można zapisać jako zadanie punktu stałego

Mx=Nx+b,

gdzie Z=MA. Inaczej:

x=M1(Zx+b),

i zastosować doń metodę iteracji prostej Banacha:

xk+1=M1(Zxk+b).

Takie metody nazywamy stacjonarnymi metodami iteracyjnymi. Aby przeanalizować zbieżność takiej metody, warto rozpatrzyć przypadek ogólniejszy

xk=Bxk1+c,

dla pewnej macierzy B oraz wektora c. (Dla stacjonarnej metody iteracyjnej, B=M1Z oraz c=M1b.)

W tym przypadku

xkx*=Bk(x0x*),

a stąd i z nierówności BkBk, mamy

xkx*Bkx0x*.

Warunkiem dostatecznym zbieżności iteracji prostych jest więc B<1. Okazuje się, że warunkiem koniecznym i dostatecznym zbieżności tej iteracji dla dowolnego wektora startowego x0 jest

ρ=max{|λ|:λ jest wartością własną B}<1.

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 M=diag(A), gdzie diag(A) jest macierzą diagonalną składającą się z wyrazów stojących na głównej przekątnej macierzy A, układ Ax=b jest równoważny układowi

Mx=Zx+b,

a stąd (o ile na przekątnej macierzy A nie mamy zera) otrzymujemy metodę iteracyjną

xk=Bxk1+c,

gdzie B=M1Z i c=M1b, 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ń:

xi(k)=1aii(bijiaijxj(k1)),

co znaczy dokładnie tyle, że w i-tym równaniu wyjściowego układu przyjmujemy za współrzędne x wartości z poprzedniej iteracji i na tej podstawie wyznaczamy wartość xi.

W metodzie Jacobiego warunek dostateczny zbieżności, B<1, jest spełniony np. wtedy, gdy macierz A ma dominującą przekątną, tzn. gdy

|ai,i|>ji|ai,j|,i=1,,N.

Rzeczywiście, ponieważ wyraz (i,j) macierzy M1Z wynosi 0 dla i=j oraz ai,j/ai,i dla ij, a więc

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \lefteqn{\|M^{-1}Z\|_\infty \;=\; \max_{1\le i\le N} \sum_{j=1,j\ne i}^N{|a_{i,j}|}/{|a_{i,i}|} } \\ && =\;\max_{1\le i\le N} \sum_{j=1}^N{|a_{i,j}|}/{|a_{i,i}|}\,-\,1\;<\;1, \endaligned}

przy czym ostatnia nierówność wynika z warunku diagonalnej dominacji.

Przykład: Macierz laplasjanu

Macierz N×N, zwana macierzą jednowymiarowego laplasjanu

L=(2112112)

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 O(N). Stosując do niej metodę Jacobiego mamy M=2I oraz Z=LM. Obliczając normę macierzy iteracji Jacobiego dostajemy ||M1Z||=1, 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 L:

λj=4sin2(jπ2(N+1)),

dla 1jN.

W konsekwencji, wartościami własnymi M1Z=12Z=12LI są liczby μi=12λi1. Ponieważ 0<μi<1, znaczy to, że metoda Jacobiego jest zbieżna dla macierzy L.

Z drugiej strony, nie dajmy się zwieść optymizmowi matematyka ("nie martw się, jest zbieżny..."): nietrudno sprawdzić, że ||Z||2=1O(N2)<1, co oznacza, że metoda Jacobiego --- choć zbieżna --- dla dużych N 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 x.

Rzeczywiście, przecież rozwiązując równanie metody Jacobiego:

xi(k)=1aii(bijiaijxj(k1)),

nietrudno zauważyć, że w części sumy moglibyśmy odwoływać się do "dokładniejszych" wartości xj(k): dla j<i, tzn.

xi(k)=1aii(bij<iaijxj(k)j>iaijxj(k1)).

W języku rozkładu macierzy A=MZ i iteracji xk+1=M1(Zxk+b) mamy więc M=tril(A) (dolny trójkąt macierzy A).

Twierdzenie O zbieżności metody Gaussa--Seidela

Jeśli macierz A jest diagonalnie dominująca, to metoda Gaussa--Seidela jest zbieżna dla dowolnego wektora startowego x0.

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 ich głównym składnikiem 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 x*, przez złożoność metody będziemy rozumieli koszt kombinatoryczny obliczenia xk z zadaną dokładnością ϵ>0. Dla uproszczenia założymy, że medoda jest zbieżna liniowo z ilorazem ρ. Zauważmy, że aby zredukować błąd początkowy do ϵ>0, wystarczy wykonać k=k(ϵ) iteracji, gdzie k spełnia

ρkx0x*ϵ,

czyli

klog(1/ϵ)log(1/x0x*)log(1/ρ).

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 N układu jest dużo mniej istotna (w zadaniach praktycznych -- takich jak jednowymiarowy laplasjan --- jednak często okazuje się, że... ρ zależy od N!).

Zakładając, że koszt jednej iteracji wynosi c=c(N) (c(N) jest tym mniejszy, im mniejsza jest liczba niezerowych elementów macierzy A), złożoność metody jest proporcjonalna do

c(N)log(1/ϵ)log(1/ρ).

Stąd oczywisty wniosek (prawdziwy nie tylko dla metod stacjonarnych), że metody iteracyjne warto stosować zamiast metod bezpośrednich w przypadku, gdy

  • wymiar N układu Ax=b jest "duży", oraz
  • macierz A układu jest "rozrzedzona", tzn. ma stosunkowo niewielką liczbę elementów niezerowych, np. proporcjonalną do N.

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 xk dobiera się w taki sposób, by minimalizowało pewną miarę błędu na podprzestrzeni Kryłowa

Kk=span{r,Ar,,Ak1r},

gdzie r=bAx0 jest residuum na początku iteracji. (Zwróć uwagę, że przestrzeń Kryłowa jest rozpięta przez kolejne wektory \link{sec:eigenvalue}{iteracji prostej}--- 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 A jest symetryczna i dodatnio określona.

Kolejne przybliżenie xk ma minimalizować błąd w normie energetycznej indukowanej przez A,

||xkx||A=(xkx)TA(xkx)

na przestrzeni afinicznej x0+Kk. 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>\displaystyle \rho_0</math> = <math>\displaystyle ||r||_2^2</math>; <math>\displaystyle \beta</math> = 0; k = 1;
while (!stop)
{
	p = r + <math>\displaystyle \beta</math>*p;
	w = A*p;
	<math>\displaystyle \alpha</math> = <math>\displaystyle \rho_{k-1}</math>/<math>\displaystyle p^Tw</math>;
	x = x + <math>\displaystyle \alpha</math>*p;
	r = r - <math>\displaystyle \alpha</math>*w;
	<math>\displaystyle \rho_k</math> = <math>\displaystyle ||r||_2^2</math>;
	<math>\displaystyle \beta</math> = <math>\displaystyle \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ń Kk), a najdroższym jej elementem jest mnożenie macierzy przez wektor.

Twierdzenie O zbieżności CG jako metody bezpośredniej

Niech ARN×N będzie symetryczna i dodatnio określona. Algorytm CG znajdzie dokładne rozwiązanie po co najwyżej N iteracjach.

Powyższe twierdzenie, choć teoretycznie interesujące, ma małą wartość praktyczną z dwóch powodów:

  • dla bardzo dużych N, wykonanie N 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ść xk przestaje się poprawiać.

Dlatego wygodniej potraktować CG jako metodę iteracyjną. Zachodzi bowiem

Twierdzenie Zbieżność CG jako metody iteracyjnej

Po k iteracjach metody CG,

||xkx||A2(cond(A)1cond(A)+1)k||x0x||A,

gdzie cond(A)=||A||2||A1||2.

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 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

Ax=b

z macierzą o niekorzystnych własnościach, do układu

MAx=Mb,

gdzie macierz MA 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 MA 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 MA zbiegała szybko, musimy w jakiś sposób "ścisnąć" spektrum macierzy A w okolice jedności. Taką operację nazywamy ściskaniem (preconditioning), a macierz M --- imadłem.

Aby całość miała sens, macierz ściskająca M 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: M(Ax)),
  • macierz MA powinna mieć znacznie korzystniejsze własności z punktu widzenia używanej metody iteracyjnej.

Kilka ekstremalnych propozycji na macierz imadła to M=I (łatwa w konstrukcji i tania w mnożeniu, ale niestety nic nie polepsza...) oraz M=A1 (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.

Zbieżność metody CG bez żadnego ściskania oraz ściśniętej imadłem opartym na jednej iteracji (blokowej) metody Jacobiego.

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 imadła.

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 podręcznik