Gauss-Seidel metode til løsning af et system af lineære ligninger

Gauss-Seidel-metoden (Seidel-metoden, Libman-processen, successiv substitutionsmetode) er en klassisk iterativ metode til løsning af et system af lineære ligninger .

Opkaldt efter Seidel og Gauss .

Udtalelse af problemet

Tag systemet: , hvor

Eller

Og vi vil vise, hvordan det kan løses ved hjælp af Gauss-Seidel-metoden.

Metode

For at tydeliggøre essensen af ​​metoden omskriver vi problemet i formularen

Her, i den th ligning, har vi overført til højre side alle led, der indeholder , for . Denne post kan repræsenteres som

hvor, i den accepterede notation, betyder en matrix, hvis hoveddiagonal indeholder de tilsvarende elementer i matrixen og alle andre nuller; mens matricerne og indeholder øvre og nedre trekantede dele , på hvis hoveddiagonal er nuller.

Den iterative proces i Gauss-Seidel metoden er bygget efter formlen

efter at have valgt den passende indledende tilnærmelse .

Gauss-Seidel-metoden kan ses som en modifikation af Jacobi-metoden . Hovedideen med modifikationen er, at nye værdier bruges her, så snart de er modtaget, mens de i Jacobi-metoden ikke bruges før næste iteration:

hvor

Således beregnes den i -te komponent af den -te tilnærmelse af formlen

For eksempel, når :

, det er , det er , det er

Konvergensbetingelse

Lad os præsentere en tilstrækkelig betingelse for metodens konvergens.

Sætning .
Lad, hvorer matrixen invers til. Så for ethvert valg af indledende tilnærmelse:
  1. Gauss-Seidel-metoden konvergerer;
  2. metodens konvergenshastighed er lig med konvergenshastigheden for en geometrisk progression med nævneren ;
  3. korrekt fejlvurdering :.

Opsigelsesbetingelse

Betingelsen for afslutning af Seidel iterative proces, når nøjagtighed er opnået i en forenklet form, har formen:

En mere præcis betingelse for afslutningen af ​​den iterative proces har formen

og kræver mere beregning. God til sparsomme matricer .

Implementeringseksempel i C++

#include <iostream> #include <cmath> bruger navneområde std ; // Sluttilstand bool konvergere ( dobbelt xk [ 10 ], dobbelt xkp [ 10 ], int n , dobbelt eps ) { dobbelt norm = 0 ; for ( int i = 0 ; i < n ; i ++ ) norm += ( xk [ i ] - xkp [ i ]) * ( xk [ i ] - xkp [ i ]); return ( sqrt ( norm ) < eps ; } dobbelt okr ( dobbelt x , dobbelt eps ) { int i = 0 ; dobbelt neweps = eps ; mens ( neweps < 1 ) { i ++ ; neweps *= 10 ; } int okr = pow ( dobbelt ( 10 ), i ); x = int ( x * okr + 0,5 ) / dobbelt ( okr ); returnere x ; } bool diagonal ( dobbelt a [ 10 ][ 10 ], int n ) { int i , j , k = 1 ; dobbelt sum ; for ( i = 0 ; i < n ; i ++ ) { sum = 0 ; for ( j = 0 ; j < n ; j ++ ) sum += abs ( a [ i ][ j ]); sum -= abs ( a [ i ][ i ]); if ( sum > a [ i ][ i ]) { k = 0 _ cout << a [ i ][ i ] << " < " << sum << endl ; } andet { cout << a [ i ][ i ] << " > " << sum << endl ; } } return ( k == 1 ); } int main () { setlocale ( LC_ALL , "" ); dobbelt eps , a [ 10 ][ 10 ], b [ 10 ], x [ 10 ], p [ 10 ]; int n , i , j , m = 0 ; int metode _ cout << "Indtast størrelsen af ​​den kvadratiske matrix: " ; cin >> n ; cout << "Indtast beregningspræcisionen: " ; cin >> eps ; cout << "Fyld matrix A: " << endl << endl ; for ( i = 0 ; i < n ; i ++ ) for ( j = 0 ; j < n ; j ++ ) { cout << "A[" << i << "][" << j << "] = " ; cin >> a [ i ][ j ]; } cout << endl << endl ; cout << "Din matrix A er: " << endl << endl ; for ( i = 0 ; i < n ; i ++ ) { for ( j = 0 ; j < n ; j ++ ) cout << a [ i ][ j ] << " " ; cout << endl ; } cout << endl ; cout << "Udfyld kolonnen for gratis medlemmer: " << endl << endl ; for ( i = 0 ; i < n ; i ++ ) { cout << "B[" << i + 1 << "] = " ; cin >> b [ i ]; } cout << endl << endl ; /* Metodefremskridt, hvor: a[n][n] - Matrix af koefficienter x[n], p[n] - Nuværende og tidligere løsninger b[n] - Kolonne af højre dele Alle ovenstående arrays er ægte og skal defineres i hovedprogrammet, også i arrayet x[n] skal du sætte initialen løsningskolonnetilnærmelse (f.eks. alle nuller) */ for ( int i = 0 ; i < n ; i ++ ) x [ i ] = 1 ; cout << "Diagonal dominans: " << endl ; if ( diagonal ( a , n )) { gør { for ( int i = 0 ; i < n ; i ++ ) p [ i ] = x [ i ]; for ( int i = 0 ; i < n ; i ++ ) { dobbelt var = 0 ; for ( int j = 0 ; j < n ; j ++ ) if ( j != i ) var += ( a [ i ][ j ] * x [ j ]); x [ i ] = ( b [ i ] -var ) / a [ i ][ i ] ; } m ++ ; } mens ( ! konvergerer ( x , p , n , eps )); cout << "Systembeslutning:" << endl << endl ; for ( i = 0 ; i < n ; i ++ ) cout << "x" << i << " = " << okr ( x [ i ], eps ) << "" << endl ; cout << "Iterations: " << m << endl ; } andet { cout << "Ingen diagonal dominans" << endl ; } system ( "pause" ); returnere 0 ; }


Implementeringseksempel i Python

import numpy som np def seidel ( A , b , eps ): n = len ( A ) x = np . nuller ( n ) # nul vektor converge = Falsk , mens den ikke konvergerer : x_new = np . kopi ( x ) for i i område ( n ): s1 = sum ( A [ i ][ j ] * x_ny [ j ] for j i område ( i )) s2 = sum ( A [ i ][ j ] * x [ j ] for j i området ( i + 1 , n )) x_new [ i ] = ( b [ i ] - s1 - s2 ) / A [ i ][ i ] konvergere = np . sqrt ( sum (( x_new [ i ] - x [ i ]) ** 2 for i i området ( n ))) <= eps x = x_new returnere x

Se også

Noter

Links