예제 #1
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;
 }
예제 #2
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:    */ }
예제 #3
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:    */ }
예제 #4
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);
      }
    }
  }
예제 #5
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);
  }