Sunteți pe pagina 1din 25

Theory without practice is useless, practice without theory is blind Roger Bacon

Rezolvarea sistemelor de ecuatii liniare

Metoda eliminarii Gauss

Aspecte teoretice

Metoda lui Gauss este una din metode tradiionale directe si eficiente de rezolvare a sistemelor de ecuaii liniare avand forma :
A x = b

Ideea de baz a metodei const n aducerea sistemului de ecuaii prin transformri elementare la o form echivalent, avnd o matrice superior sau inferior triunghiular, urmat de rezolvarea sistemului rezultat prin procedee recurente specifice, foarte eficiente. Transformarea sistemului iniial ntr-un sistem de form triunghiular se realizeaz cu ajutorul a trei operaii elementare: interschimbarea a dou ecuaii ntre ele; nmulirea unei ecuaii cu o constant nenul; scderea unei ecuaii din alta i nlocuirea celei de-a doua ecuaii cu rezultatul scderii. Transformarea sistemului este echivalent cu eliminarea succesiv a necunoscutelor din ecuaii, prin aceast operaie ajungndu-se la o matrice triunghiular a sistemului (faza eliminrii). Rezolvarea sistemului cu matrice triunghiular const n determinarea necunoscutelor i substituia lor n ecuaiile sistemului n ordine invers, fiind denumit din acest motiv faza substituiei inverse. Sa consideram pentru exemplificare un sistem de trei ecuatii cu trei necunoscute ,

(1)
1

Theory without practice is useless, practice without theory is blind Roger Bacon

Pentru majoritatea metodelor de rezolvare a sistemelor de ecuaii liniare - fie ele directe sau iterative - se ajunge ca la un moment dat s fie necesar mprirea la un element diagonal din matricea A, ajj. Acest element poart numele generic de pivot. Desigur, dac acest element este nul metoda respectiv eueaz, deoarece - din punct de vedere numeric - operaia de mprire la 0 este imposibil i, dac nu se iau masuri speciale, orice program de calcul se ntrerupe din execuie ca urmare a producerii unei erori de tipul "Run time error", cu un mesaj de eroare de genul "Floating point overflow". Situaia extrem n care ntr-o matrice A poate s apar un element diagonal nul este cea n care matricea respectiv este singular (determinantul ei este nul). Pe de alt parte, pivotul se poate anula far ca matricea A s fie singular. Mai mult dect att, pivotul poate fi nenul, dar cu o valoare foarte mic, astfel nct mprirea la el s conduc la producerea unor erori de rotunjire, care prin acumulare pot denatura rezultatul. Evitarea unor asemenea situaii se poate face prin adoptarea unei msuri care s permit aducerea pe diagonal a unui element suficient de mare. O asemenea tehnic este aceea a pivotrii care const n schimbarea ntre ele a dou linii sau a dou coloane, astfel nct noul pivot sa aib o valoare absolut ct mai mare posibil. Cutarea noului pivot se face pe coloana curent j*, pe liniile situate sub linia j*, inclusiv aceasta (pivotarea partiala) sau pe liniile i coloanele situate sub linia j* i la dreapta coloanei j*, inclusiv acestea (pivotarea complet). In cazul pivotrii pariale, la un pas j*, se spune ca se executa pivotarea parial pe coloana j*. Prin aceast tehnic se caut pe coloana j* elementul subdiagonal maxim n valoare absolut i se schimb linia j* cu linia in care apare acel element. Deoarece schimbarea a dou linii n matricea A nseamn de fapt schimbarea ordinii a dou ecuaii din sistem, se impune ca - simultan - s se realizeze i interschimbarea termenilor liberi corespunztori din vectorul b i de asemenea, schimbarea semnului determinantului matricii. n cazul concret al unui sistem de trei ecuaii cu trei necunoscute, la primul pas al etapei eliminrii urmrim eliminarea necunoscutei x1 din toate ecuaiile sistemului, cu excepia primei ecuaii. Pentru aceasta, mprim mai nti prima linie la elementul pivot a11, presupus nenul, adic a11 0 (dac nu este ndeplinit aceast condiie se reordoneaz ecuaiile sistemului):

Scdem apoi prima ecuaie nmulit cu primul coeficient al celei de-a doua ecuaii din a doua ecuaie i, respectiv, prima ecuaie nmulit cu primul coeficient al celei de-a treia ecuaii din cea de-a treia ecuaie. Obinem astfel sistemul:

unde:

(2)

Aadar, primul pas al metodei eliminrii a lui Gauss conduce la ecuaia matricial:

(3)

La urmatorul pas ,eliminam necunoscuta mai intai a doua ecuatie la elementul pivot

din ultima ecuatie.Pentru aceasta , impartim

, diferit de zero (daca nu este asa atunci realizam ,din

interschimbarea ecuatiilor a doua si a treia) si apoi scadem linia obtinuta, inmultita cu , ecuatia a treia.Acest al doilea pas conduce la ecuatia matriciala :

(4)

unde :

(5)

Faza eliminarii se incheie impartind cea de a treia ecuatie la elementul pivot

, care ,

pentru un sistem cu matrice nesingulara (matrice patratica , cu determinand nenul) trebuie sa fie diferit de zero.Rezulta dupa acest pas sistemul :

(6)

cu :

Sau matriceal : Se observa ca matricea

este superior triunghiulara, iar sistemul obtinut este

echivalent cu cel initial A =b , adica are solutia ( ). Faza substitutiei inverse (mersul inapoi) presupune parcurgerea in sens invers a ecuatiilor sistemului cu matrice triunghiulara (6) , rezultat in faza eliminarii si stabilirea solutiei sistemului pe baza unui calcul recursiv :

(7)

Asadar, determinarea solutiilor se face recursiv, de la indici mari spre indici mici, fiecare noua solutie depinzand in mod explicit numai de solutiile determinate anterior.

Exemplu eliminare Gaussiana Etapa 1


Fie sistemul de ecuatii :

2 x0 + 2 x1 + 4 x2 + 2 x3 = 7 6 x + 3x + 2 x + x = 5 2 0 1 2 3 3x0 + 2 x1 + 2 x2 + x3 = 5 7 x0 + x1 + 3x2 + 3x3 = 6 4

Ec1 se imparte la 2 Din Ec2 se scade Din Ec3 se scade Din Ec4 se scade

Exemplu eliminare Gaussiana Etapa 2

x0 + x1 + 2 x2 + 1x3 = 3 8 2x =14 1 x1 4 x2 2 x3 = 5 7 x2 + 2 x3 = 2 6

x0 + x1 + 2 x2 + 1x3 = 3 8 2x =14 1 x1 4 x2 2 x3 = 5 7 x2 + 2 x3 = 2 6

Ec2 se imparte la 2 Din Ec3 se scade Din Ec4 se scade

x0 + x1 + 2 x2 + 1x3 = 3 8 x1 =7 4 x2 2 x3 = 5 0 x2 + 2 x3 = 2 6

Exemplu eliminare Gaussiana Etapa 3

x0 + x1 + 2 x2 + 1x3 = 3 8 x1 =7 4 x2 2 x3 = 5 0 x2 + 2 x3 = 2 6

Ec3 se imparte la -4 Din Ec4 se scade

x0 + x1 + 2 x2 + 1x3 = 3 8 x1 =7 x2 + 0.5 x3 = 1 2.5 1.5 x3 = 1 3.5


Pentru un sistem de ecuatii adus la forma tridiagonala :

x0 + x1 + 2 x2 + 1x3 = 3 8 x1 =7 x2 + 0.5 x3 = 1 2.5 1.5 x3 = . Se obtine solutia sistemului :( 1 3 5

)=(6,7,8,9).

Pasi urmariti :
Putem acum sa sumarizam procedura solutiei care consta din trei pasi principali, dupa cum urmeaza :

1) Descompunerea LU : A=L U Procedura aceasta reprezinta faza substitutiei inverse si determina cele doua

matrici L si U .In particular vom inlocui LUx=b =>Ly=b, iar Ux=y. 2) Rezolvarea inainte (Forward Solve ) pentru y : Ly=b; 3) Rezolvarea din spate (Backward Solve) pentru x : Ux=y; Pseudocodul pentru pasi (1) si (2) este :

Implementarea Secventiala
Date Intrare :fisierul gauss.in Dimensiunea matricei intrare : 3x3 Matricea : 2 1 -1 8 -3 -1 2 -11 -2 1 2 -3

