Метод Якобі — класичний ітераційний метод розв'язку системи лінійних рівнянь
Опис методу Для квадратної системи з n лінійних рівнянь:
де:
Матрицю A можна розкласти на два доданки: діагональну матрицю D, та все інше R:
Систему лінійних рівнянь можна переписати в вигляді:
Ітераційний метод Якобі виражається формулою:
чи
Збіжність
Достатньою, але не необхідною, є умова, коли матриця A має домінантну головну діагональ:
Необхідною і достатньою умовою збіжності є, те щоб спектральний радіус матриці не перевищував одиницю:
Алгоритм Реалізація на С++ #include <vector> #include <iostream> #include <cmath> using namespace std;
void solve(const vector<float> a, //квадратна матриця const vector<float> b, //вектор вільних елементів vector<float>& x, //сюди буде записано розв'язок const float allowed_error) //допустима похибка { const unsigned n = x.size(); vector<float> tmp_x(n);
float error;
do
error = 0;
tmp_x = b; for (unsigned i = 0; i < n; ++i)
for (unsigned j = 0; j < n; ++j)
if (i != j)
tmp_x[i] -= a[i * n + j] * x[j];
//оновити x[i] та порахувати похибку const float x_updated = tmp_x[i] / a[i * (n + 1)]; const float e = fabs(x[i] - x_updated); x[i] = x_updated; if (e > error) { error = e; }
while (error > allowed_error); }
//приклад використання. Користувач вводить вхідні дані. int main() { unsigned n;
cout << "\nВведіть розмір системи:\nn = "; cin >> n;
vector<float> x(n); vector<float> a(n * n); vector<float> b(n);
cout << "\nВведіть вектор вільних елементів: \n"; for (auto& b_elem : b)
cin >> b_elem;
cout << "\nВведіть коефіцієнти системи: \n"; for (auto& a_elem : a)
cin >> a_elem;
float allowed_error; cout << "\nВведіть допустиму похибку: \n"; cin >> allowed_error;
solve(a, b, x, allowed_error);
cout << "\nРозв'язок системи:: \n"; for (unsigned i = 0; i < n; ++i)
cout << "\nx[" << i << "]= " << x[i];
Реалізація на С #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<math.h>
void main(){ int n, i, j, count = 0; float **a, *b, *x, *tmp_x, exp, e;
printf("Введіть розміри системи:\n"); printf("n = "); scanf("%i", &n);
a = (float**)malloc(n*sizeof(float*)); for(i = 0; i < n; i++){ a[i] = (float*)malloc(n*sizeof(float));
b = (float*)malloc(n*sizeof(float)); x = (float*)malloc(n*sizeof(float)); tmp_x = (float*)malloc(n*sizeof(float));
printf("Введіть коефіцієнти системи:\n"); for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ scanf("%f", &a[i][j]);
printf("Введіть вектор вільних елементів:\n"); for(i = 0; i < n; i++){ scanf("%f", &b[i]); x[i] = 0;
printf("Введіть точність обчислення: "); scanf("%f", &e);
do{ count++;
for(i = 0; i < n; i++){ tmp_x[i] = 0.0; for(j = 0; j < n; j++){ if(i != j){ tmp_x[i] = tmp_x[i] + (a[i][j] * x[j]);
tmp_x[i] = (b[i] - tmp_x[i]) / a[i][i];
exp = 0;
for(i = 0; i < n; i++){ if(fabs(x[i] - tmp_x[i]) > exp){ exp = fabs(x[i] - tmp_x[i]);
x[i] = tmp_x[i];
}while(exp > e);
free(tmp_x); for(i = 0; i < n; i++){ free(a[i]); } free(a); free(b);
printf("Розв'язок системи:\n"); for(i = 0; i < n; i++){ printf("x[%d] = %.6f\n", i+1, x[i]);
free(x); }
Див. також Ітераційні методи розв'язування СЛАР Метод Гауса — Зейделя
Джерела