Beispiel #1
0
 /* 120:    */
 /* 121:    */ public PointValuePair doOptimize()
     /* 122:    */ throws MaxCountExceededException, UnboundedSolutionException,
         NoFeasibleSolutionException
       /* 123:    */ {
   /* 124:187 */ SimplexTableau tableau =
       new SimplexTableau(
           getFunction(),
           getConstraints(),
           getGoalType(),
           restrictToNonNegative(),
           this.epsilon,
           this.maxUlps);
   /* 125:    */
   /* 126:    */
   /* 127:    */
   /* 128:    */
   /* 129:    */
   /* 130:    */
   /* 131:    */
   /* 132:195 */ solvePhase1(tableau);
   /* 133:196 */ tableau.dropPhase1Objective();
   /* 134:198 */ while (!tableau.isOptimal()) {
     /* 135:199 */ doIteration(tableau);
     /* 136:    */ }
   /* 137:201 */ return tableau.getSolution();
   /* 138:    */ }
Beispiel #2
0
 /**
  * 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;
 }
Beispiel #3
0
 /** {@inheritDoc} */
 @Override
 public RealPointValuePair doOptimize() throws OptimizationException {
   final SimplexTableau tableau =
       new SimplexTableau(f, constraints, goalType, restrictToNonNegative, epsilon);
   solvePhase1(tableau);
   tableau.discardArtificialVariables();
   while (!isOptimal(tableau)) {
     doIteration(tableau);
   }
   return tableau.getSolution();
 }
Beispiel #4
0
 /**
  * Returns whether the problem is at an optimal state.
  *
  * @param tableau simple tableau for the problem
  * @return whether the model has been solved
  */
 public boolean isOptimal(final SimplexTableau tableau) {
   if (tableau.getNumArtificialVariables() > 0) {
     return false;
   }
   for (int i = tableau.getNumObjectiveFunctions(); i < tableau.getWidth() - 1; i++) {
     if (MathUtils.compareTo(tableau.getEntry(0, i), 0, epsilon) < 0) {
       return false;
     }
   }
   return true;
 }
Beispiel #5
0
 /**
  * Returns the column with the most negative coefficient in the objective function row.
  *
  * @param tableau Simple tableau for the problem.
  * @return the 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++) {
     final double entry = tableau.getEntry(0, i);
     // check if the entry is strictly smaller than the current minimum
     // do not use a ulp/epsilon check
     if (entry < minValue) {
       minValue = entry;
       minPos = i;
     }
   }
   return minPos;
 }
Beispiel #6
0
 /*  27:    */
 /*  28:    */ private Integer getPivotColumn(SimplexTableau tableau) /*  29:    */ {
   /*  30: 70 */ double minValue = 0.0D;
   /*  31: 71 */ Integer minPos = null;
   /*  32: 72 */ for (int i = tableau.getNumObjectiveFunctions(); i < tableau.getWidth() - 1; i++)
   /*  33:    */ {
     /*  34: 73 */ double entry = tableau.getEntry(0, i);
     /*  35: 74 */ if (Precision.compareTo(entry, minValue, this.maxUlps) < 0)
     /*  36:    */ {
       /*  37: 75 */ minValue = entry;
       /*  38: 76 */ minPos = Integer.valueOf(i);
       /*  39:    */ }
     /*  40:    */ }
   /*  41: 79 */ return minPos;
   /*  42:    */ }
Beispiel #7
0
  /**
   * 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 (!isPhase1Solved(tableau)) {
      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();
    }
  }
Beispiel #8
0
 /* 106:    */
 /* 107:    */ protected void solvePhase1(SimplexTableau tableau)
     /* 108:    */ throws MaxCountExceededException, UnboundedSolutionException,
         NoFeasibleSolutionException
       /* 109:    */ {
   /* 110:169 */ if (tableau.getNumArtificialVariables() == 0) {
     /* 111:170 */ return;
     /* 112:    */ }
   /* 113:173 */ while (!tableau.isOptimal()) {
     /* 114:174 */ doIteration(tableau);
     /* 115:    */ }
   /* 116:178 */ if (!Precision.equals(
       tableau.getEntry(0, tableau.getRhsOffset()), 0.0D, this.epsilon)) {
     /* 117:179 */ throw new NoFeasibleSolutionException();
     /* 118:    */ }
   /* 119:    */ }
Beispiel #9
0
 /**
  * Returns the row with the minimum ratio as given by the minimum ratio test (MRT).
  *
  * @param tableau simple tableau for the problem
  * @param col the column to test the ratio of. See {@link #getPivotColumn(SimplexTableau)}
  * @return row with the minimum ratio
  */
 private Integer getPivotRow(final int col, final SimplexTableau tableau) {
   double minRatio = Double.MAX_VALUE;
   Integer minRatioPos = null;
   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;
       if (ratio < minRatio) {
         minRatio = ratio;
         minRatioPos = i;
       }
     }
   }
   return minRatioPos;
 }
Beispiel #10
0
  /**
   * Solves Phase 1 of the Simplex method.
   *
   * @param tableau Simple tableau for the problem.
   * @throws TooManyIterationsException if the allowed number of iterations has been exhausted.
   * @throws UnboundedSolutionException if the model is found not to have a bounded solution.
   * @throws NoFeasibleSolutionException if there is no feasible solution?
   */
  protected void solvePhase1(final SimplexTableau tableau)
      throws TooManyIterationsException, UnboundedSolutionException, NoFeasibleSolutionException {

    // 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 (!Precision.equals(tableau.getEntry(0, tableau.getRhsOffset()), 0d, epsilon)) {
      throw new NoFeasibleSolutionException();
    }
  }
Beispiel #11
0
 /*  85:    */
 /*  86:    */ protected void doIteration(SimplexTableau tableau)
     /*  87:    */ throws MaxCountExceededException, UnboundedSolutionException
       /*  88:    */ {
   /*  89:137 */ incrementIterationsCounter();
   /*  90:    */
   /*  91:139 */ Integer pivotCol = getPivotColumn(tableau);
   /*  92:140 */ Integer pivotRow = getPivotRow(tableau, pivotCol.intValue());
   /*  93:141 */ if (pivotRow == null) {
     /*  94:142 */ throw new UnboundedSolutionException();
     /*  95:    */ }
   /*  96:146 */ double pivotVal = tableau.getEntry(pivotRow.intValue(), pivotCol.intValue());
   /*  97:147 */ tableau.divideRow(pivotRow.intValue(), pivotVal);
   /*  98:150 */ for (int i = 0; i < tableau.getHeight(); i++) {
     /*  99:151 */ if (i != pivotRow.intValue())
     /* 100:    */ {
       /* 101:152 */ double multiplier = tableau.getEntry(i, pivotCol.intValue());
       /* 102:153 */ tableau.subtractRow(i, pivotRow.intValue(), multiplier);
       /* 103:    */ }
     /* 104:    */ }
   /* 105:    */ }
Beispiel #12
0
  /** {@inheritDoc} */
  @Override
  public PointValuePair doOptimize()
      throws MaxCountExceededException, UnboundedSolutionException, NoFeasibleSolutionException {
    final SimplexTableau tableau =
        new SimplexTableau(
            getFunction(),
            getConstraints(),
            getGoalType(),
            restrictToNonNegative(),
            epsilon,
            maxUlps);

    solvePhase1(tableau);
    tableau.dropPhase1Objective();

    while (!tableau.isOptimal()) {
      doIteration(tableau);
    }
    return tableau.getSolution();
  }
Beispiel #13
0
  /**
   * 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(pivotCol, tableau);
    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);
      }
    }
  }
Beispiel #14
0
 /*  43:    */
 /*  44:    */ private Integer getPivotRow(SimplexTableau tableau, int col) /*  45:    */ {
   /*  46: 90 */ List<Integer> minRatioPositions = new ArrayList();
   /*  47: 91 */ double minRatio = 1.7976931348623157E+308D;
   /*  48: 92 */ for (int i = tableau.getNumObjectiveFunctions(); i < tableau.getHeight(); i++)
   /*  49:    */ {
     /*  50: 93 */ double rhs = tableau.getEntry(i, tableau.getWidth() - 1);
     /*  51: 94 */ double entry = tableau.getEntry(i, col);
     /*  52: 96 */ if (Precision.compareTo(entry, 0.0D, this.maxUlps) > 0)
     /*  53:    */ {
       /*  54: 97 */ double ratio = rhs / entry;
       /*  55: 98 */ int cmp = Precision.compareTo(ratio, minRatio, this.maxUlps);
       /*  56: 99 */ if (cmp == 0)
       /*  57:    */ {
         /*  58:100 */ minRatioPositions.add(Integer.valueOf(i));
         /*  59:    */ }
       /*  60:101 */ else if (cmp < 0)
       /*  61:    */ {
         /*  62:102 */ minRatio = ratio;
         /*  63:103 */ minRatioPositions = new ArrayList();
         /*  64:104 */ minRatioPositions.add(Integer.valueOf(i));
         /*  65:    */ }
       /*  66:    */ }
     /*  67:    */ }
   /*  68:109 */ if (minRatioPositions.size() == 0) {
     /*  69:110 */ return null;
     /*  70:    */ }
   /*  71:111 */ if (minRatioPositions.size() > 1) {
     /*  72:114 */ for (Integer row : minRatioPositions) {
       /*  73:115 */ for (int i = 0; i < tableau.getNumArtificialVariables(); i++)
       /*  74:    */ {
         /*  75:116 */ int column = i + tableau.getArtificialVariableOffset();
         /*  76:117 */ double entry = tableau.getEntry(row.intValue(), column);
         /*  77:118 */ if ((Precision.equals(entry, 1.0D, this.maxUlps))
             && (row.equals(tableau.getBasicRow(column)))) {
           /*  78:120 */ return row;
           /*  79:    */ }
         /*  80:    */ }
       /*  81:    */ }
     /*  82:    */ }
   /*  83:125 */ return (Integer) minRatioPositions.get(0);
   /*  84:    */ }
Beispiel #15
0
  /**
   * Returns the row with the minimum ratio as given by the minimum ratio test (MRT).
   *
   * @param tableau Simple tableau for the problem.
   * @param col Column to test the ratio of (see {@link #getPivotColumn(SimplexTableau)}).
   * @return the row with the minimum ratio.
   */
  private Integer getPivotRow(SimplexTableau tableau, final int col) {
    // create a list of all the rows that tie for the lowest score in the minimum ratio test
    List<Integer> minRatioPositions = new ArrayList<Integer>();
    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 (Precision.compareTo(entry, 0d, maxUlps) > 0) {
        final double ratio = rhs / entry;
        // check if the entry is strictly equal to the current min ratio
        // do not use a ulp/epsilon check
        final int cmp = Double.compare(ratio, minRatio);
        if (cmp == 0) {
          minRatioPositions.add(i);
        } else if (cmp < 0) {
          minRatio = ratio;
          minRatioPositions = new ArrayList<Integer>();
          minRatioPositions.add(i);
        }
      }
    }

    if (minRatioPositions.size() == 0) {
      return null;
    } else if (minRatioPositions.size() > 1) {
      // there's a degeneracy as indicated by a tie in the minimum ratio test

      // 1. check if there's an artificial variable that can be forced out of the basis
      if (tableau.getNumArtificialVariables() > 0) {
        for (Integer row : minRatioPositions) {
          for (int i = 0; i < tableau.getNumArtificialVariables(); i++) {
            int column = i + tableau.getArtificialVariableOffset();
            final double entry = tableau.getEntry(row, column);
            if (Precision.equals(entry, 1d, maxUlps) && row.equals(tableau.getBasicRow(column))) {
              return row;
            }
          }
        }
      }

      // 2. apply Bland's rule to prevent cycling:
      //    take the row for which the corresponding basic variable has the smallest index
      //
      // see http://www.stanford.edu/class/msande310/blandrule.pdf
      // see http://en.wikipedia.org/wiki/Bland%27s_rule (not equivalent to the above paper)
      //
      // Additional heuristic: if we did not get a solution after half of maxIterations
      //                       revert to the simple case of just returning the top-most row
      // This heuristic is based on empirical data gathered while investigating MATH-828.
      if (getEvaluations() < getMaxEvaluations() / 2) {
        Integer minRow = null;
        int minIndex = tableau.getWidth();
        final int varStart = tableau.getNumObjectiveFunctions();
        final int varEnd = tableau.getWidth() - 1;
        for (Integer row : minRatioPositions) {
          for (int i = varStart; i < varEnd && !row.equals(minRow); i++) {
            final Integer basicRow = tableau.getBasicRow(i);
            if (basicRow != null && basicRow.equals(row) && i < minIndex) {
              minIndex = i;
              minRow = row;
            }
          }
        }
        return minRow;
      }
    }
    return minRatioPositions.get(0);
  }