Metoda Gauss-Seidel pentru rezolvarea unui sistem de ecuații liniare

Metoda Gauss-Seidel (metoda Seidel, procesul Libman, metoda substituției succesive) este o metodă iterativă clasică pentru rezolvarea unui sistem de ecuații liniare .

Numit după Seidel și Gauss .

Enunțul problemei

Luați sistemul: , unde

Sau

Și vom arăta cum poate fi rezolvată folosind metoda Gauss-Seidel.

Metoda

Pentru a clarifica esența metodei, rescriem problema în formă

Aici, în a- a ecuație, am transferat în partea dreaptă toți termenii care conțin , pentru . Această intrare poate fi reprezentată ca

unde, în notația acceptată, înseamnă o matrice a cărei diagonală principală conține elementele corespunzătoare ale matricei și toate celelalte zerouri; în timp ce matricele și conțin părți triunghiulare superioare și inferioare , pe diagonala principală a cărora sunt zerouri.

Procesul iterativ din metoda Gauss-Seidel este construit conform formulei

după alegerea aproximării iniţiale adecvate .

Metoda Gauss-Seidel poate fi privită ca o modificare a metodei Jacobi . Ideea principală a modificării este că noile valori sunt folosite aici de îndată ce sunt primite, în timp ce în metoda Jacobi nu sunt utilizate până la următoarea iterație:

Unde

Astfel, componenta i -a a aproximării -a este calculată prin formula

De exemplu, când :

, acesta este , acesta este , acesta este

Condiție de convergență

Să prezentăm o condiție suficientă pentru convergența metodei.

Teorema .
Fie, undeeste matricea inversă cu. Apoi, pentru orice alegere de aproximare inițială:
  1. metoda Gauss-Seidel converge;
  2. rata de convergenţă a metodei este egală cu rata de convergenţă a unei progresii geometrice cu numitorul ;
  3. estimarea corectă a erorii: .

Condiție de încetare

Condiția pentru încheierea procesului iterativ Seidel atunci când precizia este atinsă într-o formă simplificată are forma:

O condiție mai precisă pentru terminarea procesului iterativ o are forma

și necesită mai multe calcule. Bun pentru matrici rare .

Exemplu de implementare în C++

#include <iostream> #include <cmath> folosind namespace std ; // Încheierea condiției bool converge ( dublu xk [ 10 ], dublu xkp [ 10 ], int n , dublu eps ) { dubla norma = 0 ; pentru ( int i = 0 ; i < n ; i ++ ) norma += ( xk [ i ] - xkp [ i ]) * ( xk [ i ] - xkp [ i ]); return ( sqrt ( norm ) < eps ); } dublu okr ( dublu x , dublu eps ) { int i = 0 ; double neweps = eps ; în timp ce ( neweps < 1 ) { i ++ ; neweps *= 10 ; } int okr = pow ( dublu ( 10 ), i ); x = int ( x * okr + 0,5 ) / dublu ( okr ); întoarce x ; } diagonala bool ( dublu a [ 10 ][ 10 ], int n ) { int i , j , k = 1 ; sumă dublă ; pentru ( i = 0 ; i < n ; i ++ ) { suma = 0 ; pentru ( j = 0 ; j < n ; j ++ ) suma += abs ( a [ i ][ j ]); sum -= abs ( a [ i ][ i ]); dacă ( suma > a [ i ][ i ]) { k = 0 _ cout << a [ i ][ i ] << " < " << sum << endl ; } altfel { cout << a [ i ][ i ] << " > " << sum << endl ; } } return ( k == 1 ); } int main () { setlocale ( LC_ALL , "" ); dublu eps , a [ 10 ][ 10 ], b [ 10 ], x [ 10 ], p [ 10 ]; int n , i , j , m = 0 ; metoda int _ cout << "Introduceți dimensiunea matricei pătrate: " ; cin >> n ; cout << "Introduceți precizia de calcul: " ; cin >> eps ; cout << "Completați matricea A: " << endl << endl ; pentru ( i = 0 ; i < n ; i ++ ) pentru ( j = 0 ; j < n ; j ++ ) { cout << "A[" << i << "][" << j << "] = " ; cin >> a [ i ][ j ]; } cout << endl << endl ; cout << "Matricea ta A este: " << endl << endl ; pentru ( i = 0 ; i < n ; i ++ ) { pentru ( j = 0 ; j < n ; j ++ ) cout << a [ i ][ j ] << " " ; cout << endl ; } cout << endl ; cout << "Completează coloana pentru membri gratuiti: " << endl << endl ; pentru ( i = 0 ; i < n ; i ++ ) { cout << "B[" << i + 1 << "] = " ; cin >> b [ i ]; } cout << endl << endl ; /* Progresul metodei, unde: a[n][n] - Matricea coeficienților x[n], p[n] - Soluții curente și anterioare b[n] - Coloana părților drepte Toate tablourile de mai sus sunt reale și trebuie definite în programul principal, de asemenea, în tabloul x[n] ar trebui să puneți inițiala aproximarea coloanei cu soluție (de exemplu, toate zerourile) */ pentru ( int i = 0 ; i < n ; i ++ ) x [ i ] = 1 ; cout << "Dominanță diagonală: " << endl ; dacă ( diagonala ( a , n )) { do { pentru ( int i = 0 ; i < n ; i ++ ) p [ i ] = x [ i ]; pentru ( int i = 0 ; i < n ; i ++ ) { var dublu = 0 ; pentru ( int j = 0 ; j < n ; j ++ ) if ( j != i ) var += ( a [ i ][ j ] * x [ j ]); x [ i ] = ( b [ i ] - var ) / a [ i ][ i ]; } m ++ ; } în timp ce ( ! converge ( x , p , n , eps )); cout << "Decizie de sistem:" << endl << endl ; for ( i = 0 ; i < n ; i ++ ) cout << "x" << i << " = " << okr ( x [ i ], eps ) << "" << endl ; cout << "Iterații: " << m << endl ; } else { cout << "Fără dominanță diagonală" << endl ; } sistem ( „pauză” ); returnează 0 ; }


Exemplu de implementare în Python

import numpy ca np def seidel ( A , b , eps ): n = len ( A ) x = np . zerouri ( n ) # vector zero converge = Fals în timp ce nu converge : x_new = np . copie ( x ) pentru i în interval ( n ): s1 = sumă ( A [ i ][ j ] * x_new [ j ] pentru j în interval ( i )) s2 = sumă ( A [ i ][ j ] * x [ j ] pentru j în interval ( i + 1 , n )) x_new [ i ] = ( b [ i ] - s1 - s2 ) / A [ i ][ i ] converge = np . sqrt ( suma (( x_new [ i ] - x [ i ]) ** 2 pentru i în interval ( n ))) <= eps x = x_new întoarce x

Vezi și

Note

Link -uri