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:
  1. Gauss-Seidelin menetelmä konvergoi;
  2. menetelmän konvergenssinopeus on yhtä suuri kuin geometrisen progression lähentymisnopeus nimittäjän kanssa ;
  3. 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 ; }


Toteutusesimerkki Pythonissa

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