Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

obrazek

Autor artykułu: mgr Jerzy Wałaszek

©2026 mgr Jerzy Wałaszek

obrazek

Równania

Rozkład LU i układ równań liniowych

SPIS TREŚCI REMANENT
Podrozdziały
 

Definicje

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:

\[
\begin{cases}
a_{1,1}x_1 + a_{1,2}x_2 + \dots + a_{1,n}x_n = b_1 \\
a_{2,1}x_1 + a_{2,2}x_2 + \dots + a_{2,n}x_n = b_2 \\
\dots \\
a_{n,1}x_1 + a_{n,2}x_2 + \dots + a_{n,n}x_n = b_n
\end{cases}
\]

Zapiszmy ten układ w postaci macierzowej:

\[
\begin{array}{l}
A_{n \times n} = \begin{bmatrix}
a_{1,1} & a_{1,2} & \dots & a_{1,n} \\
a_{2,1} & a_{2,2} & \dots & a_{2,n} \\
\dots & \dots & \dots & \dots \\
a_{n,1} & a_{n,2} & \dots & a_{n,n}
\end{bmatrix} \\[4ex]
X_n = \begin{bmatrix} x_1 \\ x_2 \\ \dots \\ x_n \end{bmatrix} \\[4ex]
B_n = \begin{bmatrix} b_1 \\ b_2 \\ \dots \\ b_n \end{bmatrix} \\[4ex]
A \times X = B \\[2ex]
\begin{bmatrix}
a_{1,1} & a_{1,2} & \dots & a_{1,n} \\
a_{2,1} & a_{2,2} & \dots & a_{2,n} \\
\dots & \dots & \dots & \dots \\
a_{n,1} & a_{n,2} & \dots & a_{n,n}
\end{bmatrix} \times
\begin{bmatrix} x_1 \\ x_2 \\ \dots \\ x_n \end{bmatrix} =
\begin{bmatrix} b_1 \\ b_2 \\ \dots \\ b_n \end{bmatrix}
\end{array}
\]

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

\[A = L \times U\]

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

\[(L \times U) \times X = B\]

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

\[L \times (U \times X) = B\]

Robimy podstawienie:

\[U \times X = Y\]

Otrzymujemy:

\[L \times Y = B\]

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

\[\begin{array}{l}
\left\{ \begin{array}{l}
L \times Y = B \to Y \\
U \times X = Y \to X
\end{array} \right.
\end{array}\]

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:

\[\begin{array}{l}
L = \left[ \begin{array}{rrrrr}
1 & 0 & 0 & ... & 0 \\
l_{2,1} & 1 & 0 & ... & 0 \\
l_{3,1} & l_{3,2} & 1 & ... & 0 \\
... & ... & ... & ... & 0 \\
l_{n,1} & l_{n,2} & l_{n,3} & ... & 1
\end{array} \right] \quad Y = \left[ \begin{array}{r}
y_1 \\
y_2 \\
y_3 \\
... \\
y_n
\end{array} \right] \\
\left\{ \begin{array}{l}
y_1 = b_1 \\
l_{2,1}y_1 + y_2 = b_2 \\
l_{3,1}y_1 + l_{3,2}y_2 + y_3 = b_3 \\
... = ... \\
l_{n,1}y_1 + l_{n,2}y_2 + l_{n,3}y_3 + ... + y_n = b_n
\end{array} \right.
\end{array}\]

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

\[y_1 = b_1\]

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

\[\begin{array}{l}
l_{2,1}y_1 + y_2 = b_2 \\
y_2 = b_2 - l_{2,1}y_1
\end{array}\]

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

\[\begin{array}{l}
l_{3,1}y_1 + l_{3,2}y_2 + y_3 = b_3 \\
y_3 = b_3 - l_{3,1}y_1 - l_{3,2}y_2
\end{array}\]

Metoda ta nosi nazwę podstawiania w przód (ang. forward-substitution). Uogólniając, widzimy wyraźnie, że niewiadomą \(y_i\) wyliczamy z poprzednio wyliczonych niewiadomych \({y_1, y_2, \dots , y_{i - 1}}\). Wzór jest następujący:

\[\begin{array}{l}
y_i = b_i - l_{i,1}y_1 - l_{i,2}y_2 - ... - l_{i,i-1}y_{i-1} \\
y_i = b_i - \sum\limits_{k = 1}^{i - 1} (l_{i,k}y_k)
\end{array}\]

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

\[U \times X = Y\]

Rozpiszmy je:

\[\begin{array}{l}
U = \left[ \begin{array}{rrrrr}
u_{1,1} & u_{1,2} & u_{1,3} & ... & u_{1,n} \\
0 & u_{2,2} & u_{2,3} & ... & u_{2,n} \\
0 & 0 & u_{3,3} & ... & u_{3,n} \\
... & ... & ... & ... & ... \\
0 & 0 & 0 & ... & u_{n,n}
\end{array} \right] \quad Y = \left[ \begin{array}{r}
y_1 \\
y_2 \\
y_3 \\
... \\
y_n
\end{array} \right] \\
\left\{ \begin{array}{r}
u_{1,1}x_1 + u_{1,2}x_2 + u_{1,3}x_3 + ... + u_{1,n}x_n = y_1 \\
u_{2,2}x_2 + u_{2,3}x_3 + ... + u_{2,n}x_n = y_2 \\
u_{3,3}x_3 + ... + u_{3,n}x_n = y_3 \\
... = ... \\
u_{n,n}x_n = y_n
\end{array} \right.
\end{array}\]

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

\[\begin{array}{l}
u_{n,n}x_n = y_n \\
x_n = \dfrac{y_n}{u_{n,n}}
\end{array}\]

Wyliczoną wartość \(x_n\) wstawiamy do równania przedostatniego:

\[\begin{array}{l}
u_{n - 1,n - 1}x_n - u_{n - 1,n}x_n = y_{n - 1} \\
x_{n - 1} = \dfrac{y_{n - 1} - u_{n - 1,n}x_n}{u_{n - 1,n - 1}}
\end{array}\]

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

\[\begin{array}{l}
x_i = \dfrac{y_i - u_{i,n}x_n - u_{i,n - 1}x_{n - 1} - ... - u_{i,i + 1}x_{i + 1}}{u_{i,i}} \\
x_i = \dfrac{y_i - \sum\limits_{k = n}^{i + 1} (u_{i,k}x_k)}{u_{i,i}}
\end{array}\]

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.


do podrozdziału  do strony 

Rozkład LU w rozwiązywaniu układu równań liniowych

Metoda rozwiązywania układu równań liniowych z wykorzystaniem rozkładu LU jest następująca:

  1. Dokonujemy rozkładu LU macierzy współczynników \(A\).
  2. Jeśli macierz \(A\) jest zdegenerowana, to układ równań nie ma rozwiązania. Kończymy
  3. Dokonując podstawień w przód wyznaczamy macierz \(Y\) (może być w macierzy X).
  4. Dokonując podstawień wstecz wyznaczamy macierz \(X\).

Algorytm rozwiązywania układu równań liniowych z wykorzystaniem rozkładu LU

Dane wejściowe:

\(\varepsilon\) dokładność przyrównania do zera
\(n\) stopień macierzy
\(A\) macierz \({n \times n}\) współczynników
\(B\) macierz \({n \times 1}\) z wyrazami wolnymi
\(X\) macierz \({n \times 1}\) dla rozwiązań

Dane wyjściowe

true/false określa, czy operacja powiodła się, czy nie.
\(X\) macierz \({n \times 1}\) z wartościami niewiadomych, jeśli wynikiem jest true.

Zmienne pomocnicze

\(i,j,k\) indeksy
\(s\) suma
\(W\) macierz \({n \times 1}\) 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

Lista kroków

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 \times (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ń:

\[\begin{cases}
-x_0 + 2x_1 - 3x_2 + 3x_3 + 5x_4 = 56 \\
8x_0 + 7x_2 + 4x_3 - x_4 = 62 \\
-3x_0 + 4x_1 - 3x_2 + 2x_3 - 2x_4 = -10 \\
8x_0 - 3x_1 - 2x_2 + x_3 + 2x_4 = 14 \\
-2x_0 - x_1 - 6x_2 + 9x_3 = 28
\end{cases}\]
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")

do podrozdziału  do strony 

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: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.