1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
| #include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "fonction.h"
#include "../Operations_de_base/GOperations_matrice_de_base.h"
#define LimiteMax 1e-10//define à modifier en fonction des nombres traité dans la matrice si ceux ci très petit
#define LimiteMin -1e-10
struct Matrice *Inverse(struct Matrice *matrice)
{
int n, i, j, k , l, g, cPi = 0, cPj = 0, MatriceNonInversible = 0;
double Pivot = 0.0, C;
//Allocation dynamique pour les deux matrices Mb et Ib ainsi que pour les differents tableaux de coordonnées
Matrice *Mb, *Ib = NULL, *I, *M;
M = CreerMatrice(matrice->nbreligne,matrice->nbrecolonne);
/*On copie la matrice "matrice" entrée en paramètre dans une matrice M pour pouvoir conserver notre
matrice de base*/
for (i = 0; i < matrice->nbreligne; i++)
{
for (j = 0; j < matrice->nbrecolonne; j++)
{
M->matrice[i][j] = matrice->matrice[i][j];
}
}
//Allocation pour les autres matrice dont nous aurons besoin
Mb = CreerMatrice(M->nbreligne,M->nbrecolonne);
Ib = CreerMatrice(M->nbreligne,M->nbrecolonne);
I = CreerMatrice(M->nbreligne,M->nbrecolonne);
/*Tableau contenant les lignes de recherche de pivot encore valable
initialiser à 1, dès qu'une ligne et colonne sera mobilisé par un pivot
les tableaux prendrons la valeur 0 aux coordonnées correspondante aux pivot*/
int *iPivotpossible = malloc(M->nbreligne*sizeof(int));
int *jPivotpossible = malloc(M->nbrecolonne*sizeof(int));
//Tableaux de coordonnées d'échange de ligne
int *iechange = malloc (M->nbreligne*sizeof(int));
int *jechange = malloc (M->nbrecolonne*sizeof(int));
//On verifie que tout les pointeurs sont différents de NULL
if (Mb != NULL && Ib != NULL && I != NULL && iPivotpossible != NULL && jPivotpossible != NULL && iechange != NULL && jechange != NULL)
{
//Initialisation des tableau à la valeur 1
for (i = 0; i < M->nbreligne; i++)
{
iPivotpossible[i] = 1;
}
for (i = 0; i < M->nbrecolonne; i++)
{
jPivotpossible[i] = 1;
}
//Initialisation de la matrice identité
for (i = 0; i < M->nbreligne; i++)
{
for(j = 0; j < M->nbreligne; j++)
{
if (i != j)
{
I->matrice[i][j] = 0;
}
else
{
I->matrice[i][j] = 1;
}
}
}
//Début de l'inversion de la matrice
/*Etape 1 : Recherche du pivot, en choisissant la valeur la plus grande
parmis les valeurs permise restantes*/
for (n = 0; n < M->nbreligne; n++) //Le nombre d'itterration est toujours <= à la dimension de la matrice
{
printf("\n\nn = %d",n);
printf("\n"); //print de controle de l'iteration en cours
if (MatriceNonInversible != 1)
{
for (k = 0; k < M->nbreligne; k++) //On parcourt le tableau des coordonnées i des pivots restant
{
for (l = 0; l < M->nbrecolonne; l++) //On parcourt le tableau des coordonnées j des pivots restant
{
//Condition d'entrée dans la boucle : coordonnées possible pour le pivot
if (iPivotpossible[k] != 0 && jPivotpossible[l] != 0)
{
/*Comparaison d'une valeur absolu possible avec la valeur absolu
du pivot déjà en mémoire, si plus grand la valeur devient le pivot*/
if (fabs(M->matrice[k][l]) > fabs(Pivot))
{
Pivot = M->matrice[k][l];
cPi = k; //On garde en mémoire la valeur des coordonnées du dernier pivot trouvé
cPj = l;
}
}
}
}
if (Pivot > LimiteMin && Pivot < LimiteMax)
/*Condition de non inversibilité de la matrice si le
pivotmax est nul alors on ne peu pas inverser la matrice*/
{
MatriceNonInversible = 1;
//Le programme doit se terminer ici on libère la mémoire
DetruireMatrice(M);
DetruireMatrice(Mb);
DetruireMatrice(I);
DetruireMatrice(Ib);
free(iPivotpossible);
free(jPivotpossible);
free(iechange);
free(jechange);
Ib = NULL;
}
else
{
iPivotpossible[cPi] = 0;//On remplace la valeur 1 par 0 à la coordonée i
jPivotpossible[cPj] = 0;//On remplace la valaur 1 par 0 à la coordonée j
printf("\nPivot = %f",Pivot);//print de controle des pivots trouvés
Pivot = 0;//On réinitialise le pivot pour l'iteration n suivante
//Etape 2 : Début de l'inversion de la matrice
for (i = 0; i < M->nbreligne; i++)//On parcour les éléments de matrices
{
C = (M->matrice[i][cPj])/(M->matrice[cPi][cPj]);/*On rentre le cooeficient lié au pivot qui permetent
de mettre les autres valeurs de la même colonne à 0*/
printf("\nC = %f", C);//print de controle
for (j = 0; j < M->nbrecolonne; j++)//On parcour en j
{
if (i != cPi)//Pour les lignes différentes de la ligne du pivot
{
M->matrice[i][j] = M->matrice[i][j] - C*(M->matrice[cPi][j]);/*On effectue ces transformation pour amener les
autres nombres de la colone du pivot à 0*/
I->matrice[i][j] = I->matrice[i][j] - C*(I->matrice[cPi][j]);/*Même opérations sur la matrice identité*/
}
}
}
}
}
}//ici nous sortons de la boucle lié à n, les ittérations sont toutes faites
if (MatriceNonInversible != 1)
{
//Etape 3 : On remet les lignes dans le bon ordre, pour cela on les places dans de nouvelles matrices
//On commence par remplacer les valeurs très proche de 0 dût au quelques résidu des dévisions par 0
for (i = 0; i < M->nbreligne; i++)
{
for (j = 0; j < M->nbreligne; j++)
{
if (M->matrice[i][j] > LimiteMin && M->matrice[i][j] < LimiteMax)
{
M->matrice[i][j] = 0;
}
}
}
/*On cherche les valeurs non nuls, grace à leurs coordonées de colonne j on les replace au bonne endroit
dans une nouvelle matrice c'est à dire à la coordonée jj, on en profite pour ranger les coordonnés
de lignes et de colonnes dans deux tableaux, Ces tableaux nous permetterons de remetre la matrice I
dans l'ordres :
Exemple : iechange[i] = 1
jechange[i] = 2
alors cela signifie que la ligne 1 de Is dois se trouver en réalité à la ligne 2.*/
for (i = 0; i < M->nbreligne; i++)
{
for (j = 0; j < M->nbreligne; j++)
{
if (M->matrice[i][j] != 0)
{
Mb->matrice[j][j] = M->matrice[i][j];
iechange[i] = i;
jechange[i] = j;
}
}
}
/*On effectue les changements de ligne sur la matrice I*/
for (g = 0; g < M->nbreligne; g++)
{
for (j = 0; j < M->nbrecolonne; j++)
{
Ib->matrice[jechange[g]][j] = I->matrice[iechange[g]][j];
}
}
/*On divise chaque ligne de Ib pas l'unique élément non nul de Mb de la même ligne
on obtient donc la matrice inverse de M dans Ib*/
for (i = 0; i < Ib->nbreligne; i++)
{
for (j = 0; j < Ib->nbrecolonne; j++)
{
Ib->matrice[i][j] = Ib->matrice[i][j]/(Mb->matrice[i][i]);
}
}
//On libère toute la mémoire alloué
DetruireMatrice(M);
DetruireMatrice(Mb);
DetruireMatrice(I);
free(iPivotpossible);
free(jPivotpossible);
free(iechange);
free(jechange);
}
}
return Ib;
} |
Partager