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:
    - Gauss-Seidel-metoden konvergerar;
- metodens konvergenshastighet är lika med konvergenshastigheten för en geometrisk progression med nämnaren ;

- 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
Metoder för att lösa SLAE |
---|
Direkta metoder |
|
---|
Iterativa metoder |
|
---|
Allmän |
|
---|