Vous êtes sur la page 1sur 10

Génie de l’Eau GE3 / 2012-2013

Sophia Antipolis - 19 Novembre 2012

l’Eau GE3 / 2012-2013 Sophia Antipolis - 19 Novembre 2012 Résolution de systèmes linéaires de très

Résolution de systèmes linéaires de très grande taille

Présenté par :

BLAVET Marion DAVID Thomas GOUNAND Emeline CHAILLOT Anthony

Alain OLIVETTI………………………………………………………………….Tuteur académique

Ecole Polytechnique de l’Université de Nice – Sophia Antipolis POLYTECH’NICE-SOPHIA Département Hydroinformatique et Ingénierie de l’Eau 1645, route des Lucioles – 06410 BIOT Cédex Tél. +33(0)492388550 – Fax +44(0)492388502 – hydro@polytech.unice.fr – www.polytech.unice.fr

Sommaire

1.Introduction

3

2.Le principe de la méthode de Gauss-Jordan

4

3.Le code en langage C de la méthode de Gauss

5

4.D’autres méthodes

8

5.Comparaison

9

6.Sources

10

2

1. Introduction

Un système d’équations est un ensemble de plusieurs équations comprenant les mêmes inconnues. Si le problème comporte n inconnues, alors n équations linéairement indépendantes sont nécessaires pour toutes les déterminer.

La résolution de systèmes de très grande taille est très courante dans les domaines scientifiques et ceux de l’ingénierie. C’est pourquoi il est important de connaître une ou plusieurs méthodes rapides, précises et efficaces de résolution. Il en existe plusieurs telles que la méthode de Gauss-Jordan, la décomposition de Choleski ou encore la décomposition de LU. Le principe de la méthode de Gauss- Jordan.

Dans notre cas, nous avons restreint notre étude aux systèmes linéaires et nous nous sommes intéressés plus particulièrement à la méthode de Gauss-Jordan car elle suit la méthode que nous utilisons pour résoudre un système « à la main ».

Après avoir présenté cette méthode et son code, nous l’avons testé sur plusieurs exemples et l’avons comparé avec les autres méthodes dont le code nous était donné afin d’évaluer ses performances.

3

2. Le principe de la méthode de Gauss-Jordan

En général, on écrit un système linéaire sous la forme suivante :

on écrit un système linéaire sous la forme suivante : Où x i sont les inconnues

Où x i sont les inconnues à déterminer et a m,n et b m sont des coefficients connus.

Mais pour un système de très grande taille, il est intéressant de l’écrire sous la

forme matricielle suivante :

Ax=B avec

l’écrire sous la forme matricielle suivante : Ax=B avec La méthode de Gauss-Jordan est simple puisqu’elle

La méthode de Gauss-Jordan est simple puisqu’elle retranscrit ce que nous faisons à la main pour résoudre ce problème.

Dans un premier temps, il faut triangulariser la matrice A tout en effectuant les mêmes opérations sur les lignes du vecteur b. Pour i>1 par exemple, les

ai1

a11

transformations L i = L i

L 1 . Le terme a 11 est le pivot de l’étape de l’algorithme. En réitérant le procédé, on aboutit à une matrice triangulaire :

L 1 éliminent l’inconnue x 1 dans les lignes autres que

En calcul numérique, pour minimiser les erreurs d’arrondi, on choisit comme pivot le terme le plus grand en valeur absolue en échangeant des lignes, ce qui n’a pas

4

d’influence sur le système. En effet, cela revient seulement à changer la place de deux équations dans le système.

Enfin, il reste à résoudre : a nn ’ X n = b n ’ . On peut ainsi connaître X n que l’on reporte dans la ligne n-a où la seule inconnue n’est plus que X n-1 etc.

3. Le code en langage C de la méthode de Gauss

#include<stdio.h> #include <stdlib.h> #include<math.h>

//Initialisation des matrices

struct matrix

{

int nbLigne, nbColonne; double **cases;

};

struct matrix matrixCreation(int nbLigne, int nbColonne)

{

struct matrix M; M.nbLigne=nbLigne; M.nbColonne=nbColonne; int i;

M.cases=(double**) malloc(nbLigne*sizeof(double*)); for (i=0;i<M.nbLigne;i++)

{

M.cases[i]=(double*) malloc(nbColonne*sizeof(double));

}

return M;

}

void matrixAfficheMatrice(struct matrix Input)

{

 

int i=0,j=0;

for(i=0;i<Input.nbLigne;i++)

{

for(j=0;j<Input.nbColonne;j++)

{

printf("%lg " ,Input.cases[i][j]);

}

printf("\n");

}

}

// Fonction Permutation : permet de permuter deux lignes dans une matrice

5

void Permutation(struct matrix M,int Ligne1,int Ligne2)

{

// Initialisation d'un tableau pour stocker temporairement une ligne de matrice que l’on souhaite déplacer int Temp[M.nbLigne];

int j; for (j=0;j<=M.nbLigne;j++)

{

 

Temp[j]=M.cases[Ligne1][j];

M.cases[Ligne1][j]=M.cases[Ligne2][j];

M.cases[Ligne2][j]=Temp[j];

}

}

//Fonction du plus grand pivot : compare les pivots et choisit le plus grand coefficient en valeur absolue

void PlusGrandPivot(struct matrix M,struct matrix B,int i)

{

 

int max,j=i; max=M.cases[i][i];

for (i;i<M.nbLigne;i++)

{

if (abs(M.cases[i][j])>max)

{

max=abs(M.cases[i][j]);

Permutation(M,i,j);

Permutation(B,i,j);

}

}

}