Codul C :
#include <stdio.h> #include <conio.h> int n=3; float a[3][4]={{2, 1, -1, 8}, {-3, -1, 2, -11},{-2, 1, 2, -3}}; void forwardSubstitution() { int i, j, k, max; float t; for (i = 0; i < n; ++i) { max = i; for (j = i + 1; j < n; ++j) if (a[j][i] > a[max][i]) max = j; for (j = 0; j < n + 1; ++j) { t = a[max][j]; a[max][j] = a[i][j]; a[i][j] = t; } for (j = n; j >= i; --j) for (k = i + 1; k < n; ++k) a[k][j] -= a[k][i]/a[i][i] * a[i][j]; } } void reverseElimination() { int i, j; for (i = n - 1; i >= 0; --i) { a[i][n] = a[i][n] / a[i][i]; a[i][i] = 1; for (j = i - 1; j >= 0; --j) {

} } }

a[j][n] -= a[j][i] * a[i][n]; a[j][i] = 0;

void gauss() { int i, j; forwardSubstitution(); reverseElimination(); for (i = 0; i < n; ++i) { for (j = 0; j < n + 1; ++j) printf("%.2f\t", a[i][j]); printf("\n"); }

void main() { int i, j; gauss(); getch(); }

Listingul aplicatiei secventiale :

Message Passing Interface

Algoritmi paraleli folosesc resursele specifice unui sistem de calcul paralel(un numar de p procesoare) pentru rezolvarea unei probleme. Un algoritm secvential poate fi paralelizat daca secventa de operatii elementare generata poate fi descompusa in p subsecvente, in asa fel incat operatiile din fiecare subsecventa sa poata fi executate concurentialde procesoarele disponibile. Exista situatii in care aceasta descompunere este naturala , in general insa, algoritmul secvential cel mai natural pentru rezolvarea unei probleme nu conduce la p in astfel de subsecvente. Limbajul C permite implementarea aplicatiilor paralele printr-o librarie MPI (Message Passing Interface). MPI este un protocol de comunicatie folosit pentru programarea paralela menit sa ofere functionalitate pentru sincronizarea si comunicarea intre procese intr-un mod independent de limbaj si de platforma ( exista implementari ale MPI pentru aproape orice platforma ). Programele MPI sunt orientate catre procese, asadar pentru obtinerea de performante maxime trebuiesc definite pe fiecare computer atatea procese cate procesoare exista ( sau coreuri ). In cadrul desfasurari acestui proiect am folosit MPICH2, o implementare free, open-source a MPI-2. Cele mai importante componente ale MPICH sunt mpd (multi-purpose daemon) si mpiexec. Mpd are rolul de manager n ceea ce priveste comunicarea si sincronizarea intre procese, iar mpiexec are rolul de a lansa in executie aplicatiile MPI.

Implementarea Paralela (p=n)


Daca p=n , fiecare procesor va primi o linie de procesat ; Initial , procesorul trimite linia sa catre toate celelalte (broadcast processor).

Apoi fiecare procesor calculeaza multiplicarea cu o constanta si modifica in

linia sa coeficientii ; Procedura se repeta pentru procesoarele

, etc.

Mesajul i de broadcast contine n-i elemente. Fiecare processor aflat dupa procesorul de broadcast calculeaza mutiplicarea sa operand cu n-i elemente dupa ce trimite la toate procesoarele linia sa (broadcast).

Paralelizare prin descompunere 1D pe linii


Matricea A este partitionata pe linii intre n procese: procesul

detine linia i a

matricii pe care o transforma ;


La un moment dat toate procesele executa aceeasi iteratie k ; Exista dependente de date intre instructiunile de scadere si de impartire ;

P0

im p art

Evaluarea performantelor - descompunere 1D pe linii

Intr-un pas k:

Calcule impartire: Procesul Pk: n-k-1 operatii aritmetice de impartire Calcule scadere : procesele Pi, k<i<n: 2*(n-k-1) operatii aritmetice( de inmultire si scadere) Comunicare: one-to-all broadcast Tcomm=(ts+(n-k-1)*tw)*log(n)

Timpul total in toti pasii k:


TP = 3(n k 1) + (t S + tW (n k 1)) log n
k =0 k =0 n 1 n 1

3 1 TP = n (n 1) +t S n log n + t W n (n 1) log n 2 2

Numarul de operatii pentru substitutia inainte , inapoi este: O()

Timpul secvential pentru descompunerea LU:


W = 2 3 n 3

Paralelizarea Aplicatiei folosind MPI

Date de Intrare: fisierele mdatgaus.inp,vdatgaus.inp Matricea A : 4 4

1.0 -4.0 -2.0 3.0 4.0 1.0

3.0 4.0

2.0 3.0 4.0

2.0 -1.0 3.0

2.0 -1.0

Vectorul B : 4 22.0 6.0 -4.0 6.0

Codul C :
#include #include #include #include #include <stdio.h> <stdlib.h> <assert.h> "mpi.h" <conio.h>

int main(int argc, char** argv) { int n_size, NoofRows, NoofCols,NoofRows_Bloc,ColofPivot; int Numprocs, MyRank ,Root= 0; int i, j,index,k,icol; double **matrice_A,*vector_B,*vector_A,*ARecv, *BRecv;

double *Buffer_Pivot, *Y_buffer,*Buffer_bksub,*X_buffer ; double tmp,Pivot; double *Output; FILE *fp; MPI_Status status; //This routine establishes the MPI environment, returning an error code if there is a problem. MPI_Init(&argc, &argv); //MPI_COMM_WORLD //basic communicator ;every processor can communicate with every other processor MPI_Comm_rank(MPI_COMM_WORLD, &MyRank); MPI_Comm_size(MPI_COMM_WORLD, &Numprocs); if(MyRank == 0) { if ((fp = fopen ("mdatgaus.inp", "r")) == NULL) { printf("Eroare la deschiderea fisierului!"); exit(-1); } fscanf(fp, "%d %d", &NoofRows,&NoofCols); n_size=NoofRows; matrice_A = (double **) malloc(n_size*sizeof(double *)); for(i = 0; i < n_size; i++){ matrice_A[i] = (double *) malloc(n_size * sizeof(double)); for(j = 0; j < n_size; j++) fscanf(fp, "%lf", &matrice_A[i][j]); } fclose(fp); if ((fp = fopen ("vdatgaus.inp", "r")) == NULL){ printf("Can't open input vector file"); exit(-1); } fscanf(fp, "%d", &NoofRows); n_size=NoofRows; vector_B = (double *)malloc(n_size*sizeof(double)); for (i = 0; i<n_size; i++) fscanf(fp, "%lf",&vector_B[i]); fclose(fp);

vector_A = (double *)malloc(n_size*n_size*sizeof(double)); index = 0; for(i=0; i<n_size; i++) for(j=0; j<n_size; j++) vector_A[index++] = matrice_A[i][j];

} //broadcasts a message from the process with rank "root" to all other processes of the communicator MPI_Bcast(&NoofRows, 1, MPI_INT, Root, MPI_COMM_WORLD); MPI_Bcast(&NoofCols, 1, MPI_INT, Root, MPI_COMM_WORLD); if(NoofRows != NoofCols) { MPI_Finalize(); if(MyRank == 0){ printf("Matricea trebuie sa fie patratica! \n"); getch(); } exit(-1);

// Broadcast the size of the matrix to all MPI_Bcast(&n_size, 1, MPI_INT, 0, MPI_COMM_WORLD); if(n_size % Numprocs != 0) { MPI_Finalize(); if(MyRank == 0){ printf("No of processors (p) should divide the size of the input matrix (n)\n"); } exit(-1); } NoofRows_Bloc = n_size/Numprocs; //alocam memorie pentru fiecare proces pt matricea si vectorul de intrare ARecv = (double *) malloc (NoofRows_Bloc * n_size* sizeof(double)); BRecv = (double *) malloc (NoofRows_Bloc * sizeof(double)); //Distribuie datele de intrate catre procese //Mpi Scatter: divides a big array into a number of smaller parts equal //to the number of processes and sends //each process (including the source) a piece of the array in rank order. MPI_Scatter (vector_A, NoofRows_Bloc * n_size, MPI_DOUBLE, ARecv, NoofRows_Bloc * n_size, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Scatter (vector_B, NoofRows_Bloc, MPI_DOUBLE, BRecv, NoofRows_Bloc, MPI_DOUBLE, 0, MPI_COMM_WORLD); //alocam memorie pentru Buffer Pivot Buffer_Pivot = (double *) malloc ((NoofRows_Bloc + 1 + n_size * NoofRows_Bloc) * sizeof(double)); //primeste datele de la toate procesoarele (i=0 ,k-1) deasupra procesorului k.... */ for(k = 0; k < MyRank; k++) { MPI_Recv(Buffer_Pivot, NoofRows_Bloc * n_size + 1 + NoofRows_Bloc, MPI_DOUBLE, k, k, MPI_COMM_WORLD, &status);

for(i = 0; i < NoofRows_Bloc; i++){ ///Buffer_Pivot[0] gaseste rangul procesorului de la recv //Index il folosim pentru a reduce matricea la o forma triunghiulara // buffer_Pivot[0] determina valoarea pivotului in fiecare linie din matrice //, in fiecare procesor ColofPivot = ((int) Buffer_Pivot[0]) * NoofRows_Bloc + i; for (j = 0; j < NoofRows_Bloc; j++){ index = j*n_size; tmp = ARecv[index + ColofPivot]; for (icol = ColofPivot; icol < n_size; icol++) ARecv[index + icol] -= tmp * Buffer_Pivot[i*n_size+icol+1+NoofRows_Bloc]; BRecv[j] -= tmp * Buffer_Pivot[1+i]; ARecv[index + ColofPivot] = 0.0; } } } Y_buffer = (double *) malloc (NoofRows_Bloc * sizeof(double));

//impartirea la pivot ///i linie for(i = 0; i < NoofRows_Bloc; i++){ ColofPivot = MyRank * NoofRows_Bloc + i; index = i*n_size; Pivot = ARecv[index + ColofPivot];

for (icol = ColofPivot; icol < n_size; icol++){ ARecv[index + icol] = ARecv[index + icol]/Pivot; Buffer_Pivot[index + icol + 1 + NoofRows_Bloc] = ARecv[index + icol]; } Y_buffer[i] = BRecv[i] / Pivot; Buffer_Pivot[i+1] = Y_buffer[i]; //j linie for (j = i+1; j<NoofRows_Bloc; j++) { tmp = ARecv[j*n_size + ColofPivot]; for (icol = ColofPivot+1; icol < n_size; icol++) ARecv[j*n_size+icol] -= tmp * Buffer_Pivot[index + icol + 1 + NoofRows_Bloc]; BRecv[j] -= tmp * Y_buffer[i]; ARecv[j*n_size+i] = 0; } }

//trimite catre toate procesoarele de sub procesorul curent for (k = MyRank+1; k < Numprocs; k++) { Buffer_Pivot[0] = (double) MyRank; MPI_Send(Buffer_Pivot, NoofRows_Bloc*n_size+1+NoofRows_Bloc, MPI_DOUBLE, k, MyRank, MPI_COMM_WORLD); }

// back substitution //primeste de la toate procesoarele "sus" Buffer_bksub = (double *) malloc (NoofRows_Bloc * 2 * sizeof(double)); X_buffer = (double *) malloc (NoofRows_Bloc * sizeof(double)); for (k = MyRank+1; k<Numprocs; ++k) { MPI_Recv(Buffer_bksub, 2*NoofRows_Bloc, MPI_DOUBLE, k, k, MPI_COMM_WORLD,&status); for (i = NoofRows_Bloc-1; i >= 0; i--) { for (icol = NoofRows_Bloc-1;icol >= 0; icol--) { index = (int) Buffer_bksub[icol]; Y_buffer[i] -= Buffer_bksub[NoofRows_Bloc+icol] * ARecv[i*n_size+index]; } } for (i = NoofRows_Bloc-1; i >= 0; i--) { index = MyRank*NoofRows_Bloc+i; Buffer_bksub[i] = (double) index; Buffer_bksub[NoofRows_Bloc+i] = X_buffer[i] = Y_buffer[i]; for (j = i-1; j >= 0; j--) Y_buffer[j] -= X_buffer[i] * ARecv[j*n_size + index]; } }

//trimite catre toate procesoarele "jos" for (k = 0; k < MyRank; k++) MPI_Send(Buffer_bksub, 2*NoofRows_Bloc, MPI_DOUBLE, k, MyRank, MPI_COMM_WORLD); //aduna rezultatul in procesorul 0 Output = (double *) malloc (n_size * sizeof(double)); MPI_Gather(X_buffer, NoofRows_Bloc, MPI_DOUBLE, Output, NoofRows_Bloc, MPI_DOUBLE, 0, MPI_COMM_WORLD); if (MyRank == 0) { printf ("\n"); printf("Rezultate pe procesor %d: \n", MyRank); printf ("\n"); printf("Matrice A \n"); printf ("\n"); for (i = 0; i < n_size; i++) { for (j = 0; j < n_size; j++) printf("%.3lf ", matrice_A[i][j]); printf("\n"); } printf ("\n"); printf("Vector B \n");

printf("\n"); for (i = 0; i < n_size; i++) { printf("%.3lf\n", vector_B[i]); }

printf ("\n"); printf("Vectorul solutie\n"); printf ("\n"); for(i = 0; i < n_size; i++) printf("%.3lf\n",Output[i]); } getch(); //cleans up all MPI data structures, cancels operations that never completed MPI_Finalize(); }

Descrierea rutinelor MPI utilizate :


Structura generala a programelor MPI respecta urmatoarea forma: Fisierul MPI include; Initializarea MPI environment; Executie si apeluri pentru transferul de mesaje ; Inchiderea MPI environment;

Rutinele de administrare a mediului MPI sunt utilizate pentru definirea domeniilor, cum ar fi initializarea si incheierea mediului MPI, pentru chestionarea mediului si identificare etc. Rutinele utilizate in implementarea eliminarii Gauss sunt descrise in continuare.
MPI_Init int MPI_Init(int *argc, char ***argv);

Aceasta rutina initializeaza mediul de executie MPI returnand o eroare de cod in cazul in care a aparut o problema.Aceasta rutina trebuie sa fie apelata de catre un singur fir de executie,firul respectiv fiind si acela ce va executa MPI_Finalize.
int MPI_Comm_rank(MPI_Comm comm, int *rank);

Stabileste rangul procesului apelant in communicator.Initial, fiecarui proces i se atribuie un rang intreg unic intre 0 si numarul de procesoare cuprinse in comunicatorul MPI_COMM_WORLD.Daca un proces se asociaza cu alti comunicatori , el va avea un rang unic in fiecare din acesti comunicatori.
int MPI_Comm_size(MPI_Comm comm, int *size);

Stabileste numarul de procese intr-un grup asociat cu un communicator.In general se utilizeaza in comunicatorul MPI_COMM_WORLD pentru a determina numarul de procese utilizate de o aplicatie.
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype,int root, MPI_Comm comm);

Difuzeaza un mesaj de la procesul cu rang root catre toate celelalte procese din comunicator.
int MPI_Scatter (void *sendbuffer, int sendcount, MPI_Datatype sendtype,void *recvbuf,int
recvcount, MPI_Datatype recvtype,int root, MPI_Comm comm);

Distribuie mesajele distincte de la o singura sursa fiecarui proces din grup.


int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status);

Primeste un mesaj si blocheaza pana cand datele cerute sunt disponibile in bufferul de aplicatie din taskul receptor.
int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm);

Rutina efectueaza trimiterea cu blocare a unui mesaj. Rutina revine numai dupa ce bufferul de aplicatie din taskul expeditor este liber pentru refolosire.De retinut ca aceasta rutina poate fi implementata diferit pe sisteme diferite.
int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int
recvcnt, MPI_Datatype recvtype, int root, MPI_Comm comm);

Colecteaza mesajele distincte de la fiecare task din grup pentru un singur task destinatie.Este inversul rutinei MPI_Scatter.
int MPI_Finalize( void )

nceteaz executia mediului MPI.

Listingul aplicatiei paralelizate :

Pentru o matrice 4x4 :

Pentru o matrice 8x8 :

Concluzii :

Comparatia implementarilor : secvential vs. Paralel

Complexitatatea de timp pentru codul secvential este de O( Pentru p=n , complexitatea este de O(

); );

) iar costul este optim de O(

Echilibrarea incarcarii se poate inmbunatatii


procesoare ;

prin alocarea acciclica a liniilor la

Comparatia solutiilor : Cramer vs. Gauss

Timpul obtinut folosind metoda de rezolvare Cramer este tC =O(n !) ;


Timpul obtinut folosind metoda eliminarii Gauss este tG=O(
);

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