diff --git a/src/Simplex.java b/src/Simplex.java index 2fe6e0c0aa40fbbd1da652fdee19ba4af81875f4..9be215c526f27e70345f202d1da237324e6b585b 100644 --- a/src/Simplex.java +++ b/src/Simplex.java @@ -19,6 +19,14 @@ public class Simplex { return nbPivot; } + /** + * Constructeur du simplex + * @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 + */ public Simplex(int ligne, int colonne, int nbSousCondition, int nbContraintes, boolean debugging) { this.ligne = ligne; this.colonne = colonne; @@ -30,6 +38,11 @@ public class Simplex { this.debugging = debugging; } + /** + * 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 nbContraintes nombre de contraintes + */ void createSimplex(Equation eq, int nbContraintes) { // Matrice Amxn for (int i = 0; i < this.ligne; i++) { @@ -42,17 +55,23 @@ public class Simplex { } } - // Membre de droite + // Ajout des membres de droites for (int i = 0; i <= this.ligne - 1; i++) + { this.matEcart.setData(i, this.colonne - 1, eq.getRightVec().get(i)); + } + - // Fonction obj + // Ajout de la fonction objective this.matEcart.matrixRealloc(this.matEcart.getLine() + 1, this.matEcart.getCol()); for (int i = 0; i < nbContraintes; i++) + { this.matEcart.setData(this.ligne, i, eq.getFuncObj().get(i)); + } } /** + * Choix de la phase * Si b[i] < 0 phase 1 sinon phase 2 * * @return true = phase 1 | false = phase 2 @@ -64,10 +83,15 @@ public class Simplex { return false; } + /** + * Phase 1 + * @return le résultat du pivot + */ Matrix tabAux() { if (debugging) System.out.println(); double[] tabRes = new double[this.colonne + this.nbSousCondition + 1]; Arrays.fill(tabRes, 1.0); + // Regarde si un membre de droite est négatif, si c'est le cas, on inverse toute la ligne for (int i = 0; i < this.colonne; i++) { for (int j = 0; j < this.ligne; j++) { if (this.matEcart.getData(j, this.colonne - 1) < 0) { @@ -77,6 +101,7 @@ public class Simplex { } } } + // Calcul des coûts for (int j = 0; j < this.colonne; j++) { double tmpSum = 0; for (int i = 0; i < this.ligne; i++) { @@ -86,6 +111,7 @@ public class Simplex { } // -2 car => tabRes[(tabRes.length-1) - (this.nbSousCondition - 1)]; + // Création du tableau auxiliaire tabRes[tabRes.length - 1] = tabRes[tabRes.length - this.nbSousCondition - 2]; tabRes[tabRes.length - this.nbSousCondition - 2] = 0; for (int i = 0; i < this.tabAux.getLine(); i++) { @@ -103,18 +129,23 @@ public class Simplex { if (debugging) this.tabAux.printTabAux("Tableau auxiliaire", this.nbContraintes, this.nbSousCondition, this.tabAux.getCol() - this.matEcart.getCol() - 1); + // Pivotage sur le tableau auxiliaire pivot(this.tabAux, true); double solutionOptimale = this.tabAux.getData(this.tabAux.getLine() - 1, this.tabAux.getCol() - 1); + // Si la solution optimale est positive, pas de solutions if (solutionOptimale > EPSILON) { System.out.println("Il n'y a pas de solutions admissibles pour ce problème."); } + // si la solution optimale est ~= 0, il faut pivoter sur le "petit tableau" if (Math.abs(solutionOptimale) < EPSILON || solutionOptimale == 0) { // Il y a une solution optimale. // Il faut enlever les variables auxilaires - Matrix res = new Matrix(matEcart.getLine(), matEcart.getCol()); + Matrix res = new Matrix(matEcart.getLine(), matEcart.getCol()); // pour récupérer la taille de la matrice d'écart + // 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; + 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) { res.matrixPrint("Matrice Résultat "); @@ -125,6 +156,11 @@ public class Simplex { return null; } + /** + * 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++) { if (signe(mat.getData(mat.getLine() - 1, j))) return j; @@ -133,21 +169,27 @@ public class Simplex { } /** - * @param mat Matrix + * Fonction de pivot + * @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) { this.nbPivot += 1; + // Ligne du négatif int firstNeg = getFirstNeg(mat); if (firstNeg == -1) return; // si pas de négatif boolean has_neg = false; + // Selection de la colonne du pivot 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); } + // Application du pivot de gauss sur toute la matrice (sauf la ligne du pivot précédemment appliquée) for (int i = 0; i < mat.getLine(); i++) { val_pivot = mat.getData(i, firstNeg); for (int j = 0; j < mat.getCol(); j++) { @@ -162,6 +204,7 @@ public class Simplex { System.out.println("ligne du pivot: " + id); System.out.println("Valeur du pivot: " + val_pivot); } + // Vérification des variables en bases, si un négatif est trouvé, on peut relancer la phase 2, les opérations sont terminées for (int j = 0; j < mat.getCol(); j++) if (signe(mat.getData(mat.getLine() - 1, j))) { has_neg = true;