@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); } }
/* 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: */ }
/** * 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(); } }
/* 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: */ }
/** * 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); }
/** {@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++; } } }