Sunteți pe pagina 1din 10

Ministerul Educaţiei al Republicii Moldova

Universitatea Tehnică a Moldovei


Facultatea Calculatoare Informatica si Microelectronica
Catedra Informatica Aplicata

RAPORT
Lucrarea de laborator nr.2
Disciplina: Metode si Modele de Calcul

A efectuat:
st. gr. IA-182 Melnic Octavian

A verificat:
lect., sup. Moraru Vasile

Chisinau 2019
Tema: Rezolvarea numerica a sistemelor de ecuatii liniare
Scopul lucrarii :
1) Sa se rezolve sistemul de ecuatii liniare Ax = b, utilizind:
 Metoda lui Cholesky, metoda radacinii patrate.
 Metoda iterativa a lui Jacobi cu o eroare ϵ = 10-6
 Metoda iterativa a lui Gauss-Seidel cu o eroare ϵ = 10-6
2) Sa se determine numarul de iteratii necesare pentru aproximarea solutiei sistemului cu
eroarea data ϵ.
3) Sa se compare rezultatele.

Notiuni teoretice:
Metoda lui Cholesky. Metoda lui Cholesky de rezolvare a sistemelor de ecuaţii liniare
algebrice se mai numeşte metoda rădăcinii pătratice şi constă în descompunerea sistemului
Ax=b în două sisteme triunghiulare.
In aceasta metoda se presupune ca matricea A este o matrice simetrica si pozitiv
definite.
Matricea L se alege astfel, incit A=LTL. Aceasta descompunere a matricei A se
numeste factorizarea Choleskly.
Teorema: Daca matricea A este simetrica si pozitiva definite, atunci exista o unica
matrice inferior triunghiulara LT cu elementele diagonale pozitive, astfel incit A=LT .
Factorizarea LU presupune descompunerea matricei sistemului (A) intr-un produs de
doua matrice L*U. Matricea L trebuie sa fie inferior triunghiulară,in timp ce matricea U
trebuie sa fie superior triunghiulară.

Forma factorizarii LU pentru un exemplu 3x3


Din această forma nu se pot calcula coeficienții matricelor L şi U. Pentru ca acest
lucru sa fie posibil se adaugă câteva constrângeri,astfel rezultând factorizarea Cholesky.
Daca sistemul A*x=b devine L*U*x=b, putem nota cu d=U*x. Astfel:
Pentru a rezolva sistemul de ecuații se determină mai întâi d din L*d=b prin rezolvarea
unui sistem inferior triunghiular. Ulterior se rezolvă şi sistemul d=U*x ca un sistem
superior triunghiular.

Dacă matricea sistemului este simetrica şi pozitiv definita, A se poate descompune astfel:

A=L*L’ (L’ fiind matricea L transpusa)

L este o matrice inferior triunghiulară.

Pentru determinarea elementelor matricei L se folosesc relațiile:

Metoda iteraţiei şi metoda Gauss-Seidel. Metoda iteraţiei reprezintă o extindere a


metodei aproximaţiilor succesive folosite în cazul ecuaţiilor de o singură necunoscută şi
metoda Jacobi pentru rezolvarea sistemelor de ecuaţii liniare. Acestă metodă permite
rezolvarea sistemelor de ecuaţii neliniare de forma:
Plecând de la sistemului A*x=b, descompunem A=N-P, unde N este o matrice ușor
de inversat. În continuare:

Se deduce relația de recurenţă:

Se notează:
Matricea A se partiţionează ca A=D-L-U, unde:

D=o matrice diagonală

L=o matrice strict inferior triunghiulară

U=o matrice superior triunghiulară

Metoda Jacobi

Componenta i din vectorul x la pasul (iteraţia) p+1 se calculează:

Metoda Gauss-Seidel

Componenta i din vectorul x la pasul (iteraţia) p+1 se calculează:


Codul programului:
Metoda (Cholesky):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>

double *cholesky(double *A, int n) {


double s;
double *L = (double*)calloc(n * n, sizeof(double));
if (L == NULL)
exit(EXIT_FAILURE);

for (int i = 0; i < n; i++)


for (int j = 0; j < (i+1); j++)
{
s = 0;
for (int k = 0; k < j; k++)
s += L[i * n + k] * L[j * n + k]; //calculam suma tuturor
elementelor pana la elementul dat
L[i * n + j] = (i == j) ? //daca este Aii atunci
radicald din (Aii-s)
sqrt(A[i * n + i] - s) : //daca nu 1
/ Lij * ( Aij-s)
(1.0 / L[j * n + j] * (A[i * n + j] - s));
}
return L;
}

void show_matrix(double *A, int n) { // afisarea matricei dupa ce separam


(metoda Cholesky
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf(" %2.5f ", A[i * n + j]);
printf("\t");
for(int j=0;j<n;j++)
printf(" %2.5f ", A[j * n + i]);
printf("\n");
}
}

