Gauss-Seidelin menetelmä lineaarisen yhtälöjärjestelmän ratkaisemiseksi
Gauss-Seidelin menetelmä (Seidel-menetelmä, Libman-prosessi, peräkkäinen substituutiomenetelmä) on klassinen iteratiivinen menetelmä lineaarisen yhtälöjärjestelmän ratkaisemiseksi .
Nimetty Seidelin ja Gaussin mukaan .
Ongelman selvitys
Ota järjestelmä:
, missä
Tai
Ja näytämme kuinka se voidaan ratkaista Gauss-Seidel-menetelmällä.
Menetelmä
Selvittääksemme menetelmän ydintä, kirjoitamme ongelman uudelleen muotoon
Tässä yhtälössä olemme siirtäneet oikealle puolelle kaikki termit, jotka sisältävät , for . Tämä merkintä voidaan esittää muodossa
missä hyväksytyssä merkinnässä tarkoittaa matriisia, jonka päädiagonaali sisältää vastaavat matriisin elementit ja kaikki muut nollat; kun taas matriisit ja sisältävät ylemmän ja alemman kolmion osat , joiden päälävistäjä on nollia.
Gauss-Seidel-menetelmän iteratiivinen prosessi rakennetaan kaavan mukaan
kun olet valinnut oikean alkuperäisen likiarvon .
Gauss-Seidelin menetelmää voidaan pitää Jacobin menetelmän muunnelmana . Muokkauksen pääideana on, että uusia arvoja käytetään täällä heti, kun ne on vastaanotettu, kun taas Jacobi-menetelmässä niitä ei käytetä ennen seuraavaa iteraatiota:
missä
Siten - :nnen approksimoinnin i -komponentti lasketaan kaavalla
Esimerkiksi kun :
, tuo on
, tuo on
, tuo on
Konvergenssiehto
Esitetään riittävä ehto menetelmän konvergenssille.
|
Lause . Antaa, missäon matriisi käänteinen. Sitten mistä tahansa alkuperäisen likiarvon valinnasta:
- Gauss-Seidelin menetelmä konvergoi;
- menetelmän konvergenssinopeus on yhtä suuri kuin geometrisen progression lähentymisnopeus nimittäjän kanssa ;
- oikea virhearvio: .
|
|
Päättymisehto
Edellytys Seidelin iteratiivisen prosessin lopettamiselle, kun tarkkuus saavutetaan yksinkertaistetussa muodossa, on muotoa:
Tarkemmalla ehdolla iteratiivisen prosessin lopettamiselle on muoto
ja vaatii enemmän laskentaa. Hyvä harvoille matriiseille .
Toteutusesimerkki C++ :ssa
#include <iostream>
#include <cmath>
käyttäen nimiavaruutta std ;
// Loppuehto
bool converge ( double xk [ 10 ], double xkp [ 10 ], int n , double eps )
{
kaksinkertainen normi = 0 ;
for ( int i = 0 ; i < n ; i ++ )
normi += ( xk [ i ] - xkp [ i ]) * ( xk [ i ] - xkp [ i ]);
return ( sqrt ( norm ) < eps ;
}
double okr ( double x , double eps )
{
int i = 0 ;
double neweps = eps ;
kun ( uudet uutiset < 1 )
{
i ++ ;
neweps *= 10 ;
}
int okr = pow ( double ( 10 ), i );
x = int ( x * okr + 0,5 ) / double ( okr );
paluu x ;
}
bool diagonaali ( double a [ 10 ][ 10 ], int n )
{
int i , j , k = 1 ;
kaksinkertainen summa ;
for ( i = 0 ; i < n ; i ++ ) {
summa = 0 ;
for ( j = 0 ; j < n ; j ++ ) summa += abs ( a [ i ][ j ]);
summa -= abs ( a [ i ][ i ]);
jos ( summa > a [ i ][ i ])
{
k = 0_ _
cout << a [ i ][ i ] << " < " << summa << endl ;
}
muu
{
cout << a [ i ][ i ] << " > " << summa << endl ;
}
}
paluu ( k == 1 );
}
int main ()
{
setlocale ( LC_ALL , "" );
double eps , a [ 10 ][ 10 ], b [ 10 ], x [ 10 ], p [ 10 ];
int n , i , j , m = 0 ;
int menetelmä _
cout << "Syötä neliömatriisin koko: " ;
cin >> n ;
cout << "Syötä laskennan tarkkuus:" ;
cin >> eps ;
cout << "Täytä matriisi 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 << "Matriisi A on: " << endl << endl ;
for ( i = 0 ; i < n ; i ++ )
{
for ( j = 0 ; j < n ; j ++ )
cout << a [ i ][ j ] << " " ;
cout << endl ;
}
cout << endl ;
cout << "Täytä vapaat jäsenet -sarake: " << endl << endl ;
for ( i = 0 ; i < n ; i ++ )
{
cout << "B[" << i + 1 << "] = " ;
cin >> b [ i ];
}
cout << endl << endl ;
/*
Menetelmän edistyminen, missä:
a[n][n] - kertoimien matriisi
x[n], p[n] - Nykyiset ja aiemmat ratkaisut
b[n] - Oikeanpuoleisten osien sarake
Kaikki yllä olevat taulukot ovat todellisia ja
on määriteltävä pääohjelmassa,
myös taulukkoon x[n] tulee laittaa alkukirjain
ratkaisusarakkeen likiarvo (esim. kaikki nollat)
*/
for ( int i = 0 ; i < n ; i ++ )
x [ i ] = 1 ;
cout << "Diagonaalinen dominanssi: " << endl ;
if ( diagonaali ( a , n )) {
tehdä
{
for ( int i = 0 ; i < n ; i ++ )
p [ i ] = x [ i ];
for ( int i = 0 ; i < n ; i ++ )
{
kaksinkertainen 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 ++ ;
} while ( ! converge ( x , p , n , eps ));
cout << "Järjestelmäpäätös:" << endl << endl ;
for ( i = 0 ; i < n ; i ++ ) cout << "x" << i << " = " << okr ( x [ i ], eps ) << "" << endl ;
cout << "Iteraatiot: " << m << endl ;
}
else {
cout << "Ei diagonaalista dominanssia" << endl ;
}
system ( "tauko" );
paluu 0 ;
}
tuonti numpy as np
def seidel ( A , b , eps ):
n = len ( A )
x = np . nollat ( n ) # nollavektori
converge = Väärä ,
mutta ei konvergoi :
x_new = np . kopioi ( x )
i :lle alueella ( n ) : s1 = summa ( A [ i ][ j ] * x_uusi [ j ] j :lle alueella ( i ) ) s2 = summa ( A [ i ][ j ] * x [ j ] j :lle alueella ( i + 1 , n ) ) x_uusi [ i ] = ( b [ i ] - s1 - s2 ) / A [ i ][ i ]
konverge = np . sqrt ( summa (( x_uusi [ i ] - x [ i ]) ** 2 i :lle alueella ( n ) )) <= eps x = x_uusi
palauta x
Katso myös
Muistiinpanot
Linkit