Gauss-Seidel metod för att lösa ett system av linjära ekvationer

Gauss-Seidel-metoden (Seidel-metoden, Libman-processen, successiv substitutionsmetod) är en klassisk iterativ metod för att lösa ett system av linjära ekvationer .

Uppkallad efter Seidel och Gauss .

Förklaring av problemet

Ta systemet: , där

Eller

Och vi kommer att visa hur det kan lösas med Gauss-Seidel-metoden.

Metod

För att klargöra essensen av metoden skriver vi om problemet i formuläret

Här, i den e ekvationen, har vi överfört till höger sida alla termer som innehåller , för . Denna post kan representeras som

där, i den accepterade notationen, betyder en matris vars huvuddiagonal innehåller motsvarande element i matrisen och alla andra nollor; medan matriserna och innehåller övre och nedre triangulära delar , på huvuddiagonalen som är nollor.

Den iterativa processen i Gauss-Seidel-metoden är uppbyggd enligt formeln

efter att ha valt lämplig initial uppskattning .

Gauss-Seidel-metoden kan ses som en modifiering av Jacobi-metoden . Huvudtanken med modifieringen är att nya värden används här så snart de tas emot, medan de i Jacobi-metoden inte används förrän nästa iteration:

var

Således beräknas den i -te komponenten av den -e approximationen med formeln

Till exempel när :

, det är , det är , det är

Konvergensvillkor

Låt oss presentera ett tillräckligt villkor för metodens konvergens.

Teorem .
Låt, varär matrisen invers till. Sedan för valet av initial uppskattning:
  1. Gauss-Seidel-metoden konvergerar;
  2. metodens konvergenshastighet är lika med konvergenshastigheten för en geometrisk progression med nämnaren ;
  3. korrekt feluppskattning: .

Uppsägningsvillkor

Villkoret för att avsluta Seidel iterativa processen när noggrannhet uppnås i en förenklad form har formen:

Ett mer exakt villkor för att avsluta den iterativa processen har formen

och kräver mer beräkning. Bra för glesa matriser .

Implementeringsexempel i C++

#include <iostream> #inkludera <cmath> använder namnutrymme std ; // Slutvillkor bool konvergera ( dubbel xk [ 10 ], dubbel xkp [ 10 ], int n , dubbel eps ) { dubbel norm = 0 ; för ( int i = 0 ; i < n ; i ++ ) norm += ( xk [ i ] - xkp [ i ]) * ( xk [ i ] - xkp [ i ]); return ( sqrt ( norm ) < eps ); } dubbel okr ( dubbel x , dubbel eps ) { int i = 0 ; dubbla neweps = eps ; medan ( neweps < 1 ) { i ++ ; neweps *= 10 ; } int okr = pow ( dubbel ( 10 ), i ); x = int ( x * okr + 0,5 ) / dubbel ( okr ); returnera x ; } bool diagonal ( dubbel a [ 10 ][ 10 ], int n ) { int i , j , k = 1 ; dubbel summa ; för ( i = 0 ; i < n ; i ++ ) { summa = 0 ; för ( j = 0 ; j < n ; j ++ ) summa += abs ( a [ i ][ j ]); summa -= abs ( a [ i ][ i ]); if ( summa > a [ i ][ i ]) { k = 0 _ cout << a [ i ][ i ] << " < " << summa << endl ; } annan { cout << a [ i ][ i ] << " > " << summa << endl ; } } return ( k == 1 ); } int main () { setlocale ( LC_ALL , "" ); dubbel eps , a [ 10 ][ 10 ], b [ 10 ], x [ 10 ], p [ 10 ]; int n , i , j , m = 0 ; int metod _ cout << "Ange storleken på den kvadratiska matrisen: " ; cin >> n ; cout << "Ange beräkningsprecisionen: " ; cin >> eps ; cout << "Fyll i matris A: " << endl << endl ; för ( i = 0 ; i < n ; i ++ ) för ( j = 0 ; j < n ; j ++ ) { cout << "A[" << i << "][" << j << "] = " ; cin >> a [ i ][ j ]; } cout << endl << endl ; cout << "Din matris A är: " << endl << endl ; för ( i = 0 ; i < n ; i ++ ) { för ( j = 0 ; j < n ; j ++ ) cout << a [ i ][ j ] << " " ; cout << endl ; } cout << endl ; cout << "Fyll i kolumnen för gratismedlemmar: " << endl << endl ; för ( i = 0 ; i < n ; i ++ ) { cout << "B[" << i + 1 << "] = " ; cin >> b [ i ]; } cout << endl << endl ; /* Metodens framsteg, där: a[n][n] - Matris av koefficienter x[n], p[n] - Nuvarande och tidigare lösningar b[n] - Kolumn av högra delar Alla ovanstående arrayer är verkliga och måste definieras i huvudprogrammet, även i arrayen x[n] bör du sätta initialen approximation av lösningskolumnen (t.ex. alla nollor) */ för ( int i = 0 ; i < n ; i ++ ) x [ i ] = 1 ; cout << "Diagonal dominans: " << endl ; if ( diagonal ( a , n )) { do { för ( int i = 0 ; i < n ; i ++ ) p [ i ] = x [ i ]; för ( int i = 0 ; i < n ; i ++ ) { dubbel var = 0 ; för ( int j = 0 ; j < n ; j ++ ) if ( j != i ) var += ( a [ i ][ j ] * x [ j ]); x [ i ] = ( b [ i ] -var ) / a [ i ] [ i ]; } m ++ ; } while ( ! konvergera ( x , p , n , eps )); cout << "Systembeslut:" << endl << endl ; för ( i = 0 ; i < n ; i ++ ) cout << "x" << i << " = " << okr ( x [ i ], eps ) << "" << endl ; cout << "Iterations: " << m << endl ; } annat { cout << "Ingen diagonal dominans" << endl ; } system ( "paus" ); returnera 0 ; }


Implementeringsexempel i Python

importera numpy som np def seidel ( A , b , eps ): n = len ( A ) x = np . nollor ( n ) # nollvektor converge = Falskt medan det inte konvergerar : x_new = np . kopia ( x ) för i i intervall ( n ): s1 = summa ( A [ i ][ j ] * x_new [ j ] för j i intervall ( i )) s2 = summa ( A [ i ][ j ] * x [ j ] för j i intervallet ( i + 1 , n )) x_new [ i ] = ( b [ i ] - s1 - s2 ) / A [ i ][ i ] konvergera = np . sqrt ( summa (( x_new [ i ] - x [ i ]) ** 2 för i inom intervallet ( n ))) <= eps x = x_new tillbaka x

Se även

Anteckningar

Länkar