MN04LAB: 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 1: Linia 1:


==Rozwiązywanie układów równań liniowych==
<!--
Konwertowane  z pliku LaTeX przez latex2mediawiki, zob. http://www.ii.uj.edu.pl/&nbsp;pawlik1/latex2mediawiki.php
-->
=Ćwiczenia: rozwiązywanie układów równań liniowych=


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<span  style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie</span>  
<span  style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie: Mnożyć przez odwrotność to nie zawsze to samo...</span>  
<div class="exercise">
<div class="exercise">


W Octave układ równań <math>\displaystyle Ax=b</math> rozwiązujemy korzystając z "operatora
W Octave układ równań <math>\displaystyle Ax=b</math> rozwiązujemy korzystając z "operatora
rozwiązywania równania", tzn.
rozwiązywania równania"
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
   
   
x <nowiki>=</nowiki> A \ b;
x = A \ b;
</pre></div>
</pre></div>
   
   
Linia 18: Linia 22:
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
   
   
x <nowiki>=</nowiki> inv(A)*b;
x = inv(A)*b;
</pre></div>
</pre></div>
   
   
Linia 35: Linia 39:
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
   
   
N <nowiki>=</nowiki> 400; A <nowiki>=</nowiki> rand(N,N);x <nowiki>=</nowiki> rand(N,1); b <nowiki>=</nowiki> A*x;  
N = 400; A = rand(N,N);x = rand(N,1); b = A*x;  
tic; X <nowiki>=</nowiki> A \ b; tX <nowiki>=</nowiki> toc;  
tic; X = A \ b; tX = toc;  
tic; Y <nowiki>=</nowiki> inv(A)*b; tY <nowiki>=</nowiki> toc;
tic; Y = inv(A)*b; tY = toc;
[norm(X-x)/norm(x),  norm(Y-x)/norm(x); tX, tY]  
[norm(X-x)/norm(x),  norm(Y-x)/norm(x); tX, tY]  
</pre></div>
</pre></div>
Linia 43: Linia 47:
<div class="output" style="background-color:#e0e8e8; padding:1em"><pre>
<div class="output" style="background-color:#e0e8e8; padding:1em"><pre>
   
   
ans <nowiki>=</nowiki>
ans =
   1.9861e-13  2.8687e-13
   1.9861e-13  2.8687e-13
   2.3644e-01  4.0609e-01
   2.3644e-01  4.0609e-01
Linia 50: Linia 54:
Wyszło (z grubsza) dwa razy szybciej i dwa razy dokładniej.
Wyszło (z grubsza) dwa razy szybciej i dwa razy dokładniej.


</div></div></div>
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<span  style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie: Wybór elementu głównego jest naprawdę ważny!</span>
<div class="exercise">
Rozwiąż prosty układ równań
<center><math>\displaystyle \aligned 10^{-18} x_1 + x_2 &= 1,\\
x_1 + 2x_2 &= 4,
\endaligned</math></center>
czterema sposobami:
* na kartce papieru (dokładnie!)
* w komputerze, w arytmetyce podwójnej precyzji, korzystając z rozkładu LU <strong>bez wyboru elementu głównego</strong>
* jak poprzednio, ale <strong>z wyborem elementu głównego w kolumnie</strong>
* w LAPACKu lub Octave.
Porównaj uzyskane rozwiązania i wyciągnij wnioski.
</div></div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> 
Rozwiązanie uzyskane bez wyboru elementu głównego jest bardzo mało precyzyjne <math>\displaystyle x_1</math> jest obarczone bardzo duzym błędem! Prosta analiza poazuje,  że winę za to ponosi bardzo wielki współczynnik w macierzy <math>\displaystyle L</math>. Tak nie jest, gdy stosujemy wybór elementu: elementy <math>\displaystyle L</math> są zawsze mniejsze od 1. Dlatego inne rozwiązania numeryczne dają w przypadku naszej macierzy wynik, będący bardzo dobrym przybliżeniem wyniku dokładnego. ''A propos:'' Octave korzysta z <code>DGESV</code> LAPACKa, a <code>DGESV</code> korzysta z wyboru w kolumnie...
</div></div></div>
</div></div></div>


Linia 65: Linia 92:


Przetestuj tę funkcję na kilku macierzach i porównaj czas jego działania z czasem
Przetestuj tę funkcję na kilku macierzach i porównaj czas jego działania z czasem
wykonania operacji <code>x <nowiki>=</nowiki> A\b</code>.
wykonania operacji <code>x = A\b</code>.


Spróbuj zastosować swój algorytm do kilku specjalnych macierzy:
Spróbuj zastosować swój algorytm do kilku specjalnych macierzy:
Linia 78: Linia 105:
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
   
   
function [L,U] <nowiki>=</nowiki> lufa(A)
function [L,U] = lufa(A)
# Na początku warto dodać trochę sprawdzania danych: czy A jest kwadratowa? a w ogóle,
# Na początku warto dodać trochę sprawdzania danych: czy A jest kwadratowa? a w ogóle,
# czy jest macierzą? te linie pozostawiamy inwencji Czytelnika
# czy jest macierzą? te linie pozostawiamy inwencji Czytelnika


N <nowiki>=</nowiki> size(A,1);
N = size(A,1);
for k<nowiki>=</nowiki>1:N-1
for k=1:N-1
if (A(k,k) <nowiki>=</nowiki><nowiki>=</nowiki> 0.0)
if (A(k,k) == 0.0)
return;
return;
end
end
for i<nowiki>=</nowiki>k+1:N #wyznaczenie <math>\displaystyle k</math>-tej kolumny <math>\displaystyle L</math>
for i=k+1:N #wyznaczenie <math>\displaystyle k</math>-tej kolumny <math>\displaystyle L</math>
A(i,k) <nowiki>=</nowiki> A(i,k)/A(k,k);
A(i,k) = A(i,k)/A(k,k);
end
end
for j<nowiki>=</nowiki>k+1:N #modyfikacja podmacierzy <math>\displaystyle A_{22} = A_{22} - l_{21}u_{12}^T</math>  
for j=k+1:N #modyfikacja podmacierzy <math>\displaystyle A_{22} = A_{22} - l_{21}u_{12}^T</math>  
for i<nowiki>=</nowiki>k+1:N  
for i=k+1:N  
A(i,j) -<nowiki>=</nowiki> A(i,k)*A(k,j);
A(i,j) -= A(i,k)*A(k,j);
end
end
end
end
end
end
L <nowiki>=</nowiki> tril(A,-1) + eye(N);
L = tril(A,-1) + eye(N);
U <nowiki>=</nowiki> triu(A);
U = triu(A);
end
end
</pre></div>
</pre></div>
Linia 108: Linia 135:
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
   
   
function [L,U] <nowiki>=</nowiki> lufb(A)
function [L,U] = lufb(A)
# Na początku warto dodać trochę sprawdzania danych: czy A jest kwadratowa? a w ogóle,
# Na początku warto dodać trochę sprawdzania danych: czy A jest kwadratowa? a w ogóle,
# czy jest macierzą? te linie pozostawiamy inwencji Czytelnika
# czy jest macierzą? te linie pozostawiamy inwencji Czytelnika


N <nowiki>=</nowiki> size(A,1);
N = size(A,1);
for k<nowiki>=</nowiki>1:N-1
for k=1:N-1
if (A(k,k) <nowiki>=</nowiki><nowiki>=</nowiki> 0.0)
if (A(k,k) == 0.0)
return;
return;
end
end
#wyznaczenie <math>\displaystyle k</math>-tej kolumny <math>\displaystyle L</math>
#wyznaczenie <math>\displaystyle k</math>-tej kolumny <math>\displaystyle L</math>
A(k+1:N,k) <nowiki>=</nowiki> A(k+1:N,k)/A(k,k);
A(k+1:N,k) = A(k+1:N,k)/A(k,k);
#modyfikacja podmacierzy <math>\displaystyle A_{22} = A_{22} - l_{21}u_{12}^T</math>  
#modyfikacja podmacierzy <math>\displaystyle A_{22} = A_{22} - l_{21}u_{12}^T</math>  
A(k+1:N,k+1:N) -<nowiki>=</nowiki> A(k+1:N,k)*A(k,k+1:N);
A(k+1:N,k+1:N) -= A(k+1:N,k)*A(k,k+1:N);
end
end
L <nowiki>=</nowiki> tril(A,-1) + eye(N);
L = tril(A,-1) + eye(N);
U <nowiki>=</nowiki> triu(A);
U = triu(A);
end
end
</pre></div>
</pre></div>
Linia 129: Linia 156:
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
  [Kod testujący lufa(0 i lufb()]
  [Kod testujący lufa(0 i lufb()]
N <nowiki>=</nowiki> 100;  
N = 100;  
A <nowiki>=</nowiki> rand(N) + 1000*eye(N);
A = rand(N) + 1000*eye(N);


format short e;
format short e;


t <nowiki>=</nowiki> ta <nowiki>=</nowiki> tb <nowiki>=</nowiki> Inf;
t = ta = tb = Inf;


K <nowiki>=</nowiki> 5;
K = 5;


for i <nowiki>=</nowiki> 0:K
for i = 0:K
tic; [L, U] <nowiki>=</nowiki> lu(A); t <nowiki>=</nowiki> min(t,toc);
tic; [L, U] = lu(A); t = min(t,toc);
tic; [La, Ua] <nowiki>=</nowiki> lufa(A); ta <nowiki>=</nowiki> min(ta,toc);
tic; [La, Ua] = lufa(A); ta = min(ta,toc);
tic; [Lb, Ub] <nowiki>=</nowiki> lufb(A); tb <nowiki>=</nowiki> min(tb,toc);
tic; [Lb, Ub] = lufb(A); tb = min(tb,toc);
end
end


Linia 153: Linia 180:


{| border=1
{| border=1
|+ <span style="font-variant:small-caps">Uzupelnij tytul</span>
|+ <span style="font-variant:small-caps"> </span>
|-  
|-  
| Implementacja  ||  lu (oryginalne)  ||  lufa  ||  lufb
| Implementacja  ||  lu (oryginalne)  ||  lufa  ||  lufb
Linia 182: Linia 209:
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
   
   
function x <nowiki>=</nowiki> sol(L,U,b)
function x = sol(L,U,b)
x <nowiki>=</nowiki> U \ ( L \ b);
x = U \ ( L \ b);
end
end
</pre></div>
</pre></div>
Linia 195: Linia 222:


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<span  style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie</span>  
<span  style="display: block; background-color:#fefeee; border-bottom: 1px solid #E5E5E5; line-height: 1.1em; padding-bottom: 0.2em; font-variant:small-caps; color:#1A6ABF;">Ćwiczenie: Czy Twoje programy działają <strong>naprawdę</strong> szybko?</span>  
<div class="exercise">
<div class="exercise">


Zrób zadanie poprzednie w C i porównaj z procedurą biblioteczną LAPACKa
Zrób zadanie poprzednie programując, niczym Zosia-Samosia, wszystko od początku do końca w czystym C. Porównaj czasy działania Twojego programu i programu wywołującego po prostu procedurę biblioteczną LAPACKa
<code>DGESV</code>, najlepiej wspartą dobrze podrasowanymi BLASami.
<code>DGESV</code>, najlepiej wspartą dobrze podrasowanymi BLASami.
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none">
<div style="font-size:smaller; background-color:#efe"> To zadanie to wyzwanie! </div>
</div></div>
</div></div>
</div></div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"><div style="margin-left:1em"> 
No tak, namawiamy Cię do zmierzenia się z LAPACKiem i ATLASem....
Prościutki program --- po prostu tłumaczącu algorytm z wykładu bezpośrednio
na C --- u nas spisał
się, dla macierzy wymiaru <math>\displaystyle N=1\ldots 1024</math>, następująco:
[[Image:MNdegsvtiming.png|thumb|450px|center|Prosty solver w C kontra LAPACK i LAPACK z ATLASem.
Zwróć uwagę na piki zwykłego kodu dla <math>\displaystyle N</math> będących potęgami dwójki]]
[[Image:MNdegsvtiminglogscale.png|thumb|450px|center|Skala logarytmiczna pozwala lepiej ocenić
różnice pomiędzy czasami wykonania. Prosty program w C jest około dziesięć razy
wolniejszy od kodu korzystającego z LAPACKa i około 50 razy wolniejszy od kodu
korzystającego z LAPACKa i ATLASa.]]
</div></div></div>


<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
Linia 217: Linia 265:


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none">
<div style="font-size:smaller; background-color:#efe"> Wystarczy tylko ''jeden raz'' wyznaczyć rozkład LU macierzy <math>\displaystyle A</math> </div>
<div style="font-size:smaller; background-color:#efe"> Wystarczy tylko <strong>jeden raz</strong> wyznaczyć rozkład LU macierzy <math>\displaystyle A</math> </div>
</div></div>
</div></div>


Linia 235: Linia 283:


Rozwiązanie każdego z układów <math>\displaystyle LY = B</math> i <math>\displaystyle UX = Y</math> można przyspieszyć, tworząc
Rozwiązanie każdego z układów <math>\displaystyle LY = B</math> i <math>\displaystyle UX = Y</math> można przyspieszyć, tworząc
warianty blokowe znanych algorytmów. Zaimplementowano je w LAPACKu, w tandemie
warianty algorytmów podstawienia w przód i w tył, operujące od razu na wszystkich kolumnach macierzy <math>\displaystyle B</math>. Zaimplementowano je w LAPACKu, w tandemie
funkcji <code>DGETRF</code> (rozkład) i <code>DGETRS</code> (rozwiązanie) oraz w
funkcji <code>DGETRF</code> (rozkład) i <code>DGETRS</code> (rozwiązanie) oraz w
<code>DGESV</code>, łączącej funkcjonalność obu.
<code>DGESV</code>, łączącej funkcjonalność obu.
Linia 246: Linia 294:
Ważnym przykładem macierzy  
Ważnym przykładem macierzy  
szczególnej postaci są macierze symetryczne i dodatnio określone.  
szczególnej postaci są macierze symetryczne i dodatnio określone.  
Są to macierze spełniające <math>\displaystyle A=A^T</math> oraz
Są to macierze spełniające warunki:


<center><math>\displaystyle x^T A x\,>\,0,\qquad\forall x\ne 0.
<center><math>\displaystyle A=A^T \qquad  \mbox{oraz}  \qquad x^T A x\,>\,0,\quad\forall x\ne 0.
</math></center>
</math></center>


Linia 262: Linia 310:
trójkątną dolną z jedynkami na przekątnej, a <math>\displaystyle D</math> jest macierzą  
trójkątną dolną z jedynkami na przekątnej, a <math>\displaystyle D</math> jest macierzą  
diagonalną z dodatnimi elementami na diagonali. Opracuj taki algorytm. W jego
diagonalną z dodatnimi elementami na diagonali. Opracuj taki algorytm. W jego
implementacji możesz porównywać się z procedurą LAPACKa <code>DPOSV</code>
implementacji możesz porównywać się z procedurą LAPACKa <code>DPOSV</code>.
Inny wariant tego samego
Inny wariant tego samego
rozkładu to tak zwany rozkład Cholesky'ego--Banachiewicza, w którym przy tych
rozkładu to tak zwany rozkład Cholesky'ego--Banachiewicza, w którym przy tych
Linia 320: Linia 368:
macierze <math>\displaystyle A^{(k)}</math> są symetryczne. Pozwala to zmniejszyć --- w stosunku do
macierze <math>\displaystyle A^{(k)}</math> są symetryczne. Pozwala to zmniejszyć --- w stosunku do
rozkładu LU --- koszt  
rozkładu LU --- koszt  
obliczeniowy o połowę do <math>\displaystyle 2n^3/3</math> operacji arytmetycznych i zmieścić czynniki
obliczeniowy o połowę, do <math>\displaystyle 2n^3/3</math> operacji arytmetycznych i zmieścić czynniki
rozkładu w pamięci przeznaczonej na przechowywanie istotnych elementów <math>\displaystyle A</math>
rozkładu w pamięci przeznaczonej na przechowywanie istotnych elementów <math>\displaystyle A</math>
(czyli w dolnym trójkącie macierzy).  
(czyli w dolnym trójkącie macierzy).  
Linia 360: Linia 408:
<div class="output" style="background-color:#e0e8e8; padding:1em"><pre>
<div class="output" style="background-color:#e0e8e8; padding:1em"><pre>
   
   
octave:26> A<nowiki>=</nowiki>rand(100);
octave:26> A=rand(100);
octave:27> det(A)
octave:27> det(A)
ans <nowiki>=</nowiki> -7.5240e+24
ans = -7.5240e+24
octave:28> det(10*A)
octave:28> det(10*A)
ans <nowiki>=</nowiki> -7.5240e+124
ans = -7.5240e+124
octave:29> det(100*A)
octave:29> det(100*A)
ans <nowiki>=</nowiki> -7.5240e+224
ans = -7.5240e+224
octave:30> det(1000*A)
octave:30> det(1000*A)
ans <nowiki>=</nowiki> -Inf
ans = -Inf
</pre></div>
</pre></div>
   
   
Linia 376: Linia 424:
   
   
octave:32> det(rand(100))
octave:32> det(rand(100))
ans <nowiki>=</nowiki> 4.3751e+25
ans =  4.3751e+25
octave:33> det(rand(400))
octave:33> det(rand(400))
ans <nowiki>=</nowiki> -3.0348e+218
ans = -3.0348e+218
octave:34> det(rand(800))
octave:34> det(rand(800))
ans <nowiki>=</nowiki> -Inf
ans = -Inf
</pre></div>
</pre></div>
   
   

Wersja z 16:54, 2 wrz 2006


Ćwiczenia: rozwiązywanie układów równań liniowych

Ćwiczenie: Mnożyć przez odwrotność to nie zawsze to samo...

W Octave układ równań Ax=b rozwiązujemy korzystając z "operatora rozwiązywania równania"

 
x = A \ b;

W tym celu Octave oczywiście wewenętrznie wykorzystuje funkcję LAPACKa DGESV. Ale w Octave jest także funkcja inv, wyznaczająca macierz odwrotną, więc niektóre (nie najlepsze, oględnie mówiąc) podręczniki zalecają

 
x = inv(A)*b;

Przedyskutuj, które podejście jest lepsze i dlaczego. Przeprowadź eksperymenty numeryczne weryfikujące Twoją tezę.

Rozwiązanie

Ćwiczenie: Wybór elementu głównego jest naprawdę ważny!

Rozwiąż prosty układ równań

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned 10^{-18} x_1 + x_2 &= 1,\\ x_1 + 2x_2 &= 4, \endaligned}

czterema sposobami:

  • na kartce papieru (dokładnie!)
  • w komputerze, w arytmetyce podwójnej precyzji, korzystając z rozkładu LU bez wyboru elementu głównego
  • jak poprzednio, ale z wyborem elementu głównego w kolumnie
  • w LAPACKu lub Octave.

Porównaj uzyskane rozwiązania i wyciągnij wnioski.

Rozwiązanie

Ćwiczenie

Zapisz w Octave algorytm rozkładu LU macierzy (bez wyboru elementu głównego) działający in situ.

Wskazówka

Wykorzystaj go do napisania funkcji, która rozwiąże układ równań Ax=b.

Przetestuj tę funkcję na kilku macierzach i porównaj czas jego działania z czasem wykonania operacji x = A\b.

Spróbuj zastosować swój algorytm do kilku specjalnych macierzy:

  • Hilberta dużego wymiaru
  • diagonalnej z jednym elementem bardzo małym (a nawet równym zero)
Rozwiązanie

Ćwiczenie: Czy Twoje programy działają naprawdę szybko?

Zrób zadanie poprzednie programując, niczym Zosia-Samosia, wszystko od początku do końca w czystym C. Porównaj czasy działania Twojego programu i programu wywołującego po prostu procedurę biblioteczną LAPACKa DGESV, najlepiej wspartą dobrze podrasowanymi BLASami.

Wskazówka
Rozwiązanie

Ćwiczenie: Układy równań z wieloma prawymi stronami

Podaj sposób taniego wyznaczenia rozwiązania sekwencji k<N układów równań z tą samą macierzą ARN×N i różnymi prawymi stronami:

Axi=bi,i=1,,k.

Układy równań z tą samą macierzą, ale ze zmieniającą się prawą stroną równania powstają często przy rozwiązywaniu, np. równań różniczkowych cząstkowych, gdzie prawa strona układu odpowiada zmieniającym się warunkom brzegowym.

Wskazówka
Rozwiązanie

Ćwiczenie: Metoda Cholesky'ego

Ważnym przykładem macierzy szczególnej postaci są macierze symetryczne i dodatnio określone. Są to macierze spełniające warunki:

A=ATorazxTAx>0,x0.

Dla takich macierzy można nieco zmniejszyć koszt kombinatoryczny i zużycie pamięci przeprowadzając trochę inny rozkład na macierze trójkątne: tak, aby otrzymać rozkład

A=LDLT

zamiast PA=LU, przy czym L jest tu jak zwykle macierzą trójkątną dolną z jedynkami na przekątnej, a D jest macierzą diagonalną z dodatnimi elementami na diagonali. Opracuj taki algorytm. W jego implementacji możesz porównywać się z procedurą LAPACKa DPOSV. Inny wariant tego samego rozkładu to tak zwany rozkład Cholesky'ego--Banachiewicza, w którym przy tych samych założeniach na A, szukamy rozkładu wykorzystującego tylko jedną macierz trójkątną dolną:

A=L~L~T,

(oczywiście tym razem nie żądamy, aby L~ miała na diagonali jedynki). Jaka jest relacja między rozkładem LDLT a L~L~T?

Rozwiązanie

Ćwiczenie: Obliczanie wyznacznika macierzy

Bardzo rzadko w praktyce numerycznej zdarza się potrzeba obliczenia wartości wyznacznika macierzy ARN×N. Zaproponuj metodę obliczania det(A) oraz wskaż, jakiego rodzaju problemy numeryczne możesz napotkać.

Rozwiązanie