Documente Academic
Documente Profesional
Documente Cultură
Ciobanu Stanislav Met Num Lab3 4
Ciobanu Stanislav Met Num Lab3 4
Departamentul Informatică și
Ingineria Sistemelor
RAPORT
despre lucrările de laborator
nr.3 și nr.4
la Metode Numerice
Tema: Rezolvarea
numerică a sistemelor
de ecuații liniare
Varianta 7
Chişinău, 2023
Scopul lucrărilor
1) Să se rezolve sistemul de ecuații liniare Ax=b, utilizând:
Metoda eliminării lui Gauss
Metoda lui Cholesky (metoda rădăcinii pătrate)
( )( )
6.1 −1.9 0.4 0.2 7.1
−1.9 14.3 1.8 1.4 10.2
A= b=
0.4 1.8 12.7 −0.6 −7.2
0.2 1.4 −0.6 13.1 8.6
În prima parte a sarcinii, care este mai mult teoretică, se cere de descris descris metodele
utilizate, astfel metodele numerice de rezolvare a sistemelor de ecuaţii lineare sunt de două tipuri:
metode directe şi metode iterative. Metodele directe constau în transformarea sistemului Ax=b
într-un sistem echivalent pentru care rezolvarea este cu mult mai simplă. În metodele directe soluţia
exactă se obţine după un număr finit de operaţii aritmetice elementare (adunare, scădere, înmulţire,
împărţire şi rădăcina pătrată) şi acest număr de operaţii este de ordinul n3 . Subliniem că soluţia exactă
se obţine în cazurile (ideale) în care erorile de rotunjire sunt absente. La fiecare operaţie elementară
efectuată de calculator avem o eroare de rotunjire şi prin urmare erorile directe în caz general
furnizează doar o soluţie aproximativă. Metodele directe se utilizează pentru rezolvarea sistemelor nu
prea “mari”, de dimensiune n=200.
Rezolvarea sistemelor de ecuaţii lineare printr-o metodă iterativă înseamnă construirea unui
şir de vectori x(k) , k =0 , 1, 2 , … (pornind de la un vector x(0) ales arbitrar) convergent către soluția
sistemului considerat. În metodele iterative, de obicei, o iterație necesită efectuarea unui număr de
ordinea n2 operații aritmetice. De aceea metodele iterative se utilizează pentru rezolvarea sistemelor
“mari”, de dimensiune n>100 (în cazul asigurării unei viteze sporite de convergenţă pentru o alegere
a aproximării iniţiale adecvate). Trunchierea şirului {x ( k ) } are loc la un indice m , astfel încât x (m )
constituie o aproximaţie satisfăcătoare a soluţiei căutate x ¿(de exemplu, |x (m )−x ¿|< ε , unde ε > 0 este
eroarea admisă).
Metoda eliminării a lui Gauss constă în a aduce sistemul iniţial la un sistem echivalent
avînd matricea coeficienţilor superior triunghiulară. Transformarea sistemului dat într-un sistem de
formă triunghiulară fără ca să se modifice soluţia sistemului se realizează cu ajutorul a trei operaţii de
bază. Prima este rearanjarea ecuaţiilor (schimbarea a două ecuaţii între ele), a doua este înmulţirea
unei ecuaţii cu o constantă (diferită de zero), iar a treia este scăderea unei ecuaţii din alta şi înlocuirea
celei de-a doua cu rezultatul scăderii. Fie dat sistemul nostru de ecuaţii lineare din condiție Ax=b,
unde A=( aij )n x, b ∈ R n, detA ≠ 0. Să presupunem că a 11 ≠ 0 ; dacă a 11 ≠ 0 se aduce elementul nenul
din prima coloană pe locul (1 , 1), permutând ecuațiile respective ale sistemului. Primul pas constă
în eliminarea necunoscutei x 1 din ecuaţiile sistemului începînd cu a doua, multiplicînd ecuaţia
αi1
întîia cu raportul μi 1= , i=2 , 3 , … , n şi scăzînd rezultatul obţinut din ecuaţia i pentru ∀ i≥ 2.
α 11
Obţinem în acest fel sistemul echivalent A(2) x=b(2) , cu coeficienții:
(2) (1)
α 1 j =α 1 j , j=1 , 2 ,… ,n ;
(2)
α i 1 =0 , i=2 , 3 , … , n;
(2) (1) ( 1)
α ij =α ij ∗μ i1∗α 1 j , i, j=2, 3 , … , n ;
(2) (1) (2) (1) (1 )
b 1 =b 1 ,b i =bi −μ i 1∗b1 , i=2 , 3 , … , n;
(1) (1)
Mai sus s-a notat α ij =a ij; i , j=1 ,2 , … , n și b i =b i; i=1 , 2 ,… , n . Prima ecuaţie a
sistemului echivalent coincide cu prima ecuaţie a sistemului dat inițial. În continuare se repetă
procedeul de mai sus pentru eliminarea necunoscutei x 2 din sistemul echivalent ş.a.m.d. La
pasul k se obţine sistemul A(k) x=b(k), unde:
( )( )
(1 ) (1 ) ( 1) (1 ) ( 1) (1 )
α 11 α 12 K α 1 , k−1 α 1k K α 1n b1
(2 ) ( 2) (2 ) (2 ) (2 )
0 α 22 K α 2 , k−1 α 2k K α2 n b2
(k) ( k−1 ) ( k−1) (k)
A = 0 0 α k−1 ,k−1 k−1
( )
¿ α k−1, k K α k−1 ,n b = bk−1(k−1 )
( k) (k ) (k )
0 0 0 ¿ α kk K α kn bk
0 0 0 ¿ α nk
(k )
K α nn
( k)
bn
(k )
Elementele α ij(k) ale lui A(k) și b i(k) ale lui b(k) se calculează recursiv prin formulele:
{
α ij(k−1) ,i ≤ k−1
(k)
α ij = 0 ,i ≥ k , k ≤ k −1
α ij(k−1)
−μi , k∗α k−1(k −1 ) , i≥ k , j≥ k
α i ,k−1(k−1)
unde μi , k−1= ,
α k−1 , k−1(k−1)
{
(k−1)
(k) bi , pentru ∀ i ≤ k−1
iar b i = (k−1) ( k−1)
b i −μi , k−1∗b k−1 , pentru ∀ i≥ k
După n paşi necunoscuta x n−1 va fi eliminată din ultima ecuaţie, obţinându-se un sistem cu
matricea superior triunghiulară:
{
(1) (1) (1 )
a 11 x 1+ a12 x 2 +…+ a1 k (1 ) x k +…+ a1 n(1) x n=b1
(2) ( 2) (2 ) (2)
a22 x 2+ …+a2 k x k +…+ a2 n x n=b 2
……………………… ………………………………………… ………
( ) ( ) (k)
akk k x k + …+a kn k x n=b k
……………………… ………………………………………… ………
(n)
a nn( n) x n =bn
Acest sistem se rezolvă începînd cu ultima ecuaţie cu ajutorul procesului de eliminare inversă
care se poate descrie astfel:
n
x n=
bn
( n)
; x n−1=
bn−1
( n−1 )
−an−1 , n
( n−1)
∗x n
;
b k( k )− ∑ akj( k )∗x j
;
j=k+1
α nn( n) α n−1, n−1(n−1) xk= (k )
α kk
Metoda lui Gauss prezentată mai sus presupune că elementele pivot trebuie să fie diferite de
zero. Dacă la efectuarea pasului k elementul a kk =0 atunci cel puţin unul din celelalte elemente din
coloana k şi din liniile k +1 , k +2 , … , n este nenul; în caz contrar matricea A ar fi singulară (detA =0
). Permutând ecuaţiile sistemului putem aduce pe locul (k , k ) elementul nenul şi, deci, este posibil să
reluăm eliminarea. Dacă un element pivot este exact egal cu zero, din motive de stabilitate numerică,
trebuie să efectuăm rearanjarea ecuaţiilor. Am realizat subrutina (subprogramul/funcția sau
procedura) cu numele GAUSS de calcul care realizează metoda realizării lui Gauss cu pivotarea
parţială: la pasul k pivotul se ia egal cu primul element maxim în modul din coloanak subdiagonală a
(k)
lui A , conform formulei
|ark |=max|aik |, k ≤ i≤ n. şi se permută liniile k şi r .
(k ) ( k)
(k+ 1) 1
xi = ¿
aii
Astfel obţinem o metodă de rezolvare a sistemului liniar Ax=b numită metoda lui Jacobi.
În metoda lui Jacobi este necesar de-a păstra în memoria calculatorului toate componentele
vectorului x(k) atît timp cît se calculează vectorul x(k +1). Putem modifica metoda lui Jacobi, astfel
încît la pasul (k + 1) să folosim în calculul componentei x i(k+ 1), valorile deja calculate la acelaşi
pas: x 1(k+1 ) , x 2(k+ 1) ,… , x i−1(k+1 ). Această modificare a metodei lui Jacobi se numeşte metoda
Gauss-Seidel, iar şirul iterativ anterior devine:
(k+ 1) 1
xi = ¿
aii
Rădăcina
Metoda Iterații Eroarea
X Y
x1=1.49235
x2=0,954102
Eliminării Gauss
x3=-0.725608
- 3 -
x4=0.498506
x1=1.49235 y1=1.49235
x2=0,954102 y2=0,954102
Cholesky
x3=-0.725608 y3=-0.725608
3 -
x4=0.498506 y4=0.498506
x1=1.49211
x2=0,953914
Jacobi
x3=-0.725478
- 6 0.001
x4=0.498605
x1=1.49233
x2=0,954096
x3=-0.725606
- 5 0.001
x4=0.498506
Gauss-Seidel
x1=1.49235
x2=0,954101
x3=-0.725608
- 7 0.00001
x4=0.498506
Concluzie
În cadrul acestei lucrări de laborator, care a avut un caracter deja mai mult practic, am
însușit patru metode numerice de rezolvare a sistemelor de ecuații liniare, algebrice și
transcendente neliniare, obținând aproximativ aceeleași soluții indiferent de metoda aleasă. La
general aceste metode au abordări diferite și pot prezenta avantaje sau dezavantaje în funcție de
caracteristicile sistemelor sau matricilor pe care le rezolvă. Astfel, de exemplu, metoda eliminării
lui Gauss poate fi mai eficientă pentru sisteme mici și medii, dar poate deveni costisitoare pentru
sisteme mari. În general, eficiența și numărul de iterații necesare depind de caracteristicile
matricei sistemului (simetrie, condiționare, dimensiune) și de condițiile de convergență ale
fiecărei metode. Nu există o metodă universală care să fie cea mai bună pentru orice tip de
problemă, iar alegerea depinde de specificul sistemului de ecuații liniare pe care dorim să-l
rezolvăm. Vreau să menționez că am studiat secvențele de cod date ca exemplu și le-am
convertat din limbajul de programare Pascal în C++, însă din motiv că personal m-am chiocnit cu
Pascal doar la lecțiile de informatică din gimnaziu, am decis totuși să realizez lucrarea în C++,
care îmi este un pic mai bine cunoscut și după părerea mea este mult mai modern și aplicabil în
context.
Vreau să menționez că deși am auzit de la colegi că au utilizat Wolfram Alpha pentru a se
verifica, eu totuși am decis să caut calculatoare specializate online pentru calculul sistemelor
liniare de ecuații. Astfel am găsit platforma atozmath.com, care prin intermediul plugin-ului
javascript MathJax, m-a ajutat să calculez soluțiile specifice fiecărei din cele 4 metode, ca
ulterior să le compar cu rezultatele obținute de programul meu. Dacă ar fi să fac o comparație, se
pare că luând în considerare numărul de iterații, cele mai eficiente ar fi metodele numerice
directe (eliminarea Gauss, metoda Cholesky) față de metodele iterative. Astfel, observăm că
ambele metode directe au efectuat un număr identic de iterații (adică 3). Metoda iterativă a lui
Jacobi la precizia ε =10−3 a efectuat 6 iterații pentru exemplul dat. Atragem atenția că la precizia
−3
ε =10 , metoda Gauss-Seidel a fost mai eficientă (5 iterații) față de cea a lui Jacobi, însă odată
cu creșterea preciziei până laε =10−5 , a crescut și numărul iterațiilor, devenind deja mai mare ca
la metoda lui Jacobi (7 iterații).
Din punct de vedere al programului vreau doar să menționez că la crearea unei interfețe
plăcute cu meniu de interacționare om-mașină, m-am ciocnit cu o singură dificultate banală.
Astfel obțineam eroare la încercarea de a executa instrucțiunea system(“cls”) din cadrul
limbajului de programare C++, care trebuia să curățe ecranul consolei de conținut. Problema era
că utilizam un compilator online GDB care lucra pe baza unui sistem pa bază de Linux, ceea ce
înseamnă că comanda dată trebuie înlocuită cu analogul ei system(“clear”), căci system(“cls”)
lucrează doar pe calculatoarele cu sistemele de operare (SO) de tip Windows. La fel îmi asum că
am comis o greșeală, ce ține de faptul că m-am lăsat condus de exemplele Pascal date în
materialele didactice... Acolo se utilizează instrucțiunea goto, utilizarea căreia este de dorit s-o
evităm defapt fiindcă duce la așa numitul “spaghetti-cod”.
Cursul de metode numerice face parte din disciplinele fundamentale de pregătire a
studenţilor din domeniul ingineriei, având ca scop prezentarea principiilor şi relaţiilor de calcul
matematic numeric care stau astăzi la baza costrucţiei programelor de calcul profesionale
utilizate în prezent de orice inginer. De aceea, cu siguranță voi căuta domenii de aplicare a
acestuia în sfera mea de activitate profesională.
Anexe
Anexa 1. Listing-ul programului C++
(cu screenshot-urile rezultatelor)
#include <iostream>
#include <math.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
int isMatrPosDef();
int isMatrSim();
void trans();
void determinare();
void GAUSS();
void CHOLESKY();
void JACOBI();
int isMatrDiagDom();
float A[lung][lung] = {
};
float c[lung][lung],d[lung],l[lung][lung]={0};
int main(){
system("clear");
int p,opt;
cout<<A[i][j]<<" ";
c[i][j]=A[i][j];
cout<<endl;
cout<<b[i]<<" ";
d[i]=b[i];
cout<<endl;
cout<<"\
n------------------------------------------------------------------"<<endl;
cout<<"------------------------------------------------------------------\
n"<<endl;
cin>>opt;
switch(opt){
case 1:
system("clear");
cout<<"--------------------------------------------------------"<<endl;
cout<<"--------------------------------------------------------\
n"<<endl;
GAUSS();
cout<<endl;
getchar();
exit(1);
break;
case 2:
system("clear");
cout<<"----------------------------------------------------"<<endl;
cout<<"----------------------------------------------------\n"<<endl;
CHOLESKY();
cout<<endl;
getchar();
system("clear");
main();
exit(1);
break;
case 3:
system("clear");
cout<<"------------------------------------------------"<<endl;
cout<<"------------------------------------------------\n"<<endl;
JACOBI();
cout<<endl;
getchar();
system("clear");
main();
exit(1);
break;
case 4:
system("clear");
cout<<"------------------------------------------------"<<endl;
cout<<"------------------------------------------------\n"<<endl;
SEIDEL(0.001);
cout<<endl;
cout<<"------------------------------------------------"<<endl;
cout<<"------------------------------------------------\n"<<endl;
SEIDEL(0.00001);
cout<<endl;
getchar();
system("clear");
main();
exit(1);
break;
default:
cout<<"Eroare! Ai ales o optiune gresita!";
break;
case 0:
return 0;
void GAUSS() {
float x[lung]={0};
int ni=0;
eliminSubDiag(ni);
x[i]=b[i];
x[i]-=A[i][j]*x[j];
x[i]/=A[i][i];
cout<<"\nRezultatele x:\n";
cout<<"x"<<i+1<<"="<<x[i]<<"\n";
temp=A[linia1][j];
A[linia1][j]=A[linia2][j];
A[linia2][j]=temp;
temp=b[linia1];
b[linia1]=b[linia2];
b[linia2]=temp;
if(A[k][k]==0) {
if(A[i][k]!=0) {
schimbLinii(k,i);
break;
float m=A[i][k]/A[k][k];
A[i][j]-=m*A[k][j];
b[i]-=m*b[k];
ni++;
}
}
void CHOLESKY(){
if(!isMatrPosDef()){
getchar();
system("clear");
main();
exit(1);
goto E;
if(!isMatrSim()){
getchar();
system("clear");
main();
exit(1);
determinare();
getchar();
E:;
if(k==1)
return A[0][0];
if(k==2)
return A[0][0]*A[1][1]-A[0][1]*A[1][0];
float s=0;
float t[lung][lung]={0};
int x=0;
if(l!=i){
t[x][m-1]=A[l][m];
x++;
if(i%2==0)
s+=A[i][0]*deter(t,k-1);
else
s-=A[i][0]*deter(t,k-1);
return s;
int isMatrPosDef(){
if(A[i][i]<=0 || deter(A,i+1)<=0)
return 0; // nu este
return 1; // este
int isMatrSim(){
// Conditia de simetrie
if(A[i][j]!=A[j][i])
return 0; // nu este
return 1; // este
}
// Functia ce efectueaza factorizarea Cholesky a matricei A
l[0][0]=(float)sqrt(A[0][0]);
l[i][0]=A[i][0]/l[0][0];
float t=0;
t+=l[i][j]*l[i][j];
l[i][i]=(float)sqrt(A[i][i]-t);
float t1=0;
t1+=l[j][k]*l[i][k];
l[j][i]=(A[j][i]-t1)/l[i][i];
ni++;
void trans(){
float t=0;
t=l[i][j];
l[i][j]=l[j][i];
l[j][i]=t;
int ni=0;
factor(ni);
float y[lung],x[lung];
y[0]=b[0]/l[0][0];
float t=0;
t+=l[i][j]*y[j];
y[i]=(b[i]-t)/l[i][i];
trans();
cout<<l[i][j]<<"\t";
cout<<endl;
x[lung-1]=y[lung-1]/l[lung-1][lung-1];
float t;
t=0;
t+=l[i][j]*x[j];
x[i]=(y[i]-t)/l[i][i];
cout<<"\nRezultatele x:\n";
cout<<"x"<<i+1<<"="<<x[i]<<"\n";
cout<<"\nRezultatele y:\n";
for(int i=0; i<lung; i++)
cout<<"y"<<i+1<<"="<<y[i]<<"\n";
void JACOBI(){
float epsilon=0.001;
float x[lung],x1[lung],q[lung][lung]={0},d[lung],t,max;
int ni=0;
if(i!=j)
q[i][j]=-(A[i][j]/A[i][i]);
else
q[i][j]=0;
if(!isMatrDiagDom()){
getchar();
system("clear");
main();
exit(1);
goto E;
d[i]=b[i]/A[i][i];
x[i]=d[i];
do {
x1[i]=x[i];
for(int i=0; i<lung; i++){
t=0;
t+=q[i][j]*x1[j];
x[i]=t+d[i];
max=(float)fabs(x[0]-x1[0]);
if((float)fabs(x[i]-x1[i])>max)
max=(float)fabs(x[i]-x1[i]);
ni++;
} while(max>epsilon);
cout<<"\nRezultatele x:\n";
cout<<"x"<<i+1<<"="<<x[i]<<endl;
getchar();
E:;
int isMatrDiagDom(){
float s;
s=0;
if(i!=j)
s+=A[i][j];
if(A[i][i]<s)
return 0; // nu este
if(A[i][i]==0)
return 0; // nu este
return 1; // este
float x[lung],x1[lung],q[lung][lung]={0},d[lung],t,max;
int ni=0;
if(i!=j)
q[i][j]=-(A[i][j]/A[i][i]);
else
q[i][j]=0;
if(!isMatrDiagDom()){
getchar();
system("clear");
main();
exit(1);
goto E;
d[i]=b[i]/A[i][i];
x[i]=d[i];
do {
x1[i]=x[i];
t=0;
t+=q[i][j]*x[j];
x[i]=t+d[i];
max=(float)fabs(x[0]-x1[0]);
if((float)fabs(x[i]-x1[i])>max)
max=(float)fabs(x[i]-x1[i]);
ni++;
} while(max>epsilon);
cout<<"\nRezultatele x:\n";
cout<<"x"<<i+1<<"="<<x[i]<<endl;
getchar();
E:;