Skip to content
Snippets Groups Projects
Commit 9c0c2cd1 authored by thibault.capt's avatar thibault.capt
Browse files

Merge remote-tracking branch 'origin/main' into main

# Conflicts:
#	src/META-INF/MANIFEST.MF
parents e0c27ead a6d00dcc
No related branches found
No related tags found
No related merge requests found
......@@ -10,4 +10,12 @@ Pour exécuter le code:
```java -jar tp-math.jar```
Le programme demande intéractivement le nom du fichier d'entrée. Ce dernier doit être un fichier .txt.
Le programme demande également si l'on veut activer ou non le deboguage.
Les fichiers d'input doivent se trouver dans un dossier src depuis l'endroit où l'on exécute la commande de lancement.
Exemple :
J'utilise la commande depuis le dossier Bureau, il doit donc y avoir un dossier Bureau/src qui contient les fichiers d'input.
Le code se situe dans le dossier ```src/```
......@@ -15,79 +15,75 @@ footnotes-pretty: true
## Choix du langage
Nous avons donc utilisé le Java afin de résoudre ce travail pratique. En effet, python est un langage qui est très lent
à l'exécution, car celui-ci est un langage **interprété**. Nous pouvons ainsi essayer de gagner du temps d'exécution pour
la résolution du problème.
Nous avons donc utilisé le Java afin de résoudre ce travail pratique. En effet, python est un langage qui est très lent à l'exécution, car celui-ci est un langage **interprété**. Nous pouvons ainsi essayer de gagner du temps d'exécution pour la résolution du problème.
## Astuces utilisées
Ensuite, dans la plupart des cas, nous avons utilisé des **array** à 1 ou 2 dimension(s) qui
est bien plus rapide que les Listes Java. (https://stackoverflow.com/questions/716597/array-or-list-in-java-which-is-faster).
Nous avons aussi opté pour que l'utilisateur puisse choisir un mode débogage ou non, ce qui permet de supprimer presque
tous les prints en mode non-débogage et gagner énormément de temps d'exécution.
Nous avons aussi opté pour que l'utilisateur puisse choisir un mode débogage ou non, ce qui permet de supprimer presque tous les prints en mode non-débogage et gagner énormément de temps d'exécution.
Nous commençons également à calculer le temps d'exécution après le retour du parser, soit au début des appels de fonctions du simplex, et nous terminons le calcul avant l'affichage des résultats. Nous faisons ce choix car l'affichage de matrice est assez gourmand en temps et cela se remarque de plus en plus en fonction de la taille de la matrice et du fichier original.
## Analyse des performances
Nous avons reçu plusieurs fichiers à tester pour vérifier le bon fonctionnement de notre code (nous approfondirons les
résultats à "null" dans les problèmes rencontrés) :
Nous avons reçu plusieurs fichiers à tester pour vérifier le bon fonctionnement de notre code.
Temps d'exécution et pivots : Méthode 2 / Méthode 1 (Les méthodes sont expliquées un peu plus bas)
- input.txt
- lp_glaces.txt
- Valeur obj : -34.25
- nombre de pivots : 2
- Temps d'exécution : 17ms
- input_test.txt
- Valeur obj : null
- nombre de pivots : null
- Temps d'exécution : null
- input_test2.txt
- Valeur obj : null
- nombre de pivots : null
- Temps d'exécution : null
- inputNonAdmissible.txt
- nombre de pivots : 3 / 2
- Temps d'exécution : 1ms / 0ms
- lp_test_non_admissible.txt
- Valeur obj : -34.25
- nombre de pivots : 3
- Temps d'exécution : 20ms
- flow_1.txt
- Valeur obj : 78768
- nombre de pivots : 9
- Temps d'exécution : 33ms
- nombre de pivots : 5 / 8
- Temps d'exécution : 1ms / 1ms
- lp_test.txt
- Valeur obj : 4.500000000000015
- nombre de pivots : 11 / 16
- Temps d'exécution : 1ms / 0ms
- lp_test2.txt
- Valeur obj : ~
- nombre de pivots : ~ / ~
- Temps d'exécution : ~ / ~
- Ce fichier ne nous retourne pas de résultat.
- network1.txt
- Valeur obj : 78768
- nombre de pivots : 9
- Temps d'exécution : 30ms
- Valeur obj : 78768.0
- nombre de pivots : 22 / 26
- Temps d'exécution : 4ms / 5ms
- network2.txt
- Valeur obj : 0
- nombre de pivots : 10
- Temps d'exécution : 55ms
- Valeur obj : -0.0
- nombre de pivots : 31 / 34
- Temps d'exécution : 17ms / 18ms
- network3.txt
- Valeur obj : 84077
- nombre de pivots : 45
- Temps d'exécution : 162ms
- Valeur obj : 84077.0
- nombre de pivots : 132 / 183
- Temps d'exécution : 45ms / 46ms
- network4.txt
- Valeur obj : null
- Nombre de pivots : null
- Temps d'exécution : null
- Valeur obj : 188508.0
- Nombre de pivots : 1049 / 2628
- Temps d'exécution : 227ms / 369ms
- network5.txt
- Valeur obj : NaN
- Nombre de pivots: 1255
- Temps d'exécution : 26066ms
- Valeur obj : 123542.0
- Nombre de pivots: 4074 / ~
- Temps d'exécution : 9114ms / ~
Le temps d'exécution est, dans l'ensemble, assez faible, bien qu'il soit encore possible de l'améliorer.
Une grande amélioration du temps que nous avons pu constater est la manière de choisir le négatif lors du choix du pivot. En effet nous pouvons choisir cela de deux manières différentes.
En premier lieu nous pouvons choisir le 1er négatif rencontré. Ce qui marche très bien pour les problèmes ne comportant pas une trop grande taille. Cependant avec cette méthode, le network5 nous retourne une boucle infinie.
En second lieu, nous pouvons choisir de comparer les négatifs obtenus et choisir le pivot sur la ligne du plus petit négatif recontré. De cette manière , tout d'abord le network5 nous retourne un résultat, mais en plus les autres input voient une diminution du temps d’exécution. C'est donc pour cela que nous choisissons donc cette méthode par défaut et notre jar généré utilise donc cette 2ème méthode.
## Problèmes rencontrés
Nous avons rencontré plusieurs problèmes au cours de ce travail pratique.
Premièrement, lors de la phase 1, nous ne gérions pas tous les négatifs des membres de droite. En effet, nous passions
en paramètre la ligne où nous trouvions un négatif et remplaçait cette ligne en question. Le problème étant que s'il y
avait plusieurs négatifs dans les membres de droite, il y resterait.
Premièrement, lors de la phase 1, nous ne gérions pas tous les négatifs des membres de droite. En effet, nous passions en paramètre la ligne où nous trouvions un négatif et remplacions la ligne en question. Le problème étant que s'il y avait plusieurs négatifs dans les membres de droite, ils y resteraient.
Deuxièmement et n'est pas résolu, nous pouvons voir que nous avons des résultats à null. En effet, ce problème survient
lorsque notre résultat du tableau auxiliaire de la phase 1 (avant le pivot) est négatif. Par exemple, prenons le fichier
input_test, nous ne trouvons pas de résultat. Nous avons essayé de changer la valeur de notre epsilon (initialement à
1E-7) mais cela n'y change rien.
Deuxièmement , nous avons utilisé pendant la quasi intégralité du temps imparti la première méthode de sélection du pivot (négatif décrits au dessus). Nous n'avions donc aucun résultat pour network5 ainsi que pour certains autres fichiers de tests que nous testions. En changeant cette méthode par la seconde, nous avons donc maintenant un résultat, qui nous l'espérons, est correct.
Troisièmement, le fichier network5 affiche des NaN (not a number). Il y a donc des divisions par 0 quelque part pour ce
fichier. Le problème est qu'il y a ~1400 pivots pour ce fichier et ainsi le débogage est bien trop long pour regarder
pivot par pivot.
Troisièmement, en jouant un peu avec notre epsilon, nous avons constaté que nous pouvions parfois obtenir des résultats différents. Par exemple, le fichier lp_test.txt nous retourne le bon résultat quand notre epsilon vaut 1e-7 (qui est notre valeur par défaut que nous utilisons depuis le début et que nous avons choisie arbitrairement) . Si nous dépassons 1e14, nous remarquons que nous n'obtenons plus de résultat pour ce fichier. Il s'agit surement de la valeur de la solution optimale en phase 1 qui n'est plus considérée à partir de cette valeur. Il pourrait aussi s'agir d'un dépassement de floating après la virgule mais nous n'en sommes vraiment pas sur.
<<<<<<< HEAD
Manifest-Version: 1.0
Main-Class: Main
=======
Manifest-Version: 1.0
Main-Class: Main
>>>>>>> origin/main
......@@ -53,8 +53,7 @@ public class Main {
default -> System.err.println("Une erreur a été détectée lors de la saisie du débogage");
}
// Calcule du temps d'exécution et création de l'équation
long start = System.nanoTime();
//création de l'équation
Scanner sc = new Scanner(f);
String[] elements;
int sousCondition = nbSc(sc), line = 0;
......@@ -85,13 +84,15 @@ public class Main {
line++;
}
// Print
eq.printEq();
if (debugging) eq.printEq();
// Début du calcul du temps d'exécution
long start = System.nanoTime();
// Tableau initial
Simplex spx = new Simplex(eq.getMat().getLine(), eq.getMat().getLine() + eq.getMat().getCol() + 1,
line, contraintes, debugging);
spx.createSimplex(eq, contraintes);
if(debugging) spx.printSimplex(spx.getMatEcart(), "Tableau initial");
if (debugging) spx.printSimplex(spx.getMatEcart(), "Tableau initial");
// true = phase 1 membres de droite pas admissible | false = phase 2 membres de droite admissible
if (spx.which_phase()) {
......@@ -106,7 +107,7 @@ public class Main {
// Juste le pivot sur la matrice d'écart
spx.pivot(spx.getMatEcart(), false);
// Si mode débogue, afficher chaque pivot
if(debugging) {
if (debugging) {
spx.printSimplex(spx.getMatEcart(), "Résultat");
System.out.println("Nombre de pivot: " + spx.getNbPivot());
}
......
......@@ -8,7 +8,7 @@ public class Simplex {
private final int ligne; // Ligne
private final int colonne; // Colonne
private int nbPivot;
private static final double EPSILON = 1E-20;
private static final double EPSILON = 1E-7;
private final int nbContraintes;
public Matrix getMatEcart() {
......@@ -21,11 +21,12 @@ public class Simplex {
/**
* Constructeur du simplex
* @param ligne le nombre de lignes dans le tableau initial
* @param colonne le nombre de colonnes dans le tableau initial
*
* @param ligne le nombre de lignes dans le tableau initial
* @param colonne le nombre de colonnes dans le tableau initial
* @param nbSousCondition le nombre de sous condition
* @param nbContraintes le nombre de contraintes
* @param debugging mode de debug
* @param nbContraintes le nombre de contraintes
* @param debugging mode de debug
*/
public Simplex(int ligne, int colonne, int nbSousCondition, int nbContraintes, boolean debugging) {
this.ligne = ligne;
......@@ -40,7 +41,8 @@ public class Simplex {
/**
* Crée la matrice d'écart pour le début de la résolution du simplex (transformation du tableau initial en matrice)
* @param eq Equation retournée par le parser
*
* @param eq Equation retournée par le parser
* @param nbContraintes nombre de contraintes
*/
void createSimplex(Equation eq, int nbContraintes) {
......@@ -56,16 +58,14 @@ public class Simplex {
}
// Ajout des membres de droites
for (int i = 0; i <= this.ligne - 1; i++)
{
for (int i = 0; i <= this.ligne - 1; i++) {
this.matEcart.setData(i, this.colonne - 1, eq.getRightVec().get(i));
}
// Ajout de la fonction objective
this.matEcart.matrixRealloc(this.matEcart.getLine() + 1, this.matEcart.getCol());
for (int i = 0; i < nbContraintes; i++)
{
for (int i = 0; i < nbContraintes; i++) {
this.matEcart.setData(this.ligne, i, eq.getFuncObj().get(i));
}
}
......@@ -85,6 +85,7 @@ public class Simplex {
/**
* Phase 1
*
* @return le résultat du pivot
*/
Matrix tabAux() {
......@@ -144,7 +145,6 @@ public class Simplex {
// remplir la nouvelle matrice avec les valeurs de la matrice auxiliaire, mais dans la taille de la matrice d'écart
res.matrixFill(res.getLine(), res.getCol(), tabAux.getDatas());
if (debugging) res.matrixPrint("Petit tableau");
nbPivot = 0; // reset du nombre de pivots, on pourrait implémenter un pivot de phase 1 et un pivot de phase 2
// retour a la phase 2 avec le pivot sur la nouvelle matrice
pivot(res, true);
if (debugging) {
......@@ -158,22 +158,40 @@ public class Simplex {
/**
* Sélectionne le premier négatif rencontré sur la ligne de la fonction objective
*
* @param mat la matrice
* @return la colonne du premier négatif rencontré
*/
int getFirstNeg(Matrix mat) {
for (int j = 0; j < mat.getCol() - 1; j++) {
// Méthode 1 : premier négatif
/*for (int j = 0; j < mat.getCol() - 1; j++) {
if (signe(mat.getData(mat.getLine() - 1, j))) return j;
}
return -1;
return -1;*/
// Méthode 2 : plus petit négatif
int id = -1;
double tmpVal = 0;
double val = 0;
for (int j = 0; j < mat.getCol() - 1; j++) {
tmpVal = mat.getData(mat.getLine() - 1, j);
if (signe(tmpVal)) {
if (val > tmpVal) {
val = tmpVal;
id = j;
}
}
}
return id;
}
/**
* Fonction de pivot
* @param mat phase 1 ⇒ tableau auxiliaire | phase 2 => Matrice d'écart
*
* @param mat phase 1 ⇒ tableau auxiliaire | phase 2 => Matrice d'écart
* @param phase true => phase 1 | false => phase 2
*/
void pivot(Matrix mat, boolean phase) {
void pivot(Matrix mat, boolean phase) {
this.nbPivot += 1;
// Ligne du négatif
int firstNeg = getFirstNeg(mat);
......@@ -183,7 +201,6 @@ public class Simplex {
int id = ligneSortante(mat, firstNeg, phase);
// Selection de la valeur du pivot
double val_pivot = mat.getData(id, firstNeg);
// Application du pivot de gauss sur la ligne du pivot, pour avoir une "référence" de coefficient pour la suite
for (int i = 0; i < mat.getCol(); i++) {
mat.setData(id, i, mat.getData(id, i) / val_pivot);
......@@ -216,8 +233,9 @@ public class Simplex {
/**
* Récupérer l'id de la ligne du pivot
* @param mat le tableau auxiliaire
* @param y la colonne où l'on va chercher le pivot
*
* @param mat le tableau auxiliaire
* @param y la colonne où l'on va chercher le pivot
* @param phase la phase dans laquelle on se situe
* @return l'id de la ligne du pivot
*/
......@@ -229,7 +247,7 @@ public class Simplex {
int id = 0;
// La première vérification permet de s'assurer qu'on ne tombe pas sur un 0
// La 2ᵉ vérification permet de vérifier qu'au plus profond de la matrice il s'agit bien d'un négatif
while (!(mat.getData(id, y) > 0) && mat.getData(id, depth) >= 0) {
while (!(mat.getData(id, y) > 0)) {
id++;
}
......@@ -256,8 +274,9 @@ public class Simplex {
/**
* Print les informations des matrices pour le mode débogage
*
* @param mat la matrice souhaitée
* @param s le titre
* @param s le titre
*/
public void printSimplex(Matrix mat, String s) {
mat.matrixPrint(s);
......@@ -265,34 +284,43 @@ public class Simplex {
/**
* Print du résultat comme dans l'énnoncé
* @param m la matrice
*
* @param m la matrice
* @param time le temps de l'exécution
*/
public void resultPrint(Matrix m, long time) {
if(m == null) {
if (m == null) {
System.out.println("Impossible d'écrire une matrice nulle...");
return;
}
int line = m.getLine() - 1;
int col = m.getCol() - 1;
System.out.println("-------------------Solution-------------------");
System.out.println("Status: Optimal");
System.out.format("Size: %d rows, %d cols\n", m.getLine(), m.getCol());
System.out.println("Obj value: " + -1 * m.getData(line, col));
System.out.println("Nombre de pivot(s) réalisé(s) sur le petit tableau post phase 1: " + this.nbPivot);
System.out.println("Time: " + time + " ms");
System.out.println("-------------------Variables------------------");
System.out.println("Variables:");
for (int i = 0; i < line; i++) {
System.out.format("X[%d]: = %.4f \n", i, m.getData(i, col));
if (m.getData(i, col) != 0.0)
System.out.format("X[%d]: = %.4f \n", i, m.getData(i, col));
}
for (int i = 0; i < col; i++) {
System.out.format("Z_Cstr_%d: = %.4f \n", i, m.getData(line, i));
if (m.getData(line, i) != 0.0)
System.out.format("Z_Cstr_%d: = %.4f \n", i, m.getData(line, i));
}
System.out.println("-------------------Solution-------------------");
System.out.println("Status: Optimal");
System.out.format("Size: %d rows, %d cols\n", m.getLine(), m.getCol());
System.out.println("Obj value: " + -1 * m.getData(line, col));
System.out.println("Nombre de pivot(s) : " + this.nbPivot);
System.out.println("Time: " + time + " ms");
}
/**
* Retourne True ou False en fonction du signe, True si négatif
*
* @param x La valeur
* @return True si négatif
*/
boolean signe(Double x) {
return x < 0;
}
......
min;17;43;35;47;83;75;
1;0;0;0;0;0;<=;758;
0;1;0;0;0;0;<=;798;
0;0;1;0;0;0;<=;758;
0;0;0;1;0;0;<=;270;
0;0;0;0;1;0;<=;758;
0;0;0;0;0;1;<=;758;
-1;-1;0;0;0;1;=;-758;
1;0;-1;-1;0;0;=;0;
0;1;1;0;-1;-1;=;0;
0;0;0;1;1;0;=;758;
\ No newline at end of file
File moved
File moved
File moved
File moved
File deleted
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment