/** * Checks whether the given column is basic. * @param col index of the column to check * @return the row that the variable is basic in. null if the column is not basic */ protected Integer getBasicRow(final int col) { Integer row = null; for (int i = 0; i < getHeight(); i++) { if (MathUtils.equals(getEntry(i, col), 1.0, epsilon) && (row == null)) { row = i; } else if (!MathUtils.equals(getEntry(i, col), 0.0, epsilon)) { return null; } } return row; }
/** * Returns the column with the most negative coefficient in the objective function row. * @param tableau simple tableau for the problem * @return column with the most negative coefficient */ private Integer getPivotColumn(SimplexTableau tableau) { double minValue = 0; Integer minPos = null; for (int i = tableau.getNumObjectiveFunctions(); i < tableau.getWidth() - 1; i++) { if (MathUtils.compareTo(tableau.getEntry(0, i), minValue, epsilon) < 0) { minValue = tableau.getEntry(0, i); minPos = i; } } return minPos; }
/** * Checks whether the given column is basic. * @param col index of the column to check * @return the row that the variable is basic in. null if the column is not basic */ protected Integer getBasicRow(final int col) { Integer row = null; for (int i = 0; i < getHeight(); i++) { if (MathUtils.equals(getEntry(i, col), 1.0, epsilon) && (row == null)) { row = i; } else if (!MathUtils.equals(getEntry(i, col), 0.0, epsilon)) { return null; } } return row; }
/** * Returns the column with the most negative coefficient in the objective function row. * @param tableau simple tableau for the problem * @return column with the most negative coefficient */ private Integer getPivotColumn(SimplexTableau tableau) { double minValue = 0; Integer minPos = null; for (int i = tableau.getNumObjectiveFunctions(); i < tableau.getWidth() - 1; i++) { if (MathUtils.compareTo(tableau.getEntry(0, i), minValue, epsilon) < 0) { minValue = tableau.getEntry(0, i); minPos = i; } } return minPos; }
double minRatio = Double.MAX_VALUE; for (int i = tableau.getNumObjectiveFunctions(); i < tableau.getHeight(); i++) { final double rhs = tableau.getEntry(i, tableau.getWidth() - 1); final double entry = tableau.getEntry(i, col); if (MathUtils.compareTo(entry, 0, epsilon) > 0) { final double ratio = rhs / entry; for (int i = 0; i < tableau.getNumArtificialVariables(); i++) { int column = i + tableau.getArtificialVariableOffset(); if (MathUtils.equals(tableau.getEntry(row, column), 1, epsilon) && row.equals(tableau.getBasicRow(column))) { return row;
int negativeVarColumn = columnLabels.indexOf(NEGATIVE_VAR_COLUMN_LABEL); Integer negativeVarBasicRow = negativeVarColumn > 0 ? getBasicRow(negativeVarColumn) : null; double mostNegative = negativeVarBasicRow == null ? 0 : getEntry(negativeVarBasicRow, getRhsOffset()); basicRows.add(basicRow); coefficients[i] = (basicRow == null ? 0 : getEntry(basicRow, getRhsOffset())) - (restrictToNonNegative ? 0 : mostNegative);
double minRatio = Double.MAX_VALUE; for (int i = tableau.getNumObjectiveFunctions(); i < tableau.getHeight(); i++) { final double rhs = tableau.getEntry(i, tableau.getWidth() - 1); final double entry = tableau.getEntry(i, col); if (MathUtils.compareTo(entry, 0, epsilon) > 0) { final double ratio = rhs / entry; for (int i = 0; i < tableau.getNumArtificialVariables(); i++) { int column = i + tableau.getArtificialVariableOffset(); if (MathUtils.equals(tableau.getEntry(row, column), 1, epsilon) && row.equals(tableau.getBasicRow(column))) { return row;
int negativeVarColumn = columnLabels.indexOf(NEGATIVE_VAR_COLUMN_LABEL); Integer negativeVarBasicRow = negativeVarColumn > 0 ? getBasicRow(negativeVarColumn) : null; double mostNegative = negativeVarBasicRow == null ? 0 : getEntry(negativeVarBasicRow, getRhsOffset()); basicRows.add(basicRow); coefficients[i] = (basicRow == null ? 0 : getEntry(basicRow, getRhsOffset())) - (restrictToNonNegative ? 0 : mostNegative);
/** * Runs one iteration of the Simplex method on the given model. * @param tableau simple tableau for the problem * @throws OptimizationException if the maximal iteration count has been * exceeded or if the model is found not to have a bounded solution */ protected void doIteration(final SimplexTableau tableau) throws OptimizationException { incrementIterationsCounter(); Integer pivotCol = getPivotColumn(tableau); Integer pivotRow = getPivotRow(tableau, pivotCol); if (pivotRow == null) { throw new UnboundedSolutionException(); } // set the pivot element to 1 double pivotVal = tableau.getEntry(pivotRow, pivotCol); tableau.divideRow(pivotRow, pivotVal); // set the rest of the pivot column to 0 for (int i = 0; i < tableau.getHeight(); i++) { if (i != pivotRow) { double multiplier = tableau.getEntry(i, pivotCol); tableau.subtractRow(i, pivotRow, multiplier); } } }
/** * Runs one iteration of the Simplex method on the given model. * @param tableau simple tableau for the problem * @throws OptimizationException if the maximal iteration count has been * exceeded or if the model is found not to have a bounded solution */ protected void doIteration(final SimplexTableau tableau) throws OptimizationException { incrementIterationsCounter(); Integer pivotCol = getPivotColumn(tableau); Integer pivotRow = getPivotRow(tableau, pivotCol); if (pivotRow == null) { throw new UnboundedSolutionException(); } // set the pivot element to 1 double pivotVal = tableau.getEntry(pivotRow, pivotCol); tableau.divideRow(pivotRow, pivotVal); // set the rest of the pivot column to 0 for (int i = 0; i < tableau.getHeight(); i++) { if (i != pivotRow) { double multiplier = tableau.getEntry(i, pivotCol); tableau.subtractRow(i, pivotRow, multiplier); } } }
/** * Solves Phase 1 of the Simplex method. * @param tableau simple tableau for the problem * @exception OptimizationException if the maximal number of iterations is * exceeded, or if the problem is found not to have a bounded solution, or * if there is no feasible solution */ protected void solvePhase1(final SimplexTableau tableau) throws OptimizationException { // make sure we're in Phase 1 if (tableau.getNumArtificialVariables() == 0) { return; } while (!tableau.isOptimal()) { doIteration(tableau); } // if W is not zero then we have no feasible solution if (!MathUtils.equals(tableau.getEntry(0, tableau.getRhsOffset()), 0, epsilon)) { throw new NoFeasibleSolutionException(); } }
/** * Solves Phase 1 of the Simplex method. * @param tableau simple tableau for the problem * @exception OptimizationException if the maximal number of iterations is * exceeded, or if the problem is found not to have a bounded solution, or * if there is no feasible solution */ protected void solvePhase1(final SimplexTableau tableau) throws OptimizationException { // make sure we're in Phase 1 if (tableau.getNumArtificialVariables() == 0) { return; } while (!tableau.isOptimal()) { doIteration(tableau); } // if W is not zero then we have no feasible solution if (!MathUtils.equals(tableau.getEntry(0, tableau.getRhsOffset()), 0, epsilon)) { throw new NoFeasibleSolutionException(); } }