-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMatrix.java
More file actions
392 lines (353 loc) · 12.7 KB
/
Matrix.java
File metadata and controls
392 lines (353 loc) · 12.7 KB
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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
public class Matrix{
double[][] data;
String name;
/* Constructeur
* L'utilisateur donne un nombre de lignes et un nombre de colonnes.
* Permet de générer aléatoirement une matrice. Si rand == true
* Ou de générer une matrice nulle. Si rand == false */
public Matrix (int l, int n, String na, boolean rand) {
this.data = new double [l][n];
this.name = na;
if(rand) { //Génération aléatoire si rand==true. Sinon, génère une matrice nulle
for (int i=0;i<this.data.length;i++){
for (int j=0; j<this.data[i].length;j++){
this.data[i][j]=(int)((Math.random()*200)-100); //entre -99 et 99
}
}
}
}
// Returns ranked matrix
public Matrix rank() {
Matrix m01G = new Matrix(this.data.length, this.data[0].length, this.name+"_rank", false);
for (int i = 0; i < this.data.length; i++){
for (int j = 0; j < this.data[0].length; j++){
m01G.data[i][j] = this.data[i][j];
}
}
// Check if "pivot" is null, if yes, switch lines, else continue and rank
int ind = -1;
int j = 0;
double coef;
double temp;
for(int i = 0; i < m01G.data.length; i++){
ind = -1;
j = i;
while(j < m01G.data.length && ind != -1){
if(m01G.data[i][j] != 0){
ind = j;
}
j++;
}
if(ind == -1){
// Do nothing and waits for the next column
}else{
for(int k = 0; k < m01G.data[0].length; k++) {
temp = m01G.data[1][k];
m01G.data[i][k] = m01G.data[ind][k];
m01G.data[ind][k] = temp;
}
}
for(int l = i+1; l < m01G.data.length; l++){
coef = m01G.data[l][i]/m01G.data[i][i];
for(int m = i; m < m01G.data[0].length; m++){
m01G.data[l][m] = m01G.data[l][m]-m01G.data[i][m]*coef;
}
}
}
return m01G;
}
// Used for reversed matrix, returns reduced ranked matrix
public Matrix gaussJourdan() {
Matrix m01G = new Matrix(this.data.length, this.data[0].length, this.name+"_rankr", false);
for (int i = 0; i < this.data.length; i++){
for (int j = 0; j < this.data[0].length; j++){
m01G.data[i][j] = this.data[i][j];
}
}
int r = -1;
int k;
double max;
double temp;
double temp2;
double temp3;
for(int j = 0; j < m01G.data[0].length; j++) {
if((r+1) < m01G.data.length) {
// Look for a maximum
max = m01G.data[r+1][j];
k = r+1;
for(int i = r+2; i < m01G.data.length; i++) {
if(m01G.data[i][j] > max) {
max = m01G.data[i][j];
k = i;
}
}
if(m01G.data[k][j] != 0) {
r++;
// Divide k line
temp2 = m01G.data[k][j];
for(int i = 0; i < m01G.data[0].length; i++) {
m01G.data[k][i] = m01G.data[k][i]/temp2;
}
// Switching k and r lines
for(int i = 0; i < m01G.data[0].length; i++) {
temp = m01G.data[k][i];
m01G.data[k][i] = m01G.data[r][i];
m01G.data[r][i] = temp;
}
// Other lines simplified
for(int i = 0; i < m01G.data.length; i++) {
temp3 = m01G.data[i][j];
if(i != r) {
for(int h = 0; h < m01G.data[0].length; h++) {
m01G.data[i][h] = m01G.data[i][h]-(m01G.data[r][h]*temp3);
}
}
}
}
}
}
return m01G;
}
// Returns the reversed matrix using augemented matrix and gaussJourdan
public Matrix reverse(){
// Test square parameters and if det != 0 !
Matrix m01I = new Matrix(this.data.length, (this.data.length*2), "m01I", false);
Matrix reversed = new Matrix(this.data.length, this.data.length, this.name+"_rev", false);
// Copy of initial Matrix on the left side
for(int i = 0; i < this.data.length; i++){
for(int j = 0; j < this.data.length; j++){
m01I.data[i][j] = this.data[i][j];
}
}
// Copy of Identity Matrix on the right side
for(int i = 0; i < this.data.length; i++){
for(int j = (this.data.length-1); j < (this.data.length*2); j++){
if(i == (j-this.data.length)){
m01I.data[i][j] = 1;
}
}
}
// Calculations
m01I = m01I.gaussJourdan();
// Gathering only the reversed Matrix
for(int i = 0; i < this.data.length; i++){
for(int j = 0; j < this.data.length; j++){
reversed.data[i][j] = m01I.data[i][j+this.data.length];
}
}
return reversed;
}
// soustractions de 2 matrices
public Matrix subtract(Matrix m02){
if(this.data.length==m02.data.length && this.data[0].length==m02.data[0].length){
Matrix mResult = new Matrix(this.data.length,this.data[0].length, this.name+"_sub_"+m02.name, false);
for (int i=0;i<this.data.length;i++){
for (int j=0;j<this.data[0].length;j++){
mResult.data[i][j]=this.data[i][j]-m02.data[i][j];
}
}
return mResult;
}else{
return null;
}
}
// additions de 2 matrices
public Matrix add(Matrix m02){
if(this.data.length==m02.data.length && this.data[0].length==m02.data[0].length){
Matrix mResult = new Matrix(this.data.length,this.data[0].length, this.name+"_add_"+m02.name, false);
for (int i=0;i<this.data.length;i++){
for (int j=0;j<this.data[0].length;j++){
mResult.data[i][j]=this.data[i][j]+m02.data[i][j];
}
}
return mResult;
}else{
return null;
}
}
//division de matrice 1 par matrice 2 : multiplication par l'inverse de 1 par 2
public Matrix divide(Matrix m02){
if(this.testCarree() && m02.testCarree() && this.determinant() != 0 && m02.determinant() != 0) {
Matrix m01D = this.multiplyM(m02.reverse());
m01D.name = this.name+"_divBy_"+m02.name;
return m01D;
}else{
return null;
}
}
//Produit de 2 matrices
public Matrix multiplyM (Matrix m02){
if(this.data[0].length!=m02.data.length){ //Si le nombres de colonnes de la matrice n'est pas égale aux nombres de lignes de m02, retourne le pointeur null
return null;
}else{
Matrix mResult = new Matrix(this.data.length,m02.data[0].length, this.name+"_mulm_"+m02.name, false);
for (int i=0;i<mResult.data.length;i++){
for (int j=0;j<mResult.data[0].length;j++){
for (int n=0;n<this.data[0].length;n++){
mResult.data[i][j]+=this.data[i][n]*m02.data[n][j];
}
}
}
return mResult;
}
}
// produit d'une matrice par un scalaire
public Matrix multiplyS (int scalaire){
Matrix mResult = new Matrix(this.data.length, this.data[0].length, this.name+"_muls_"+scalaire, false);
for (int i=0;i<this.data.length;i++){
for (int j=0;j<this.data[0].length;j++){
mResult.data[i][j]=scalaire*this.data[i][j];
}
}
return mResult;
}
//Diagonalise une matrice 2*2 à partir des valeurs propres
public Matrix diagonalise(){
Matrix mdiagonal = new Matrix(2,2,this.name+"_diagonal",false);
mdiagonal.data[0][0]=eigenValues()[0];
mdiagonal.data[1][1]=eigenValues()[1];
return mdiagonal; // Si la matrice n'est pas 2*2, la classe MainMatrix gère l'erreur
}
//Matrices de passage. Ne sont pas "optimisées" mais permettent de décrire deux vecteurs pour former la méthode de passage
public Matrix passage(){
Matrix mPassage = new Matrix(2,2,this.name+"_passage",false);
mPassage.data[0][0]=1; // On fixe la première coordonnée à 1
mPassage.data[0][1]=1; // idem
mPassage.data[1][0]=-(this.data[0][0]-this.eigenValues()[0]); // solution générique de l'équation permettant de décrire les vecteurs propres
mPassage.data[1][1]=-(this.data[0][0]-this.eigenValues()[1]); // idem
return mPassage;
}
//calcul des valeurs propres pour les matrices 2*2
public double[] eigenValues(){
if(this.data.length==this.data[0].length && this.data.length == 2){ //teste si la matrice est de taille 2*2
double[] lambda;
double delta = Math.pow(this.trace(),2)-4*this.determinant();
if(delta>0){
lambda = new double[2];
lambda[0]=Math.max(((this.trace()+Math.sqrt(delta))/2),((this.trace()-Math.sqrt(delta))/2));
lambda[1]=Math.min(((this.trace()+Math.sqrt(delta))/2),((this.trace()-Math.sqrt(delta))/2));
}else{
if(delta==0){
lambda = new double[1];
lambda[0]=this.trace()/2;
}else{ //si le delta n'est pas nul ou n'est pas positif, alors il est négatif. Les valeurs propres sont donc complexes, et nous ne gérons pas les complexes
return null;
}
}
return lambda;
}else{ // si la matrice n'est pas 2*2, on renvoie le pointeur null. MainMatrix gère l'erreur
return null;
}
}
/* Permet d'extraire une "sous matrice" (voir compte rendu pour les aspects mathématiques)
* est utilisé pour le calcul du déterminant */
public Matrix getSousMatrice(int quelInd){
int n=0;
Matrix m01S = new Matrix (this.data.length-1,this.data.length-1, "m01S", false);
if (quelInd==-1){ //si la matrice est de taille 1*1 (voir code déterminant)
m01S=this; //le déterminant d'une matrice 1*1 est le terme lui-même
}else{
for (int i=0;i<this.data.length;i++){
for (int j=1;j<this.data.length;j++){ //On parcours le tableau depuis la 2ème colonne. (cofacteurs de j=0)
if(i!=quelInd){ // On supprime la ligne de cofacteurs de coordonnées i=quelInd et j=0
if(i<quelInd){ //Avant la ligne à supprimer : remplit le tableau en suivant i
m01S.data[i][j-1]=this.data[i][j];
}else{ // après la ligne à supprimer : remplit le tableau en suivant i+1
m01S.data[i-1][j-1]=this.data[i][j];
}
}
}
}
}
return m01S;
}
/* Calcul du déterminant
* utilisation des fonctions récursives
* voir le compte rendu pour l'explication algorithmique
*/
public double determinant(){ // ne fonctionne que pour les matrices carrées. Erreur gérée depuis la MainMatrix.
double d=0;
if(this.data.length == 1){ //"Première condition" : matrice de taille 1*1
d=this.getSousMatrice(-1).data[0][0];
}else{
for(int i=0;i<this.data.length;i++){
d+=(Math.pow(-1,i)*this.data[i][0]*getSousMatrice(i).determinant()); //Fonction récursive
}
}
return d;
}
// transposition : inverse lignes et colonnes
public Matrix transpose(){
Matrix m01T = new Matrix(this.data[0].length,this.data.length, this.name+"_trans", false);
for (int i=0;i<this.data.length;i++){
for (int j=0;j<this.data[0].length;j++){
m01T.data[j][i]=this.data[i][j];
}
}
return m01T;
}
/*calcul de la trace
* somme des éléments diagonaux
* pour les matrices carrées : erreur gérée depuis MainMatrix
*/
public double trace(){
double[] diagonal = this.getDiagonal();
double Trace = 0;
for (int i=0; i<diagonal.length;i++){
Trace = Trace + diagonal[i];
}
return Trace;
}
/* Extraire la colonne d'une matrice
* Renvoie un tableau 1D contenant une colonne de la matrice que l'utilisateur selectionnera
*/
public double[] getColumn(int whichColumn){
double[] Column = new double[this.data.length];
for (int i=0;i<Column.length;i++){
Column[i]=this.data[i][whichColumn];
}
return Column;
}
/* Extraire la ligne d'une matrice
* Renvoie un tableau 1D contenant une ligne de la matrice que l'utilisateur selectionnera
*/
public double[] getLine(int whichLine){
double[] line = new double[this.data[0].length];
for (int i=0;i<line.length;i++){
line[i]=this.data[whichLine][i];
}
return line;
}
/*Extraire la diagonale d'une matrice
* Renvoie un tableau 1D contenant la diagonale de la matrice
*/
public double[] getDiagonal() {
if(!this.testCarree()){ // Si la matrice n'est pas carrée, retourne le pointeur null
return null;
}else{
double[] diagonal = new double[this.data.length];
for (int i=0;i<diagonal.length;i++){
diagonal[i]=this.data[i][i];
}
return diagonal;
}
}
// Teste si la matrice est carrée
public boolean testCarree() {
if (this.data.length == this.data[0].length) {
return true;
}else{
return false;
}
}
//pour debug
/*public void afficheMatrice(){
for (int i=0;i<this.data.length;i++){
for (int j=0; j<this.data[i].length;j++){
System.out.print(this.data[i][j]+" ");
}
System.out.println();
}
System.out.println();
}*/
}