Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
ProblemDla danej macierzy An×n należy znaleźć macierz odwrotną wykorzystując
rozkład LU |
Macierz odwrotna (ang. the inverse of a matrix) (A-1) do macierzy A spełnia równanie:
A×A-1 = I = A-1×A gdzie I oznacza macierz jednostkową.
Oznaczmy X = A-1. Wtedy powyższe równanie możemy zapisać jako:
A×X = I |
Niech:
Xn×n =
|
|
Weźmy następnie pierwszą kolumnę
X1 =
|
|
Zgodnie z regułami mnożenia macierzy mamy:
A×
|
|
= |
|
W wyniku otrzymujemy pierwszą kolumnę macierzy jednostkowej, gdyż z założenia
A×
|
|
= |
|
Postępując podobnie dla pozostałych kolumn
X3,
K01: r ← false ; zakładamy porażkę K02: Wykonaj rozkład LU dla macierzy A K03: Jeśli rozkład się nie powiódł, to zakończ K04: Utwórz w X macierz jednostkową K05: Dla i = 1, 2, …, n: ; obliczamy kolejne kolumny wykonuj kroki K06…K07 K06: Przyjmij za wyrazy wolne i-tą kolumnę macierzy X. Rozwiąż układ równań metodą LU. Zapisz wektor niewiadomych w i-tej kolumnie X macierzy odwrotnej K07: Jeśli rozwiązanie się nie powiodło, to zakończ K08: r ← true ; zaznaczamy sukces K09: Zakończ
Powyższy algorytm nie jest nowym algorytmem, wykorzystuje on dwa poprzednio
opisane algorytmy
rozkładu LU oraz
rozwiązywania układu równań liniowych z wykorzystaniem macierzy
L
i
U otrzymanych
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Program wczytuje dane definiujące
macierz
A i wylicza macierz do niej odwrotną. Jeśli
obliczenie nie może zostać wykonane, program wypisuje komunikat
"DZIELNIK ZERO". Dane dla macierzy A są zdefiniowane następująco: Pierwsza liczba określa |
Dane przykładowe (przekopiuj do schowka i wklej do okna konsoli): 3 25 5 1 64 8 1 144 12 1 |
Pascal// Rozkład LU-macierz odwrotna // Data: 20.10.2010 // (C)2020 mgr Jerzy Wałaszek //--------------------------- program luinv; // Typy tablic wierszy i wskaźników type NReal = array of double; MReal = array of NReal; // Przybliżenie zera const eps = 1e-12; // Funkcja dokonuje rozkładu LU macierzy A //---------------------------------------- function ludist(n : integer; A : MReal) : boolean; var i, j, k : integer; begin for k := 0 to n-2 do begin if abs(A[k][k]) < eps then Exit(false); for i := k+1 to n-1 do A[i][k] := A[i][k]/A[k][k]; for i := k+1 to n-1 do for j := k+1 to n-1 do A[i][j] := A[i][j]-A[i][k]*A[k][j]; end; ludist := true; end; // Funkcja wyznacza wektor X // na podstawie A i B //-------------------------- function lusolve(k, n : integer; A, X : MReal) : boolean; var i, j : integer; s : double; begin for i := 1 to n-1 do begin s := 0; for j := 0 to i-1 do s := s+A[i][j]*X[j][k]; X[i][k] := X[i][k]-s; end; if abs(A[n-1][n-1]) < eps then Exit(false); X[n-1][k] := X[n-1][k]/A[n-1][n-1]; for i := n-2 downto 0 do begin s := 0; for j := i+1 to n-1 do s := s+A[i][j]*X[j][k]; if abs(A[i][i]) < eps then Exit(false); X[i][k] := (X[i][k]-s)/A[i][i]; end; lusolve := true; end; // Program główny //--------------- var A, X : MReal; n, i, j : integer; ok : boolean; begin // Odczytujemy wymiar macierzy A read(n); // Tworzymy macierze A i X SetLength(A, n); SetLength(X, n); for i := 0 to n-1 do begin SetLength(A[i], n); SetLength(X[i], n); end; // Odczytujemy dane dla macierzy A for i := 0 to n-1 do for j := 0 to n-1 do read(A[i][j]); // Wykonujemy rozkład LU macierzy A if ludist(n, A) then begin // Tworzymy macierz jednostkową w X for i := 0 to n-1 do begin for j := 0 to n-1 do X[i][j] := 0; X[i][i] := 1; end; // Wyznaczamy kolumny macierzy odwrotnej w X ok := true; for i := 0 to n-1 do if not lusolve(i, n, A, X) then begin ok := false; break; end; end else ok := false; // Jeśli obliczenia się powiodły, wyświetlamy X if ok then begin for i := 0 to n-1 do begin for j := 0 to n-1 do write(X[i][j]:10:5, ' '); writeln; end; end else writeln('DZIELNIK ZERO'); // Usuwamy macierze z pamięci for i := 0 to n-1 do begin SetLength(A[i], 0); SetLength(X[i], 0); end; SetLength(A, 0); SetLength(X, 0); end. |
// Rozkład LU-macierz odwrotna // Data: 20.10.2010 // (C)2020 mgr Jerzy Wałaszek //---------------------------- #include <iostream> #include <iomanip> #include <cmath> using namespace std; const double eps = 1e-12; // Funkcja dokonuje rozkładu // LU macierzy A //-------------------------- bool ludist(int n, double ** A) { int i, j, k; for(k = 0; k < n-1; k++) { if(fabs(A[k][k]) < eps) return false; for(i = k+1; i < n; i++) A[i][k] /= A[k][k]; for(i = k+1; i < n; i++) for(j = k+1; j < n; j++) A[i][j] -= A[i][k]*A[k][j]; } return true; } // Funkcja wyznacza wektor // X na podstawie A i X[i] //------------------------ bool lusolve(int k, int n, double ** A, double ** X) { int i, j; double s; for(i = 1; i < n; i++) { s = 0; for(j = 0; j < i; j++) s += A[i][j]*X[j][k]; X[i][k] -= s; } if(fabs(A[n-1][n-1]) < eps) return false; X[n-1][k] /= A[n-1][n-1]; for(i = n-2; i >= 0; i--) { s = 0; for(j = i+1; j < n; j++) s += A[i][j]*X[j][k]; if(fabs(A[i][i]) < eps) return false; X[i][k] = (X[i][k]-s)/A[i][i]; } return true; } // Program główny //--------------- int main() { double **A, **X; int n, i, j; bool ok; cout << setprecision(5) << fixed; // Odczytujemy wymiar macierzy A cin >> n; // Tworzymy macierze A i X A = new double * [n]; X = new double * [n]; for(i = 0; i < n; i++) { A[i] = new double[n]; X[i] = new double[n]; } // Odczytujemy dane dla // macierzy A for(i = 0; i < n; i++) for(j = 0; j < n; j++) cin >> A[i][j]; // Wykonujemy rozkład LU // macierzy A if(ludist(n, A)) { // Tworzymy macierz // jednostkową w X for(i = 0; i < n; i++) { for(j = 0; j < n; j++) X[i][j] = 0; X[i][i] = 1; } // Wyznaczamy kolumny macierzy // odwrotnej w X ok = true; for(i = 0; i < n; i++) if(!lusolve(i, n, A, X)) { ok = false; break; } } else ok = false; // Jeśli obliczenia się powiodły, // wyświetlamy X if(ok) { for(i = 0; i < n; i++) { for(j = 0; j < n; j++) cout << setw(10) << X[i][j] << " "; cout << endl; } } else cout << "DZIELNIK ZERO\n"; // Usuwamy macierze z pamięci for(i = 0; i < n; i++) { delete [] A[i]; delete [] X[i]; } delete [] A; delete [] X; return 0; } |
Basic' Rozkład LU-macierz odwrotna ' Data: 20.10.2010 ' (C)2020 mgr Jerzy Wałaszek '---------------------------- Const eps As Double = 1e-12 ' Funkcja dokonuje rozkładu ' LU macierzy A '-------------------------- Function ludist(n As Integer, _ A As Double Ptr Ptr) _ As Integer Dim As Integer i, j, k For k = 0 To n-2 If Abs(A[k][k]) < eps Then _ Return 0 For i = k+1 To n-1 A[i][k] /= A[k][k] Next For i = k+1 To n-1 For j = k+1 To n-1 A[i][j] -= A[i][k]*A[k][j] Next Next Next ludist = 1 End Function ' Funkcja wyznacza wektor X ' na podstawie A i X [i] '-------------------------- Function lusolve(k As Integer, _ n As Integer, _ A As Double Ptr Ptr, _ X As Double Ptr Ptr) _ As Integer Dim As Integer i, j Dim As Double s For i = 1 To n-1 s = 0 For j = 0 To i-1 s += A[i][j]*X[j][k] Next X[i][k] -= s Next If Abs(A[n-1][n-1]) < eps Then _ Return 0 X[n-1][k] /= A[n-1][n-1] For i = n-2 To 0 Step -1 s = 0 For j = i+1 To n-1 s += A[i][j]*X[j][k] Next If Abs(A[i][i]) < eps Then _ Return 0 X[i][k] = (X[i][k]-s)/A[i][i] Next lusolve = 1 End Function Dim As Double Ptr Ptr A, X Dim As Integer i, j, ok, n Open Cons For Input As #1 ' Odczytujemy wymiar macierzy A Input #1, n ' Tworzymy macierze A i X A = New Double Ptr[n] X = New Double Ptr[n] For i = 0 To n-1 A[i] = New Double[n] X[i] = New Double[n] Next ' Odczytujemy dane dla macierzy A For i = 0 To n-1 For j = 0 To n-1 Input #1, A[i][j] Next Next Close #1 ' Wykonujemy rozkład LU macierzy A If ludist(n, A) = 1 Then ' Tworzymy macierz jednostkową w X For i = 0 To n-1 For j = 0 To n-1 X[i][j] = 0 Next X[i][i] = 1 Next ' Wyznaczamy kolumny macierzy ' odwrotnej w X ok = 1 For i = 0 To n-1 If lusolve(i, n, A, X) = 0 Then ok = 0 Exit For End If Next Else ok = 0 End If ' Jeśli obliczenia się powiodły, ' wyświetlamy X If ok = 1 Then For i = 0 To n-1 For j = 0 To n-1 Print Using "####.##### ";X[i][j]; Next Print Next Else Print "DZIELNIK ZERO" End If ' Usuwamy macierze dynamiczne For i = 0 To n-1 Delete [] A[i] Delete [] X[i] Next Delete [] A Delete [] X End |
Python
(dodatek)# Rozkład LU-macierz odwrotna # Data: 28.04.2024 # (C)2024 mgr Jerzy Wałaszek # ----------------------------- eps = 1e-12 # Funkcja dokonuje rozkładu LU # macierzy A #----------------------------- def ludist(a): n = len(a) for k in range(n-1): if abs(a[k][k]) < eps: return False for i in range(k+1, n): a[i][k] /= a[k][k] for i in range(k+1, n): for j in range(k+1, n): a[i][j] -= a[i][k]*a[k][j] return True # Funkcja wyznacza wektor X # na podstawie A i X[i] #-------------------------- def lusolve(k, a, x): n = len(a) for i in range(1, n): s = 0.0 for j in range(i): s += a[i][j]*x[j][k] x[i][k] -= s if abs(a[n-1][n-1]) < eps: return False x[n-1][k] /= a[n-1][n-1] for i in reversed(range(n-1)): s = 0.0 for j in range(i+1, n): s += a[i][j]*x[j][k] if abs(a[i][i]) < eps: return False x[i][k] = (x[i][k]-s)/a[i][i] return True # Program główny #--------------- # Odczytujemy wymiar macierzy A n = int(input()) # Tworzymy macierze A i X a = [] x = [] # Odczytujemy dane dla macierzy A for i in range(n): s = input().split() arr = [float(s[j]) for j in range(n)] a.append(arr) x.append([0]*n) # Wykonujemy rozkład LU macierzy A if ludist(a): # Tworzymy macierz jednostkową w X for i in range(n): x[i][i] = 1 # Wyznaczamy kolumny macierzy # odwrotnej w X ok = True for i in range(n): if not lusolve(i, a, x): ok = False break else: ok = False # Jeśli obliczenia się powiodły, # wyświetlamy X if ok: for i in range(n): for j in range(n): print("%10.5f" % x[i][j], end="") print() else: print("DZIELNIK ZERO") |
Wynik: |
3 25 5 1 64 8 1 144 12 1 0.04762 -0.08333 0.03571 -0.95238 1.41667 -0.46429 4.57143 -5.00000 1.42857 |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.