Skip to content
Snippets Groups Projects
Simplex.java 6.13 KiB
import java.util.Arrays;

public class Simplex {
    private Matrix matEcart;
    private Matrix tabAux;
    private int nbSousCondition;
    private int x;
    private int y;
    private int nbPivot;
    private static double EPSILON = 0E-7;
    private int nbContraintes;

    public Matrix getTabAux() {
        return tabAux;
    }

    public Matrix getMatEcart() {
        return matEcart;
    }

    public int getNbPivot() {
        return nbPivot;
    }

    public Simplex(int x, int y, int nbSousCondition, int nbContraintes) {
        this.x = x;
        this.y = y;
        this.matEcart = new Matrix(x, y);
        this.nbSousCondition = nbSousCondition;
        this.tabAux = new Matrix(x + 2, y + nbSousCondition + 1);
        this.nbPivot = 0;
        this.nbContraintes = nbContraintes;
    }

    void createSimplex(Equation eq, int nbContraintes) {
        // Matrice Amxn
        for (int i = 0; i < this.x; i++) {
            for (int j = 0; j < this.y; j++) {
                if (j < nbContraintes) {
                    this.matEcart.setData(i, j, eq.getMatAtId(i, j));
                } else {
                    this.matEcart.setData(i, j, j - nbContraintes == i ? 1.0 : 0.0);
                }
            }
        }

        // Membre de droite
        for (int i = 0; i <= this.x - 1; i++)
            this.matEcart.setData(i, this.y - 1, eq.getRightVec().get(i));

        // Fonction obj
        this.matEcart.matrixRealloc(this.matEcart.getX() + 1, this.matEcart.getY());
        for (int i = 0; i < nbContraintes; i++)
            this.matEcart.setData(this.x, i, eq.getFuncObj().get(i));
    }

    /**
     * Si b[i] < 0 phase 1 sinon phase 2
     *
     * @return true = phase 1 | false = phase 2
     */
    int which_phase() {
        int res = -1;
        for (int i = 0; i < this.x; i++) {
            if (signe(this.matEcart.getData(i, this.y - 1))) res = i;
        }
        return res;
    }

    void tabAux(int line) {
        double[] tabRes = new double[this.y + this.nbSousCondition + 1];
        Arrays.fill(tabRes, 1.0);
        for (int j = 0; j < this.y; j++) {
            if (this.matEcart.getData(line, j) != 0.0) {
                double res = this.matEcart.getData(line, j) * -1;
                this.matEcart.setData(line, j, res);
            }
            double tmpSum = 0;
            for (int i = 0; i < this.x; i++) {
                tmpSum += -1 * this.matEcart.getData(i, j);
            }
            tabRes[j] = tmpSum;
        }
        System.out.println();

        // -2 car => tabRes[(tabRes.length-1) - (this.nbSousCondition - 1)];
        tabRes[tabRes.length - 1] = tabRes[tabRes.length - this.nbSousCondition - 2];
        tabRes[tabRes.length - this.nbSousCondition - 2] = 0;
        for (int i = 0; i < this.tabAux.getX(); i++) {
            for (int j = 0; j < this.tabAux.getY(); j++) {
                if (i < this.matEcart.getX() && j < this.matEcart.getY())
                    this.tabAux.setData(i, j, this.matEcart.getData(i, j));

                else if (i == this.tabAux.getX() - 1)
                    this.tabAux.setData(i, j, tabRes[j]);

                else // membre de droite à la fin du tab
                    this.tabAux.setData(i, j, this.matEcart.getData(i, j - this.matEcart.getX()));
            }
        }
        this.tabAux.printTabAux("Tableau auxiliaire", this.nbContraintes, this.nbSousCondition, this.tabAux.getY() - this.matEcart.getY() - 1);
        pivot(this.tabAux);
        double solutionOptimale = this.tabAux.getData(this.tabAux.getX() - 1, this.tabAux.getY() - 1);
        if (solutionOptimale > 0 + EPSILON) {
            System.out.println("Il n'y a pas de solutions admissibles pour ce problème.");
        }
        if (solutionOptimale == 0) {
            // Il y a une solution optimale
            // Il faut enlever les variables auxilaires
            Matrix res = new Matrix(matEcart.getX(), matEcart.getY());
            res.matrixFill(res.getX(), res.getY(), tabAux.getDatas());
            res.matrixPrint("Petit tableau", 2);
            nbPivot = 0;
            pivot(res);
            res.matrixPrint("Résultat ", 3);
            System.out.println("Nombre de pivot : " + nbPivot);
        }
    }

    int getFirstNeg(Matrix mat) {
        for (int j = 0; j < mat.getY(); j++) {
            if (signe(mat.getData(mat.getX() - 1, j))) return j;
        }
        return -1;
    }

    void pivot(Matrix mat) {
        this.nbPivot += 1;
        int firstNeg = getFirstNeg(mat);
        if (firstNeg == -1) return; // si pas de négatif
        boolean has_neg = false;
        int id = ligneSortante(mat, firstNeg);
        double val_pivot = mat.getData(id, firstNeg);
        for (int i = 0; i < mat.getY(); i++) {
            mat.setData(id, i, mat.getData(id, i) / val_pivot);
        }
        for (int i = 0; i < mat.getX(); i++) {
            val_pivot = mat.getData(i, firstNeg);
            for (int j = 0; j < mat.getY(); j++) {
                if (i != id) {
                    mat.setData(i, j, mat.getData(i, j) - val_pivot * mat.getData(id, j));
                }
            }
        }
        mat.matrixPrint("Pivot numéro " + this.nbPivot, 2);
        for (int j = 0; j < mat.getY(); j++)
            if (signe(mat.getData(mat.getX() - 1, j))) {
                has_neg = true;
                if (has_neg) {
                    break;
                }
            }
        if (has_neg)
            pivot(mat);

    }


    // TODO : A REFAIRE POUR SWITCH DE Y AU CAS OU
    int ligneSortante(Matrix mat, int y) {
        int id = 0;
        while (!(mat.getData(id, y) > 0)) {
            id++;
        }
        double tmp = mat.getData(id, mat.getY() - 1) / mat.getData(id, y);
        double tmp_s;
        for (int i = 1; i < mat.getX() - 1; i++) {
            if (mat.getData(i, y) > 0) {
                tmp_s = mat.getData(i, mat.getY() - 1) / mat.getData(i, y);
                if (tmp_s < tmp) {
                    id = i;
                    tmp = tmp_s;
                }
            }
        }
        return id;
    }

    public void printSimplex(Matrix mat, String s, int precision) {
        mat.matrixPrint(s, precision);
    }

    boolean signe(Double x) {
        return x < 0;
    }
}