//Fonction de Gauss : permet de faire les calculs pour avoir des zéros sous la diagonale

void Gauss(struct matrix M,struct matrix B,int i)

{

int j,I=i,temp; //I est la ligne du Pivot, on la fixe for (i;i<M.nbLigne-1;i++) //On parcourt les lignes

{

temp=M.cases[i+1][I];

for (j=I;j<M.nbColonne;j++) //Puis les colonnes

{

M.cases[i+1][j]=M.cases[i+1][j]*M.cases[I][I]-temp*M.cases[I][j]; // Afin d'annuler les coefficients sous le pivot

}

B.cases[i+1][0]=B.cases[i+1][0]*M.cases[I][I]-temp*B.cases[I][0]; //

On applique les mêmes calculs sur la matrice B

}

}

//Fonction Résolution du système

void Resolution(struct matrix M, struct matrix B,struct matrix X)

{

int i=M.nbLigne-1,j;

X.cases[M.nbLigne-1][0]=B.cases[i][0]/M.cases[i][i];

6

for (i=i-1;i!=-1;i--) {

X.cases[i][0]=B.cases[i][0];

for (j=i+1;j<=M.nbLigne-1;j++)

{

X.cases[i][0]-=M.cases[i][j]*X.cases[j][0];

}

X.cases[i][0]=X.cases[i][0]/M.cases[i][i];

}

}

int main()

{

int n; struct matrix X; struct matrix N;

n=3;

N=matrixCreation(n,n); struct matrix B;

X=matrixCreation(N.nbLigne,1);

B=matrixCreation(N.nbLigne,1);

{ //Remplissage des matrices

B.cases[0][0]=5;

B.cases[1][0]=-5;

B.cases[2][0]=0;

N.cases[0][0]=4;

N.cases[0][1]=2;

N.cases[0][2]=-1;

N.cases[1][0]=2;

N.cases[1][1]=1;

N.cases[1][2]=2;

N.cases[2][0]=-1;

N.cases[2][1]=2;

N.cases[2][2]=4;

X.cases[0][0]=0;

X.cases[1][0]=0;

X.cases[2][0]=0;

}

printf("Matrice N de départ\n"); matrixAfficheMatrice(N); printf("\n"); printf("Matrice B de départ\n"); matrixAfficheMatrice(B); printf("\n"); printf("Calcul du pivot en cours\n"); int i; time_t start, stop; start=time(NULL);

for (i=0;i<N.nbLigne-1;i++) //Permet de balayer toutes les lignes

{

 

PlusGrandPivot(N,B,i);

Gauss(N,B,i);

}

//Ici ce sont les sorties du pivot de Gauss

printf("Matrice N de fin\n");

7

matrixAfficheMatrice(N); printf("\n"); printf("Matrice B de fin\n"); matrixAfficheMatrice(B); printf("\n"); Resolution(N,B,X); stop=time(NULL); printf("\n"); printf("Solution du système : \n"); matrixAfficheMatrice(X); printf("\nTemps d'execution : %d s.\n" ,(int)(stop-start)); return 0;

8

}

4. D’autres méthodes

La factorisation LU consiste à écrire une matrice non-singulière A comme le

produit de deux autres matrices L et U . L est une matrice triangulaire inférieure ayant des 1 sur la diagonale et U une matrice triangulaire supérieure.

On notera les éléments de ces deux matrices de la manière suivante:

les éléments de ces deux matrices de la manière suivante: Supposons maintenant que nous connaissons la

Supposons maintenant que nous connaissons la factorisation LU de la matrice A. Ainsi, le

systè me Ax = b peut se r éé crire LU x = b. Posons

z = U x. Nous avons donc que Lz = b. Ce syst è me est rapide à r é soudre, car la matrice L est triangulaire inf érieure. Voici l’algorithme pour trouver z, dit la substitution avant.

Algorithme de substitution avant

Algorithme de substitution avant Il ne reste plus que r é soudre le syst è me

Il ne reste plus que r é soudre le syst è me U x = z. Il ne faut pas oublier que U est une matrice triangulaire sup é rieure. Ceci est la substitution arri è re qui est la m ê me que la deuxi è me partie de l’algorithme de Gauss.

Algorithme de substitution arri è re

de Gauss. Algorithme de substitution arri è re 5. Comparaison Nombre d’op é rations Nous obtenons

5. Comparaison

Nombre d’op é rations

Nous obtenons ainsi le vecteur x. Comme nous l’avons mentionn é plus t ôt, ce qui est important de savoir pour comparer deux algorithmes, c’est le nombre de multiplication et de division demand é par chacun. C’est ces op é rations qui demandent plus grand temps de calcul à l’ordinateur, l’addition et la soustraction sont beaucoup plus rapide.

La premi è re é tape du pivot de Gauss­Jordan demande de transformer une matrice initial en une matrice triangulaire sup é rieure, ce qui am ène à multiplier les él é ments de la matrice par des coefficients puis de soustraire les ligne entres elles.

9

La deuxi è me é tape (la substitution arri è re) demande moins d'op é ration mais contient tout de m ê me des multiplications/divisions.

Comptons le nombre d’op é ration de ces deux algorithmes. Pour la substitution arri è re, il y a autant d'op é ration que pour la m é thode de Gauss­Jordan cependant la substitution avant est nettement simplifi é e du fait de la position des 1 sur la diagonale é vitant ainsi la division par ces coefficients à chaque ligne.

Il en r é sulte que le comptage des op érations nous permet de conclure que si nous

connaissons la factorisation LU et que n est grand, il est plus plus rapide d’utiliser la

m é thode de factorisation LU , que la m é thode de Gauss.

6. Sources

10