Sunteți pe pagina 1din 10

UNIVERSITATEA TEHNICĂ A MOLDOVEI

Facultatea Informatică, Calculatoare și Microelectronică


Departamentul Informatică și Ingineria Sistemelor

Lucrare de laborator nr. 2


la disciplina Metode și Modele de Calcul

Tema: REZOLVAREA NUMERICĂ A SISTEMELOR


DE ECUAŢII LINIARE

A efectuat studentul: Tombrachevici Dan, gr.IA-203


A verificat: asistent univ. Mihaela Rusanovschi

Chișinău 2021
1. Scopul lucrărilor

1) Să se rezolve sistemul de ecuaţii lineare Ax=b, utilizând


- Metoda eliminării lui Gauss;
- Metoda lui Cholesky (metoda rădăcinii pătrate);
- Metoda iterativă a lui Jacobi cu o eroare ε =10−3 ;
- Metoda iterativă a lui Gauss-Seidel cu o eroare ε =10−3 și ε=10−5 .

2) Să se determine numărul de iteraţii necesare pentru aproximarea soluţiei


sistemului cu eroarea dată ε. Să se compare rezultatele.

Problema dată spre rezolvare:

Rezolvarea:
1. Metoda lui Cholesky (metoda rădăcinii pătrate)

#include <stdio.h>
#include <stdint.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(" %5lf ", A[i * n + j]);
printf("\t");
for (int j = 0; j < n; j++)
printf(" %5lf ", A[j * n + i]);
printf("\n");
}
}

void main()
{
int n = 4, i, k;
double s = 0;
double m[] = { 17.7, 0.3, 1.4, 0.9,
0.3, 20.1, -0.8, -1.2,
1.4, -0.8, 21.9, 0.8,
0.9, -1.2, 0.8, 17.6 };
double b[] = { 11.2, -20.3, 14.4, 17.9 }, y[] = {}, x[] = {};
double* c = cholesky(m, n);
printf("Matricea Initiala :\n");
printf("Ax :\t\t\t\tB :\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf(" %3.1lf", m[i * n + j]); //afisam matricea initiala
printf(" %2.1lf", b[i]);
printf("\n");
}
printf("Factorizarea lui Cholesky\n\n Matricea L:\t\t\t\t\tTranspusa : \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);
}
Output-ul este:

2. Metoda iterativă a lui Gauss-Seidel cu o eroare ε =10−3 și ε=10−5

#include<stdio.h>
#include<conio.h>
#include<math.h>
#define eps 0.000001
void main()
{
int i, j, k, n = 4, iter = 1;
float a[5][6], x[5];
float sum, sum2, Xprim, eroare, Meroare;
printf("\n\n Metoda Gauss-Seidel: \n\n");
a[1][1] = 17.7; a[1][2] = 0.3; a[1][3] = 1.4; a[1][4] = 0.9; a[1][5] = 11.2; //atribuirea valorilor
matricii
a[2][1] = 0.3; a[2][2] = 20.1; a[2][3] = -0.8; a[2][4] = -1.2; a[2][5] = -20.3;
a[3][1] = 1.4; a[3][2] = -0.8; a[3][3] = 21.9; a[3][4] = 0.8; a[3][5] = 14.4;
a[4][1] = 0.9; a[4][2] = -1.2; a[4][3] = 0.8; a[4][4] = 17.6; a[4][5] = 17.9;
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 += 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 += 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("\n Converge in %d iteratii catre solutia:", iter);
for (i = 1; i <= n; i++)
printf("\n x[%d]= %.8f", i, x[i]);
printf("\n\n");
}
Output-ul este:

3. Metoda iterativă a lui Jacobi cu o eroare ε =10−3

#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<stdlib.h>
#define eps 0.000001

void main()
{
float a[5][6], x[4], x0[4], Meroare, Xprim, eroare, sum;
int ext = 0, n = 4, i, j, maxit = 100, itr;
char ch;
printf("\n Metoda Jacobi: \n\n");
a[1][1] = 17.7; a[1][2] = 0.3; a[1][3] = 1.4; a[1][4] = 0.9; a[1][5] = 11.2; //atribuirea valorilor
matricii
a[2][1] = 0.3; a[2][2] = 20.1; a[2][3] = -0.8; a[2][4] = -1.2; a[2][5] = -20.3;
a[3][1] = 1.4; a[3][2] = -0.8; a[3][3] = 21.9; a[3][4] = 0.8; a[3][5] = 14.4;
a[4][1] = 0.9; a[4][2] = -1.2; a[4][3] = 0.8; a[4][4] = 17.6; a[4][5] = 17.9;
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("\n Converge catre solutie in %d iteratii\n", itr); // daca converge afisam x1..xn si
iesim din ciclu
for (i = 1; i <= n; i++)
printf("\n x[%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...
}
Output-ul este:
Concluzii:
Efectuând această lucrăre de laborator am rezolvat sistemul de ecuații liniare Ax=b, utilizând
metoda eliminării lui Gauss, metoda lui Cholesky (metoda rădăcinii pătrate), metoda iterativă a lui
Jacobi cu o eroare ε =10−3 , și metoda iterativă a lui Gauss-Seidel cu eroare ε =10−3 și ε=10−5 . Am
determinat numărul de iterații necesare pentru aproximarea soluției sistemului cu eroarea dată ε .
Rezolvarea este de două tipuri: metode directe și metode iterative. Metodele directe constau în
transformarea sistemului de ecuații Ax=b într-un sistem echivalent pentru care rezolvarea este mult
mai simplă. În metodele directe, soluția exactă se obține după un număr finit de operații aritmetice
elementare și acest număr de operașii este de ordinul n3,

S-ar putea să vă placă și