main() {
int n = 3,i,k;
float s=0;
double m[] = {4, -1, 2,
-1, 10, -6,
2, -6, 9};
float b[]={-2, 5, -7}, y[]={}, x[]={};
double *c = cholesky(m, n);
printf("Matricea Initiala :\n");
printf("Ax : B :\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf(" %2.0f ", m[i * n + j]); //afisam matricea initiala
printf(" %2.0f ", b[i]);
printf("\n");
}
printf("Factorizarea lui Cholesky\n\n Matricea L:
Transpusa : \n");
show_matrix(c, n);

printf("\nVectorul Ly=b\n");
y[0]=b[0]/c[0]; //atribuim 1 val lui y b1/c11
for (i=1;i<n;i++) //pentru fiecare rand al matricei
{ s=0;
for (k=0;k<i;k++)
s+=c[i * n + k]*y[k]; //calculam suma Lik * Dk
y[i]=(1/c[i*n+i]*(b[i]-s)); //calculam Di
}

for (i=0; i<n; i++)


printf("%2.5f \n",y[i]); //afisam toate Di

printf("\nVectorul Ltxy\n");
s=0;
x[n-1]=y[n-1]/c[n*n-1];

for (i=n-2;i>=0;i--)
{
for (k=i+1;k<n;k++)
s=s+(c[i+n*k]*x[k]); //calculam suma tuturor Lik * Ljk * Dk
x[i]=(1/c[i*n+i]*(y[i]-s)); //calculam Lij
s=0;
}

for (i=0; i<n; i++) //afisam toate Lij


printf("%.4f \n",x[i]);
free(c);
getch();
}

Metoda (Jacob):
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<stdlib.h>
#define eps 0.000001
main()
{
float a[4][5],x[4],x0[4],Meroare,Xprim,eroare,sum;
int ext=0,n=3,i,j,maxit=100,itr;
char ch;
printf("Metoda Jacobi: \n\n");
a[1][1]=4;a[1][2]=-1;a[1][3]=0;a[1][4]=4; //atribuirea valorilor
matricii
a[2][1]=-1;a[2][2]=5;a[2][3]=-2;a[2][4]=1;
a[3][1]=0;a[3][2]=-2;a[3][3]=3;a[3][4]=-3;
for(i=1;i<=n;i++)
for(j=1;j<=n+1;j++)
printf("a[%d][%d]= %-2.4f\n",i,j,a[i][j]); //aratam matricea

for(i=1;i<=n;i++)x0[i]=a[i][n+1]/a[i][i]; // vectorul x1....xn


atribuim cu 0
itr=1;
do{

Meroare=0;
for(i=1;i<=n;i++)
{
sum=0;
for(j=1;j<=n;j++)
if(i!=j)sum=sum+a[i][j]*x0[j]; //se calculeaza suma elem
din linie inafara de elementul ce apartine liniei aii
x[i]=(a[i][n+1]-sum)/a[i][i]; //calculam x dupa 1 interatie
// atribuim valoarea din xprim lui x
eroare=x[i]-x0[i];
if(eroare<0)eroare*=-1;
if(eroare>Meroare) Meroare=eroare; // verificam daca xprim -
xprec <eps
}
for(i=1;i<=n;i++)x0[i]=x[i];
if(Meroare<eps)
{
printf("\nConverge catre solutie in %d iteratii\n",itr); //
daca converge afisam x1..xn si iesim din ciclu
for(i=1;i<=n;i++)
printf("\nx[%d] = %.4f",i,x[i]);
ext=1;
goto ex;
}
itr++;
}while(itr<=maxit);
ex:if(ext!=1)printf(" Nu converge in %d de iteratii \n",maxit); //daca
nu converge in decurs de 100 interatii...
getch();
}
Metoda (Gauss):
#include<stdio.h>
#include<conio.h>
#include<math.h>
#define eps 0.000001
main()
{
int i,j,k,n=3,iter=1;
float a[4][5],x[4];
float sum,sum2,Xprim,eroare,Meroare;
printf("Metoda Gauss-Seidel: \n\n");
a[1][1]=4;a[1][2]=-1;a[1][3]=0;a[1][4]=4; //atribuirea valorilor
matricii
a[2][1]=-1;a[2][2]=5;a[2][3]=-2;a[2][4]=1;
a[3][1]=0;a[3][2]=-2;a[3][3]=3;a[3][4]=-3;
for(i=1;i<=n;i++) //vect x de iesire dam val 0
x[i]=a[i][n+1]/a[i][i];
do{
Meroare=0;
for(i=1;i<=n;i++)
{
sum2=0;
sum=0;
for(j=1;j<=n;j++)
if(j!=i)
sum=sum+a[i][j]*x[j]; //se calculeaza suma elem din
linie inafara de elementul ce apartine liniei aii
for(j=1;j<i-1;j++)
if(j!=i)
sum2=sum2+a[i][j]*x[j];
Xprim=(a[i][n+1]-sum-sum2)/a[i][i]; //calculam Xprim
(urmatorul x )
eroare=fabs(x[i]-Xprim); //calculam xprim - xprec
if(eroare>Meroare) Meroare=eroare; //verificam la cea mai mare
eroare din toate x1..xn
x[i]=Xprim; //atribuim x1..xn xprim
printf(" x[%d] =%.8f",i,x[i]);
}
printf("\n");
iter++;
}while(Meroare>eps);
printf("\nConverge in %d iteratii catre solutia:",iter);
for(i=1;i<=n;i++)
printf("\nx[%d]=%.8f",i,x[i]);
getch();
}

Rezultatele obtinute

Fig.1 Metoda Cholesky


Fig.2 Metoda Jacob

Fig.3 Metoda Gauss – Seidel


Compararea rezultatelorz

Metoda Radacina Iteratii Eroarea


x y
x1= 1.0000 y1= 2.00000
Cholesky x2= 0.0000 y2= 0.91766 - -
x3= -1.0000 y1= -1.46898
x1= 1.00000024
Gauss -Seidel x2= 0.00000033 11 0.000001
x3= -0.00000076
x1= 1.0000
x2= -0.0000 23 0.000001
Jacobi
x3= -1.0000

Concluzii

In aceasta lucrare de laborator am facut cunostinta cu trei metode de


rezolvare numerica a sistemelor de ecuatii liniare: Metoda Cholesky, Metoda Jacobi si
Metoda Gauss - Seidel .In urma rezultatelor obtinute, din exemplul dat, cea mai
eficienta metoda iterativa de calculare a radacinelor sistemelor de ecuatii a fost
metoda Gauss-Seidel.