|
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 |
©2026 mgr Jerzy Wałaszek
|
| SPIS TREŚCI REMANENT |
|
| Podrozdziały |
Do rozwiązania układu równań można wykorzystać rozkład LU. Postępujemy następująco:
Mamy dany układ równań n liniowych z n niewiadomymi:

Zapiszmy ten układ w postaci macierzowej:

Załóżmy, iż dokonaliśmy rozkładu LU macierzy współczynników A:

Nasze równanie możemy teraz zapisać jako:

Ponieważ mnożenie macierzy jest łączne, to:

Robimy podstawienie:

Otrzymujemy:

Rozwiązanie układu jest dwuetapowe. Najpierw wyznaczamy macierz Y z ostatniego równania, a następnie wyznaczamy macierz X z podstawienia:

Okazuje się, że ze względu na postać macierzy L i U rozwiązanie takiego układu jest bardzo proste. Rozpiszmy pierwsze równanie macierzowe:


Z pierwszego równania w układzie od razu dostajemy wartość pierwszej niewiadomej y:

Wstawiając ją do równania drugiego wyliczamy drugą niewiadomą y:

Wyliczone wartości niewiadomych y wstawiamy do równania trzeciego i otrzymujemy:

Metoda ta nosi nazwę podstawiania w przód (ang. forward-substitution). Uogólniając, widzimy wyraźnie, że niewiadomą yi wyliczamy z poprzednio wyliczonych niewiadomych y1, y2,..., yi - 1. Wzór jest następujący:

Gdy znajdziemy wektor Y, to przechodzimy do drugiego równania macierzowego:

Rozpiszmy je:


Tutaj mamy sytuację odwrotną do poprzedniej. Rozwiązywanie rozpoczynamy od ostatniego równania:

Wyliczoną wartość xn wstawiamy do równania przedostatniego:

Niewiadome x wyliczamy od ostatniej do pierwszej. Taka metoda postępowania nosi nazwę podstawiania wstecz (ang. back-substitution). Wzór uogólniony ma postać:

Rozwiązanie układu istnieje, jeśli wszystkie elementy przekątnej głównej macierzy U są niezerowe. Warunek ten jest sprawdzany w algorytmie rozkładu LU.
Zwróć uwagę, iż macierze X i Y mogą być tą samą macierzą X, ponieważ w obu fazach wyliczania niewiadomych elementy y nie kolidują z elementami x.
Metoda rozwiązywania układu równań liniowych z wykorzystaniem rozkładu LU jest następująca:
| ε | – | dokładność przyrównania do zera |
| n | – | stopień macierzy |
| A | – | macierz n × n współczynników |
| B | – | macierz n × 1 z wyrazami wolnymi |
| X | – | macierz n × 1 dla rozwiązań |
| true/false | – | określa, czy operacja powiodła się, czy nie. |
| X | – | macierz n × 1 z wartościami niewiadomych, jeśli wynikiem jest true. |
| i,j,k | – | indeksy |
| s | – | suma |
| W | – | macierz 1 × n z numerami wierszy macierzy A. |
| maxw | – | numer wiersza z elementem maksymalnym |
| maxe | – | moduł elementu maksymalnego |
| akk | – | element macierzy A leżący na jej przekątnej po piwotowaniu |
| K01: | Dla i = 0,1,...,n – 1: wykonuj W[i] ← i |
ustawiamy wektor wierszowy |
| K02: | Dla k = 0,1,...,n – 1: wykonuj kroki K03...K12 |
rozpoczynamy rozkład LU |
| K03: | maxw ← k | wiersz z elementem maksymalnym |
| K04: | maxe ← |A[W[k],k]| | moduł elementu maksymalnego |
| K05: | Dla i = k + 1, k +
2,..., n – 1: wykonuj krok K07 |
szukamy elementu większego |
| K06: |
Jeśli |A[W[i],k]| > maxe, to maxw ← i maxe ← |A[W[i],k]| |
|
| K07: | Jeśli maxe ≤ ε, to zakończ z wynikiem false |
macierz jest zdegenerowana |
| K08: | Jeśli maxw ≠ W[k], to W[k] ← W[maxw] |
znaleziono element maksymalny |
| K09: | akk ← A[W[k],k] | rozkład LU |
| K10: | Dla i = k + 1, k +
2,...,n – 1: wykonuj: A[W[i],k] ← A[W[i],k] / akk |
normalizacja kolumny |
| K11: | Dla i = k + 1,k +
2,...,n – 1: wykonuj krok K12 |
modyfikujemy podmacierz |
| K12: | Dla j = k + 1,k +
2,...,n – 1: wykonuj: A [W[i],j] ← A[W[i],j] - A[W[i],k] × A[W[k],j] |
|
| K13: | X[0] ← B[W[0]] | w X tworzymy macierz Y |
| K14: | Dla i = 1,...,n – 1: wykonuj kroki K15...K17 |
stosujemy podstawienia w przód |
| K15: | s ← B[W[i]] | |
| K16: | Dla j = 0,...,i –
1: wykonuj s ← s – A[W[i],j] × X[j] |
|
| K17: | X[i] ← s | |
| K18: | X[n – 1] ← X[n – 1] / A[W[n – 1],n – 1] | w X wyliczamy niewiadome x |
| K19: | Dla i = n – 2,...,0: wykonuj kroki K20...K22 |
stosujemy podstawienia wstecz |
| K20: | s ← X[i] | |
| K21: | Dla j = n –
1,...,i + 1: wykonuj s ← s – A[W[i],j] × X[j] |
|
| K22: | X[i] ← s / A[W[i],i] | |
| K23: | Zakończ z wynikiem true |
Poniższy program jest przykładową realizacją powyższego algorytmu. W programie łączymy macierz współczynników A z macierzą wyrazów wolnych B w jedną macierz AB o rozmiarze n × n + 1. Dane wejściowe do programu są następujące:
Pierwsza liczba określa liczbę równań i niewiadomych n. Następne liczby określają współczynniki przy niewiadomych oraz wyrazy wolne. Należy wprowadzać je wierszami. Pierwsze n liczb w każdym wierszu to kolejne współczynniki przy niewiadomych. Po tych n współczynnikach należy wprowadzić wyraz wolny. Wierszy takich musi być n.Układ równań:

|
Dane wejściowe: 5 -1 2 -3 3 5 56 8 0 7 4 -1 62 -3 4 -3 2 -2 -10 8 -3 -2 1 2 14 -2 -1 -6 9 0 28 |
C++// Rozkład LU w równaniach
// (C)2019 mgr Jerzy Wałaszek
// Metody numeryczne 0069
//---------------------------
#include <iostream>
#include <windows.h>
#include <iomanip>
#include <cmath>
using namespace std;
const double EPS = 0.000000001;
// Funkcja rozwiązuje układ równań
// metodą rozkładu LU
// n - stopień macierzy
// AB - wskaźnik macierzy n x (n + 1)
// X - wskaźnik macierzy rozwiązań n x 1
// Jeśli układ został rozwiązany,
// to wynikiem jest true.
// Inaczej wynikiem jest false.
//--------------------------------------
bool LUeq(int n,
double ** AB,
double * X)
{
int i, j, k, * W, maxw;
double s, akk, maxe;
// Tworzymy wektor wierszowy
W = new int [n];
// Inicjujemy wektor wierszowy
// numerami wierszy
for(i = 0; i < n; i++)
W[i] = i;
// Rozkład LU
for(k = 0; k < n; k++)
{
// numer wiersza
// z elementem max
maxw = k;
maxe = fabs(AB[W[k]][k]);
// Szukamy elementu max
for(i = k + 1; i < n; i++)
if(fabs(AB[W[i]][k]) > maxe)
{
maxw = i;
maxe = fabs(AB[W[i]][k]);
}
// Jeśli max jest zero,
// to macierz jest
// zdegenerowana
if(maxe <= EPS)
{
delete [] W;
return false;
}
// Jeśli max nie leży
// na przekątnej,
// zamieniamy wiersze
if(maxw != k)
swap(W[k],W[maxw]);
// Dzielnik
akk = AB[W[k]][k];
// Normalizujemy kolumnę
for(i = k + 1; i < n; i++)
AB[W[i]][k] /= akk;
// Modyfikujemy podmacierz
for(i = k + 1; i < n; i++)
for(j = k + 1; j < n; j++)
AB[W[i]][j] -= AB[W[i]][k] *
AB[W[k]][j];
}
// Teraz rozwiązujemy układ
// równań w dwóch etapach
// Najpierw w X wyznaczamy
// macierz Y stosując
// podstawienia w przód
X[0] = AB[W[0]][n];
for(i = 1; i < n; i++)
{
s = AB[W[i]][n];
for(j = 0; j < i; j++)
s -= AB[W[i]][j] * X[j];
X[i] = s;
}
// Wyznaczamy X stosując
// podstawienia wstecz
X[n - 1] /= AB[W[n - 1]][n - 1];
for(i = n - 2; i >= 0; i--)
{
s = X[i];
for(j = n - 1; j > i; j--)
s -= AB[W[i]][j] * X[j];
X[i] = s / AB[W[i]][i];
}
delete [] W;
return true;
}
// Program główny
//---------------
int main()
{
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
cout << setprecision(5)
<< fixed;
cout <<
"Rozwiązywanie układu równań "
"liniowych metodą rozkładu LU\n"
"----------------------------"
"----------------------------\n\n"
"Wpisz dane wejściowe:\n\n";
// Liczba równań w układzie
int n;
cin >> n;
int i,j;
// Tworzymy dynamicznie
// potrzebne macierze
// Macierz współczynników
// przy niewiadomych x
// oraz wyrazów wolnych
double ** AB;
// Macierz niewiadomych
double * X;
AB = new double * [n];
X = new double [n];
for(i = 0; i < n; i ++)
AB[i] = new double [n + 1];
// Odczytujemy dane
// układu równań
for(i = 0; i < n; i++)
for(j = 0; j <= n; j++)
cin >> AB[i][j];
cout << endl;
// Rozwiązujemy układ równań
if(LUeq(n,AB,X))
{
for(i = 0; i < n; i++)
cout << "x" << i << " = "
<< setw(12) << X[i]
<< endl;
}
else
cout <<
"Błąd w trakcie obliczeń!!!\n";
cout << endl;
// Usuwamy tablice dynamiczne
for(i = 0; i < n; i++)
delete [] AB[i];
delete [] AB;
delete [] X;
system("pause");
return 0;
}
|
| Wynik |
| Rozwiązywanie układu równań liniowych
metodą rozkładu LU -------------------------------------------------------- Wpisz dane wejściowe: 5 -1 2 -3 3 5 56 8 0 7 4 -1 62 -3 4 -3 2 -2 -10 8 -3 -2 1 2 14 -2 -1 -6 9 0 28 x0 = 1.00000 x1 = 3.00000 x2 = 5.00000 x3 = 7.00000 x4 = 9.00000 |
Python
(dodatek) # Rozkład LU w równaniach
# (C)2026 mgr Jerzy Wałaszek
# Metody numeryczne 0069
#---------------------------
EPS = 0.000000001
# Funkcja rozwiązuje układ równań
# metodą rozkładu LU
# n - stopień macierzy
# ab - macierz n x (n +1)
# x - macierz rozwiązań n x 1
# Jeśli układ został rozwiązany,
# to wynikiem jest True.
# Inaczej wynikiem jest False.
#--------------------------------------
def lu_eq(n,ab,x):
# Tworzymy wektor wierszowy
w = [i for i in range(n)]
# Rozkład LU
for k in range(0,n):
# numer wiersza
# z elementem max
maxw = k
maxe = abs(ab[w[k]][k])
# Szukamy elementu max
for i in range(k + 1,n):
if abs(ab[w[i]][k]) > maxe:
maxw = i
maxe = abs(ab[w[i]][k])
# Jeśli max jest zero,
# to macierz jest
# zdegenerowana
if maxe <= EPS:
return False
# Jeśli max nie leży
# na przekątnej,
# zamieniamy wiersze
if maxw != k:
w[k],w[maxw] = w[maxw],w[k]
# Dzielnik
akk = ab[w[k]][k]
# Normalizujemy kolumnę
for i in range(k + 1,n):
ab[w[i]][k] /= akk
# Modyfikujemy podmacierz
for i in range(k + 1,n):
for j in range(k + 1,n):
ab[w[i]][j] -= (ab[w[i]][k]
* ab[w[k]][j])
# Teraz rozwiązujemy układ
# równań w dwóch etapach
# Najpierw w X wyznaczamy
# macierz Y stosując
# podstawienia w przód
x[0] = ab[w[0]][n]
for i in range(1,n):
s = ab[w[i]][n]
for j in range(i):
s -= ab[w[i]][j] * x[j]
x[i] = s
# Wyznaczamy X stosując
# podstawienia wstecz
x[n - 1] /= ab[w[n - 1]][n - 1]
for i in reversed(range(n - 1)):
s = x[i]
for j in reversed(range(i + 1,n)):
s -= ab[w[i]][j] * x[j]
x[i] = s / ab[w[i]][i]
return True
# Program główny
#---------------
print("Rozwiązywanie układu równań "
"liniowych metodą rozkładu LU\n"
"----------------------------"
"----------------------------\n\n"
"Wpisz dane wejściowe:\n")
# Liczba równań w układzie
n = int(input())
# Tworzymy dynamicznie
# potrzebne macierze
# Macierz współczynników
# przy niewiadomych x
# oraz wyrazów wolnych
ab =[[float(s)
for s in input().split()]
for _ in range(n)]
# Macierz niewiadomych
x = [0.0 for _ in range(n)]
print()
# Rozwiązujemy układ równań
if lu_eq(n,ab,x):
for i in range(n):
print(f"x{i} = {x[i]:12.5f}")
else:
print("Błąd w trakcie obliczeń!!!")
print()
input("Naciśnij Enter")
|
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 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.