Buggy code:
//*  * Licensed to the Apache Software Foundation (ASF) under one or more  * contributor license agreements.  See the NOTICE file distributed with  * this work for additional information regarding copyright ownership.  * The ASF licenses this file to You under the Apache License, Version 2.0  * (the "License"); you may not use this file except in compliance with  * the License.  You may obtain a copy of the License at  *  *      http: *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  *//  package org.apache.commons.math3.optimization.linear;  import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set;  import org.apache.commons.math3.linear.Array2DRowRealMatrix; import org.apache.commons.math3.linear.MatrixUtils; import org.apache.commons.math3.linear.RealMatrix; import org.apache.commons.math3.linear.RealVector; import org.apache.commons.math3.optimization.GoalType; import org.apache.commons.math3.optimization.PointValuePair; import org.apache.commons.math3.util.Precision;  //**  * A tableau for use in the Simplex method.  *  * <p>  * Example:  * <pre>  *   W |  Z |  x1 |  x2 |  x- | s1 |  s2 |  a1 |  RHS  * ---------------------------------------------------  *  -1    0    0     0     0     0     0     1     0   &lt;= phase 1 objective  *   0    1   -15   -10    0     0     0     0     0   &lt;= phase 2 objective  *   0    0    1     0     0     1     0     0     2   &lt;= constraint 1  *   0    0    0     1     0     0     1     0     3   &lt;= constraint 2  *   0    0    1     1     0     0     0     1     4   &lt;= constraint 3  * <//pre>  * W: Phase 1 objective function<//br>  * Z: Phase 2 objective function<//br>  * x1 &amp; x2: Decision variables<//br>  * x-: Extra decision variable to allow for negative values<//br>  * s1 &amp; s2: Slack//Surplus variables<//br>  * a1: Artificial variable<//br>  * RHS: Right hand side<//br>  * <//p>  * @version $Id$  * @since 2.0  *// class SimplexTableau implements Serializable {      //** Column label for negative vars. *//     private static final String NEGATIVE_VAR_COLUMN_LABEL = "x-";      //** Default amount of error to accept in floating point comparisons (as ulps). *//     private static final int DEFAULT_ULPS = 10;      //** Serializable version identifier. *//     private static final long serialVersionUID = -1369660067587938365L;      //** Linear objective function. *//     private final LinearObjectiveFunction f;      //** Linear constraints. *//     private final List<LinearConstraint> constraints;      //** Whether to restrict the variables to non-negative values. *//     private final boolean restrictToNonNegative;      //** The variables each column represents *//     private final List<String> columnLabels = new ArrayList<String>();      //** Simple tableau. *//     private transient RealMatrix tableau;      //** Number of decision variables. *//     private final int numDecisionVariables;      //** Number of slack variables. *//     private final int numSlackVariables;      //** Number of artificial variables. *//     private int numArtificialVariables;      //** Amount of error to accept when checking for optimality. *//     private final double epsilon;      //** Amount of error to accept in floating point comparisons. *//     private final int maxUlps;      //**      * Build a tableau for a linear problem.      * @param f linear objective function      * @param constraints linear constraints      * @param goalType type of optimization goal: either {@link GoalType#MAXIMIZE}      * or {@link GoalType#MINIMIZE}      * @param restrictToNonNegative whether to restrict the variables to non-negative values      * @param epsilon amount of error to accept when checking for optimality      *//     SimplexTableau(final LinearObjectiveFunction f,                    final Collection<LinearConstraint> constraints,                    final GoalType goalType, final boolean restrictToNonNegative,                    final double epsilon) {         this(f, constraints, goalType, restrictToNonNegative, epsilon, DEFAULT_ULPS);     }      //**      * Build a tableau for a linear problem.      * @param f linear objective function      * @param constraints linear constraints      * @param goalType type of optimization goal: either {@link GoalType#MAXIMIZE}      * or {@link GoalType#MINIMIZE}      * @param restrictToNonNegative whether to restrict the variables to non-negative values      * @param epsilon amount of error to accept when checking for optimality      * @param maxUlps amount of error to accept in floating point comparisons      *//     SimplexTableau(final LinearObjectiveFunction f,                    final Collection<LinearConstraint> constraints,                    final GoalType goalType, final boolean restrictToNonNegative,                    final double epsilon,                    final int maxUlps) {         this.f                      = f;         this.constraints            = normalizeConstraints(constraints);         this.restrictToNonNegative  = restrictToNonNegative;         this.epsilon                = epsilon;         this.maxUlps                = maxUlps;         this.numDecisionVariables   = f.getCoefficients().getDimension() +                                       (restrictToNonNegative ? 0 : 1);         this.numSlackVariables      = getConstraintTypeCounts(Relationship.LEQ) +                                       getConstraintTypeCounts(Relationship.GEQ);         this.numArtificialVariables = getConstraintTypeCounts(Relationship.EQ) +                                       getConstraintTypeCounts(Relationship.GEQ);         this.tableau = createTableau(goalType == GoalType.MAXIMIZE);         initializeColumnLabels();     }      //**      * Initialize the labels for the columns.      *//     protected void initializeColumnLabels() {       if (getNumObjectiveFunctions() == 2) {         columnLabels.add("W");       }       columnLabels.add("Z");       for (int i = 0; i < getOriginalNumDecisionVariables(); i++) {         columnLabels.add("x" + i);       }       if (!restrictToNonNegative) {         columnLabels.add(NEGATIVE_VAR_COLUMN_LABEL);       }       for (int i = 0; i < getNumSlackVariables(); i++) {         columnLabels.add("s" + i);       }       for (int i = 0; i < getNumArtificialVariables(); i++) {         columnLabels.add("a" + i);       }       columnLabels.add("RHS");     }      //**      * Create the tableau by itself.      * @param maximize if true, goal is to maximize the objective function      * @return created tableau      *//     protected RealMatrix createTableau(final boolean maximize) {                  int width = numDecisionVariables + numSlackVariables +         numArtificialVariables + getNumObjectiveFunctions() + 1;         int height = constraints.size() + getNumObjectiveFunctions();         Array2DRowRealMatrix matrix = new Array2DRowRealMatrix(height, width);                  if (getNumObjectiveFunctions() == 2) {             matrix.setEntry(0, 0, -1);         }         int zIndex = (getNumObjectiveFunctions() == 1) ? 0 : 1;         matrix.setEntry(zIndex, zIndex, maximize ? 1 : -1);         RealVector objectiveCoefficients =             maximize ? f.getCoefficients().mapMultiply(-1) : f.getCoefficients();         copyArray(objectiveCoefficients.toArray(), matrix.getDataRef()[zIndex]);         matrix.setEntry(zIndex, width - 1,             maximize ? f.getConstantTerm() : -1 * f.getConstantTerm());          if (!restrictToNonNegative) {             matrix.setEntry(zIndex, getSlackVariableOffset() - 1,                 getInvertedCoefficientSum(objectiveCoefficients));         }                  int slackVar = 0;         int artificialVar = 0;         for (int i = 0; i < constraints.size(); i++) {             LinearConstraint constraint = constraints.get(i);             int row = getNumObjectiveFunctions() + i;                          copyArray(constraint.getCoefficients().toArray(), matrix.getDataRef()[row]);                          if (!restrictToNonNegative) {                 matrix.setEntry(row, getSlackVariableOffset() - 1,                     getInvertedCoefficientSum(constraint.getCoefficients()));             }                          matrix.setEntry(row, width - 1, constraint.getValue());                          if (constraint.getRelationship() == Relationship.LEQ) {                 matrix.setEntry(row, getSlackVariableOffset() + slackVar++, 1);              } else if (constraint.getRelationship() == Relationship.GEQ) {                 matrix.setEntry(row, getSlackVariableOffset() + slackVar++, -1);             }                          if ((constraint.getRelationship() == Relationship.EQ) ||                     (constraint.getRelationship() == Relationship.GEQ)) {                 matrix.setEntry(0, getArtificialVariableOffset() + artificialVar, 1);                 matrix.setEntry(row, getArtificialVariableOffset() + artificialVar++, 1);                 matrix.setRowVector(0, matrix.getRowVector(0).subtract(matrix.getRowVector(row)));             }         }          return matrix;     }      //**      * Get new versions of the constraints which have positive right hand sides.      * @param originalConstraints original (not normalized) constraints      * @return new versions of the constraints      *//     public List<LinearConstraint> normalizeConstraints(Collection<LinearConstraint> originalConstraints) {         List<LinearConstraint> normalized = new ArrayList<LinearConstraint>();         for (LinearConstraint constraint : originalConstraints) {             normalized.add(normalize(constraint));         }         return normalized;     }      //**      * Get a new equation equivalent to this one with a positive right hand side.      * @param constraint reference constraint      * @return new equation      *//     private LinearConstraint normalize(final LinearConstraint constraint) {         if (constraint.getValue() < 0) {             return new LinearConstraint(constraint.getCoefficients().mapMultiply(-1),                                         constraint.getRelationship().oppositeRelationship(),                                         -1 * constraint.getValue());         }         return new LinearConstraint(constraint.getCoefficients(),                                     constraint.getRelationship(), constraint.getValue());     }      //**      * Get the number of objective functions in this tableau.      * @return 2 for Phase 1.  1 for Phase 2.      *//     protected final int getNumObjectiveFunctions() {         return this.numArtificialVariables > 0 ? 2 : 1;     }      //**      * Get a count of constraints corresponding to a specified relationship.      * @param relationship relationship to count      * @return number of constraint with the specified relationship      *//     private int getConstraintTypeCounts(final Relationship relationship) {         int count = 0;         for (final LinearConstraint constraint : constraints) {             if (constraint.getRelationship() == relationship) {                 ++count;             }         }         return count;     }      //**      * Get the -1 times the sum of all coefficients in the given array.      * @param coefficients coefficients to sum      * @return the -1 times the sum of all coefficients in the given array.      *//     protected static double getInvertedCoefficientSum(final RealVector coefficients) {         double sum = 0;         for (double coefficient : coefficients.toArray()) {             sum -= coefficient;         }         return sum;     }      //**      * 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++) {             final double entry = getEntry(i, col);             if (Precision.equals(entry, 1d, maxUlps) && (row == null)) {                 row = i;             } else if (!Precision.equals(entry, 0d, maxUlps)) {                 return null;             }         }         return row;     }      //**      * Removes the phase 1 objective function, positive cost non-artificial variables,      * and the non-basic artificial variables from this tableau.      *//     protected void dropPhase1Objective() {         if (getNumObjectiveFunctions() == 1) {             return;         }          List<Integer> columnsToDrop = new ArrayList<Integer>();         columnsToDrop.add(0);                  for (int i = getNumObjectiveFunctions(); i < getArtificialVariableOffset(); i++) {             final double entry = tableau.getEntry(0, i);             <START_BUG> if (Precision.compareTo(entry, 0d, maxUlps) > 0) { <END_BUG>                 columnsToDrop.add(i);             }         }                  for (int i = 0; i < getNumArtificialVariables(); i++) {           int col = i + getArtificialVariableOffset();           if (getBasicRow(col) == null) {             columnsToDrop.add(col);           }         }          double[][] matrix = new double[getHeight() - 1][getWidth() - columnsToDrop.size()];         for (int i = 1; i < getHeight(); i++) {           int col = 0;           for (int j = 0; j < getWidth(); j++) {             if (!columnsToDrop.contains(j)) {               matrix[i - 1][col++] = tableau.getEntry(i, j);             }           }         }          for (int i = columnsToDrop.size() - 1; i >= 0; i--) {           columnLabels.remove((int) columnsToDrop.get(i));         }          this.tableau = new Array2DRowRealMatrix(matrix);         this.numArtificialVariables = 0;     }      //**      * @param src the source array      * @param dest the destination array      *//     private void copyArray(final double[] src, final double[] dest) {         System.arraycopy(src, 0, dest, getNumObjectiveFunctions(), src.length);     }      //**      * Returns whether the problem is at an optimal state.      * @return whether the model has been solved      *//     boolean isOptimal() {         for (int i = getNumObjectiveFunctions(); i < getWidth() - 1; i++) {             final double entry = tableau.getEntry(0, i);             if (Precision.compareTo(entry, 0d, epsilon) < 0) {                 return false;             }         }         return true;     }      //**      * Get the current solution.      *      * @return current solution      *//     protected PointValuePair getSolution() {       int negativeVarColumn = columnLabels.indexOf(NEGATIVE_VAR_COLUMN_LABEL);       Integer negativeVarBasicRow = negativeVarColumn > 0 ? getBasicRow(negativeVarColumn) : null;       double mostNegative = negativeVarBasicRow == null ? 0 : getEntry(negativeVarBasicRow, getRhsOffset());        Set<Integer> basicRows = new HashSet<Integer>();       double[] coefficients = new double[getOriginalNumDecisionVariables()];       for (int i = 0; i < coefficients.length; i++) {           int colIndex = columnLabels.indexOf("x" + i);           if (colIndex < 0) {             coefficients[i] = 0;             continue;           }           Integer basicRow = getBasicRow(colIndex);           if (basicRow != null && basicRow == 0) {                                                         coefficients[i] = 0;           } else if (basicRows.contains(basicRow)) {                                           coefficients[i] = 0 - (restrictToNonNegative ? 0 : mostNegative);           } else {               basicRows.add(basicRow);               coefficients[i] =                   (basicRow == null ? 0 : getEntry(basicRow, getRhsOffset())) -                   (restrictToNonNegative ? 0 : mostNegative);           }       }       return new PointValuePair(coefficients, f.getValue(coefficients));     }      //**      * Subtracts a multiple of one row from another.      * <p>      * After application of this operation, the following will hold:      *   minuendRow = minuendRow - multiple * subtrahendRow      * <//p>      * @param dividendRow index of the row      * @param divisor value of the divisor      *//     protected void divideRow(final int dividendRow, final double divisor) {         for (int j = 0; j < getWidth(); j++) {             tableau.setEntry(dividendRow, j, tableau.getEntry(dividendRow, j) // divisor);         }     }      //**      * Subtracts a multiple of one row from another.      * <p>      * After application of this operation, the following will hold:      *   minuendRow = minuendRow - multiple * subtrahendRow      * <//p>      * @param minuendRow row index      * @param subtrahendRow row index      * @param multiple multiplication factor      *//     protected void subtractRow(final int minuendRow, final int subtrahendRow,                                final double multiple) {         tableau.setRowVector(minuendRow, tableau.getRowVector(minuendRow)             .subtract(tableau.getRowVector(subtrahendRow).mapMultiply(multiple)));     }      //**      * Get the width of the tableau.      * @return width of the tableau      *//     protected final int getWidth() {         return tableau.getColumnDimension();     }      //**      * Get the height of the tableau.      * @return height of the tableau      *//     protected final int getHeight() {         return tableau.getRowDimension();     }      //** Get an entry of the tableau.      * @param row row index      * @param column column index      * @return entry at (row, column)      *//     protected final double getEntry(final int row, final int column) {         return tableau.getEntry(row, column);     }      //** Set an entry of the tableau.      * @param row row index      * @param column column index      * @param value for the entry      *//     protected final void setEntry(final int row, final int column,                                   final double value) {         tableau.setEntry(row, column, value);     }      //**      * Get the offset of the first slack variable.      * @return offset of the first slack variable      *//     protected final int getSlackVariableOffset() {         return getNumObjectiveFunctions() + numDecisionVariables;     }      //**      * Get the offset of the first artificial variable.      * @return offset of the first artificial variable      *//     protected final int getArtificialVariableOffset() {         return getNumObjectiveFunctions() + numDecisionVariables + numSlackVariables;     }      //**      * Get the offset of the right hand side.      * @return offset of the right hand side      *//     protected final int getRhsOffset() {         return getWidth() - 1;     }      //**      * Get the number of decision variables.      * <p>      * If variables are not restricted to positive values, this will include 1      * extra decision variable to represent the absolute value of the most      * negative variable.      * <//p>      * @return number of decision variables      * @see #getOriginalNumDecisionVariables()      *//     protected final int getNumDecisionVariables() {         return numDecisionVariables;     }      //**      * Get the original number of decision variables.      * @return original number of decision variables      * @see #getNumDecisionVariables()      *//     protected final int getOriginalNumDecisionVariables() {         return f.getCoefficients().getDimension();     }      //**      * Get the number of slack variables.      * @return number of slack variables      *//     protected final int getNumSlackVariables() {         return numSlackVariables;     }      //**      * Get the number of artificial variables.      * @return number of artificial variables      *//     protected final int getNumArtificialVariables() {         return numArtificialVariables;     }      //**      * Get the tableau data.      * @return tableau data      *//     protected final double[][] getData() {         return tableau.getData();     }      //** {@inheritDoc} *//     @Override     public boolean equals(Object other) {        if (this == other) {         return true;       }        if (other instanceof SimplexTableau) {           SimplexTableau rhs = (SimplexTableau) other;           return (restrictToNonNegative  == rhs.restrictToNonNegative) &&                  (numDecisionVariables   == rhs.numDecisionVariables) &&                  (numSlackVariables      == rhs.numSlackVariables) &&                  (numArtificialVariables == rhs.numArtificialVariables) &&                  (epsilon                == rhs.epsilon) &&                  (maxUlps                == rhs.maxUlps) &&                  f.equals(rhs.f) &&                  constraints.equals(rhs.constraints) &&                  tableau.equals(rhs.tableau);       }       return false;     }      //** {@inheritDoc} *//     @Override     public int hashCode() {         return Boolean.valueOf(restrictToNonNegative).hashCode() ^                numDecisionVariables ^                numSlackVariables ^                numArtificialVariables ^                Double.valueOf(epsilon).hashCode() ^                maxUlps ^                f.hashCode() ^                constraints.hashCode() ^                tableau.hashCode();     }      //** Serialize the instance.      * @param oos stream where object should be written      * @throws IOException if object cannot be written to stream      *//     private void writeObject(ObjectOutputStream oos)         throws IOException {         oos.defaultWriteObject();         MatrixUtils.serializeRealMatrix(tableau, oos);     }      //** Deserialize the instance.      * @param ois stream from which the object should be read      * @throws ClassNotFoundException if a class in the stream cannot be found      * @throws IOException if object cannot be read from the stream      *//     private void readObject(ObjectInputStream ois)       throws ClassNotFoundException, IOException {         ois.defaultReadObject();         MatrixUtils.deserializeRealMatrix(this, "tableau", ois);     } } 


Fix:
if (Precision.compareTo(entry, 0d, epsilon) > 0) {