@Test
 public void testJacobiEvaluationAt1() {
   for (int v = 0; v < 10; ++v) {
     for (int w = 0; w < 10; ++w) {
       for (int i = 0; i < 10; ++i) {
         PolynomialFunction jacobi = PolynomialsUtils.createJacobiPolynomial(i, v, w);
         double binomial = CombinatoricsUtils.binomialCoefficient(v + i, i);
         Assert.assertTrue(Precision.equals(binomial, jacobi.value(1.0), 1));
       }
     }
   }
 }
 @Override
 public boolean equals(Object o) {
   if (this == o) {
     return true;
   }
   if (!(o instanceof TesparSymbol)) {
     return false;
   } else {
     TesparSymbol symbol = (TesparSymbol) o;
     return duration == symbol.getDuration()
         && shape == symbol.getShape()
         && Precision.equals(amplitude, symbol.getAmplitude(), TimeSeriesPrecision.EPSILON);
   }
 }
Esempio n. 3
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:    */ }
Esempio n. 4
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();
    }
  }
Esempio n. 5
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:    */ }
Esempio n. 6
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);
  }
Esempio n. 7
0
  /** {@inheritDoc} */
  @Override
  protected UnivariatePointValuePair doOptimize() {
    final boolean isMinim = getGoalType() == GoalType.MINIMIZE;
    final double lo = getMin();
    final double mid = getStartValue();
    final double hi = getMax();

    // Optional additional convergence criteria.
    final ConvergenceChecker<UnivariatePointValuePair> checker = getConvergenceChecker();

    double a;
    double b;
    if (lo < hi) {
      a = lo;
      b = hi;
    } else {
      a = hi;
      b = lo;
    }

    double x = mid;
    double v = x;
    double w = x;
    double d = 0;
    double e = 0;
    double fx = computeObjectiveValue(x);
    if (!isMinim) {
      fx = -fx;
    }
    double fv = fx;
    double fw = fx;

    UnivariatePointValuePair previous = null;
    UnivariatePointValuePair current = new UnivariatePointValuePair(x, isMinim ? fx : -fx);
    // Best point encountered so far (which is the initial guess).
    UnivariatePointValuePair best = current;

    while (true) {
      final double m = 0.5 * (a + b);
      final double tol1 = relativeThreshold * FastMath.abs(x) + absoluteThreshold;
      final double tol2 = 2 * tol1;

      // Default stopping criterion.
      final boolean stop = FastMath.abs(x - m) <= tol2 - 0.5 * (b - a);
      if (!stop) {
        double p = 0;
        double q = 0;
        double r = 0;
        double u = 0;

        if (FastMath.abs(e) > tol1) { // Fit parabola.
          r = (x - w) * (fx - fv);
          q = (x - v) * (fx - fw);
          p = (x - v) * q - (x - w) * r;
          q = 2 * (q - r);

          if (q > 0) {
            p = -p;
          } else {
            q = -q;
          }

          r = e;
          e = d;

          if (p > q * (a - x) && p < q * (b - x) && FastMath.abs(p) < FastMath.abs(0.5 * q * r)) {
            // Parabolic interpolation step.
            d = p / q;
            u = x + d;

            // f must not be evaluated too close to a or b.
            if (u - a < tol2 || b - u < tol2) {
              if (x <= m) {
                d = tol1;
              } else {
                d = -tol1;
              }
            }
          } else {
            // Golden section step.
            if (x < m) {
              e = b - x;
            } else {
              e = a - x;
            }
            d = GOLDEN_SECTION * e;
          }
        } else {
          // Golden section step.
          if (x < m) {
            e = b - x;
          } else {
            e = a - x;
          }
          d = GOLDEN_SECTION * e;
        }

        // Update by at least "tol1".
        if (FastMath.abs(d) < tol1) {
          if (d >= 0) {
            u = x + tol1;
          } else {
            u = x - tol1;
          }
        } else {
          u = x + d;
        }

        double fu = computeObjectiveValue(u);
        if (!isMinim) {
          fu = -fu;
        }

        // User-defined convergence checker.
        previous = current;
        current = new UnivariatePointValuePair(u, isMinim ? fu : -fu);
        best = best(best, best(previous, current, isMinim), isMinim);

        if (checker != null && checker.converged(getIterations(), previous, current)) {
          return best;
        }

        // Update a, b, v, w and x.
        if (fu <= fx) {
          if (u < x) {
            b = x;
          } else {
            a = x;
          }
          v = w;
          fv = fw;
          w = x;
          fw = fx;
          x = u;
          fx = fu;
        } else {
          if (u < x) {
            a = u;
          } else {
            b = u;
          }
          if (fu <= fw || Precision.equals(w, x)) {
            v = w;
            fv = fw;
            w = u;
            fw = fu;
          } else if (fu <= fv || Precision.equals(v, x) || Precision.equals(v, w)) {
            v = u;
            fv = fu;
          }
        }
      } else { // Default termination (Brent's criterion).
        return best(best, best(previous, current, isMinim), isMinim);
      }

      incrementIterationCount();
    }
  }
  /** {@inheritDoc} */
  @Override
  protected double doSolve() {

    // prepare arrays with the first points
    final double[] x = new double[maximalOrder + 1];
    final double[] y = new double[maximalOrder + 1];
    x[0] = getMin();
    x[1] = getStartValue();
    x[2] = getMax();
    verifySequence(x[0], x[1], x[2]);

    // evaluate initial guess
    y[1] = computeObjectiveValue(x[1]);
    if (Precision.equals(y[1], 0.0, 1)) {
      // return the initial guess if it is a perfect root.
      return x[1];
    }

    // evaluate first  endpoint
    y[0] = computeObjectiveValue(x[0]);
    if (Precision.equals(y[0], 0.0, 1)) {
      // return the first endpoint if it is a perfect root.
      return x[0];
    }

    int nbPoints;
    int signChangeIndex;
    if (y[0] * y[1] < 0) {

      // reduce interval if it brackets the root
      nbPoints = 2;
      signChangeIndex = 1;

    } else {

      // evaluate second endpoint
      y[2] = computeObjectiveValue(x[2]);
      if (Precision.equals(y[2], 0.0, 1)) {
        // return the second endpoint if it is a perfect root.
        return x[2];
      }

      if (y[1] * y[2] < 0) {
        // use all computed point as a start sampling array for solving
        nbPoints = 3;
        signChangeIndex = 2;
      } else {
        throw new NoBracketingException(x[0], x[2], y[0], y[2]);
      }
    }

    // prepare a work array for inverse polynomial interpolation
    final double[] tmpX = new double[x.length];

    // current tightest bracketing of the root
    double xA = x[signChangeIndex - 1];
    double yA = y[signChangeIndex - 1];
    double absYA = FastMath.abs(yA);
    int agingA = 0;
    double xB = x[signChangeIndex];
    double yB = y[signChangeIndex];
    double absYB = FastMath.abs(yB);
    int agingB = 0;

    // search loop
    while (true) {

      // check convergence of bracketing interval
      final double xTol =
          getAbsoluteAccuracy()
              + getRelativeAccuracy() * FastMath.max(FastMath.abs(xA), FastMath.abs(xB));
      if (((xB - xA) <= xTol) || (FastMath.max(absYA, absYB) < getFunctionValueAccuracy())) {
        switch (allowed) {
          case ANY_SIDE:
            return absYA < absYB ? xA : xB;
          case LEFT_SIDE:
            return xA;
          case RIGHT_SIDE:
            return xB;
          case BELOW_SIDE:
            return (yA <= 0) ? xA : xB;
          case ABOVE_SIDE:
            return (yA < 0) ? xB : xA;
          default:
            // this should never happen
            throw new MathInternalError(null);
        }
      }

      // target for the next evaluation point
      double targetY;
      if (agingA >= MAXIMAL_AGING) {
        // we keep updating the high bracket, try to compensate this
        final int p = agingA - MAXIMAL_AGING;
        final double weightA = (1 << p) - 1;
        final double weightB = p + 1;
        targetY = (weightA * yA - weightB * REDUCTION_FACTOR * yB) / (weightA + weightB);
      } else if (agingB >= MAXIMAL_AGING) {
        // we keep updating the low bracket, try to compensate this
        final int p = agingB - MAXIMAL_AGING;
        final double weightA = p + 1;
        final double weightB = (1 << p) - 1;
        targetY = (weightB * yB - weightA * REDUCTION_FACTOR * yA) / (weightA + weightB);
      } else {
        // bracketing is balanced, try to find the root itself
        targetY = 0;
      }

      // make a few attempts to guess a root,
      double nextX;
      int start = 0;
      int end = nbPoints;
      do {

        // guess a value for current target, using inverse polynomial interpolation
        System.arraycopy(x, start, tmpX, start, end - start);
        nextX = guessX(targetY, tmpX, y, start, end);

        if (!((nextX > xA) && (nextX < xB))) {
          // the guessed root is not strictly inside of the tightest bracketing interval

          // the guessed root is either not strictly inside the interval or it
          // is a NaN (which occurs when some sampling points share the same y)
          // we try again with a lower interpolation order
          if (signChangeIndex - start >= end - signChangeIndex) {
            // we have more points before the sign change, drop the lowest point
            ++start;
          } else {
            // we have more points after sign change, drop the highest point
            --end;
          }

          // we need to do one more attempt
          nextX = Double.NaN;
        }

      } while (Double.isNaN(nextX) && (end - start > 1));

      if (Double.isNaN(nextX)) {
        // fall back to bisection
        nextX = xA + 0.5 * (xB - xA);
        start = signChangeIndex - 1;
        end = signChangeIndex;
      }

      // evaluate the function at the guessed root
      final double nextY = computeObjectiveValue(nextX);
      if (Precision.equals(nextY, 0.0, 1)) {
        // we have found an exact root, since it is not an approximation
        // we don't need to bother about the allowed solutions setting
        return nextX;
      }

      if ((nbPoints > 2) && (end - start != nbPoints)) {

        // we have been forced to ignore some points to keep bracketing,
        // they are probably too far from the root, drop them from now on
        nbPoints = end - start;
        System.arraycopy(x, start, x, 0, nbPoints);
        System.arraycopy(y, start, y, 0, nbPoints);
        signChangeIndex -= start;

      } else if (nbPoints == x.length) {

        // we have to drop one point in order to insert the new one
        nbPoints--;

        // keep the tightest bracketing interval as centered as possible
        if (signChangeIndex >= (x.length + 1) / 2) {
          // we drop the lowest point, we have to shift the arrays and the index
          System.arraycopy(x, 1, x, 0, nbPoints);
          System.arraycopy(y, 1, y, 0, nbPoints);
          --signChangeIndex;
        }
      }

      // insert the last computed point
      // (by construction, we know it lies inside the tightest bracketing interval)
      System.arraycopy(x, signChangeIndex, x, signChangeIndex + 1, nbPoints - signChangeIndex);
      x[signChangeIndex] = nextX;
      System.arraycopy(y, signChangeIndex, y, signChangeIndex + 1, nbPoints - signChangeIndex);
      y[signChangeIndex] = nextY;
      ++nbPoints;

      // update the bracketing interval
      if (nextY * yA <= 0) {
        // the sign change occurs before the inserted point
        xB = nextX;
        yB = nextY;
        absYB = FastMath.abs(yB);
        ++agingA;
        agingB = 0;
      } else {
        // the sign change occurs after the inserted point
        xA = nextX;
        yA = nextY;
        absYA = FastMath.abs(yA);
        agingA = 0;
        ++agingB;

        // update the sign change index
        signChangeIndex++;
      }
    }
  }