/// <summary> /// Construct a solver. /// </summary> /// <param name="absoluteAccuracy"> Absolute accuracy. </param> /// <param name="maximalOrder"> maximal order. </param> /// <exception cref="NumberIsTooSmallException"> if maximal order is lower than 2 </exception> //JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET: //ORIGINAL LINE: public BracketingNthOrderBrentSolver(final double absoluteAccuracy, final int maximalOrder) throws org.apache.commons.math3.exception.NumberIsTooSmallException public BracketingNthOrderBrentSolver(double absoluteAccuracy, int maximalOrder) : base(absoluteAccuracy) { if (maximalOrder < 2) { throw new NumberIsTooSmallException(maximalOrder, 2, true); } this.maximalOrder = maximalOrder; this.allowed = AllowedSolution.ANY_SIDE; }
/// <summary> /// Construct a solver. /// </summary> /// <param name="relativeAccuracy"> Maximum relative error. </param> /// <param name="absoluteAccuracy"> Maximum absolute error. </param> /// <param name="functionValueAccuracy"> Maximum function value error. </param> /// <param name="method"> <em>Secant</em>-based root-finding method to use </param> protected internal BaseSecantSolver(double relativeAccuracy, double absoluteAccuracy, double functionValueAccuracy, Method method) : base(relativeAccuracy, absoluteAccuracy, functionValueAccuracy) { this.allowed = AllowedSolution.ANY_SIDE; this.method = method; }
/// <summary> /// Construct a solver. /// </summary> /// <param name="absoluteAccuracy"> Absolute accuracy. </param> /// <param name="method"> <em>Secant</em>-based root-finding method to use. </param> protected internal BaseSecantSolver(double absoluteAccuracy, Method method) : base(absoluteAccuracy) { this.allowed = AllowedSolution.ANY_SIDE; this.method = method; }
/// <summary> /// {@inheritDoc} </summary> public virtual double Solve(int maxEval, UnivariateFunction f, double min, double max, double startValue, AllowedSolution allowedSolution) { this.allowed = allowedSolution; return(base.Solve(maxEval, f, min, max, startValue)); }
/// <summary> /// {@inheritDoc} </summary> public virtual double Solve(int maxEval, UnivariateFunction f, double min, double max, AllowedSolution allowedSolution) { return(this.Solve(maxEval, f, min, max, min + 0.5 * (max - min), allowedSolution)); }
/// <summary> /// Force a root found by a non-bracketing solver to lie on a specified side, /// as if the solver was a bracketing one. </summary> /// <param name="maxEval"> maximal number of new evaluations of the function /// (evaluations already done for finding the root should have already been subtracted /// from this number) </param> /// <param name="f"> function to solve </param> /// <param name="bracketing"> bracketing solver to use for shifting the root </param> /// <param name="baseRoot"> original root found by a previous non-bracketing solver </param> /// <param name="min"> minimal bound of the search interval </param> /// <param name="max"> maximal bound of the search interval </param> /// <param name="allowedSolution"> the kind of solutions that the root-finding algorithm may /// accept as solutions. </param> /// <returns> a root approximation, on the specified side of the exact root </returns> /// <exception cref="NoBracketingException"> if the function has the same sign at the /// endpoints. </exception> public static double ForceSide(int maxEval, UnivariateFunction f, BracketedUnivariateSolver <UnivariateFunction> bracketing, double baseRoot, double min, double max, AllowedSolution allowedSolution) { if (allowedSolution == AllowedSolution.ANY_SIDE) { // no further bracketing required return(baseRoot); } // find a very small interval bracketing the root double step = FastMath.Max(bracketing.AbsoluteAccuracy, FastMath.Abs(baseRoot * bracketing.RelativeAccuracy)); double xLo = FastMath.Max(min, baseRoot - step); double fLo = f.Value(xLo); double xHi = FastMath.Min(max, baseRoot + step); double fHi = f.Value(xHi); int remainingEval = maxEval - 2; while (remainingEval > 0) { if ((fLo >= 0 && fHi <= 0) || (fLo <= 0 && fHi >= 0)) { // compute the root on the selected side return(bracketing.Solve(remainingEval, f, xLo, xHi, baseRoot, allowedSolution)); } // try increasing the interval bool changeLo = false; bool changeHi = false; if (fLo < fHi) { // increasing function if (fLo >= 0) { changeLo = true; } else { changeHi = true; } } else if (fLo > fHi) { // decreasing function if (fLo <= 0) { changeLo = true; } else { changeHi = true; } } else { // unknown variation changeLo = true; changeHi = true; } // update the lower bound if (changeLo) { xLo = FastMath.Max(min, xLo - step); fLo = f.Value(xLo); remainingEval--; } // update the higher bound if (changeHi) { xHi = FastMath.Min(max, xHi + step); fHi = f.Value(xHi); remainingEval--; } } throw new NoBracketingException("LocalizedFormats.FAILED_BRACKETING", xLo, xHi, fLo, fHi, maxEval - remainingEval, maxEval, baseRoot, min, max); }
/// <summary> /// Solve for a zero in the given interval, start at {@code startValue}. /// A solver may require that the interval brackets a single zero root. /// Solvers that do require bracketing should be able to handle the case /// where one of the endpoints is itself a root. /// </summary> /// <param name="maxEval"> Maximum number of evaluations. </param> /// <param name="f"> Function to solve. </param> /// <param name="min"> Lower bound for the interval. </param> /// <param name="max"> Upper bound for the interval. </param> /// <param name="startValue"> Start value to use. </param> /// <param name="allowedSolution"> The kind of solutions that the root-finding algorithm may /// accept as solutions. </param> /// <returns> a value where the function is zero. </returns> /// <exception cref="NullArgumentException"> if f is null. </exception> /// <exception cref="NoBracketingException"> if root cannot be bracketed </exception> //JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET: //ORIGINAL LINE: public T solve(final int maxEval, final org.apache.commons.math3.analysis.RealFieldUnivariateFunction<T> f, final T min, final T max, final T startValue, final AllowedSolution allowedSolution) throws org.apache.commons.math3.exception.NullArgumentException, org.apache.commons.math3.exception.NoBracketingException public virtual T Solve(int maxEval, RealFieldUnivariateFunction <T> f, T min, T max, T startValue, AllowedSolution allowedSolution) { // Checks. MathUtils.CheckNotNull(f); // Reset. evaluations = evaluations.WithMaximalCount(maxEval).withStart(0); T zero = field.GetZero(); T nan = zero.add(Double.NaN); // prepare arrays with the first points //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final T[] x = org.apache.commons.math3.util.MathArrays.buildArray(field, maximalOrder + 1); T[] x = MathArrays.BuildArray(field, maximalOrder + 1); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final T[] y = org.apache.commons.math3.util.MathArrays.buildArray(field, maximalOrder + 1); T[] y = MathArrays.BuildArray(field, maximalOrder + 1); x[0] = min; x[1] = startValue; x[2] = max; // evaluate initial guess evaluations.Increment(); y[1] = f.Value(x[1]); if (Precision.Equals(y[1].getReal(), 0.0, 1)) { // return the initial guess if it is a perfect root. return(x[1]); } // evaluate first endpoint evaluations.Increment(); y[0] = f.Value(x[0]); if (Precision.Equals(y[0].getReal(), 0.0, 1)) { // return the first endpoint if it is a perfect root. return(x[0]); } int nbPoints; int signChangeIndex; if (y[0].multiply(y[1]).getReal() < 0) { // reduce interval if it brackets the root nbPoints = 2; signChangeIndex = 1; } else { // evaluate second endpoint evaluations.Increment(); y[2] = f.Value(x[2]); if (Precision.Equals(y[2].getReal(), 0.0, 1)) { // return the second endpoint if it is a perfect root. return(x[2]); } if (y[1].multiply(y[2]).getReal() < 0) { // use all computed point as a start sampling array for solving nbPoints = 3; signChangeIndex = 2; } else { throw new NoBracketingException(x[0].getReal(), x[2].getReal(), y[0].getReal(), y[2].getReal()); } } // prepare a work array for inverse polynomial interpolation //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final T[] tmpX = org.apache.commons.math3.util.MathArrays.buildArray(field, x.length); T[] tmpX = MathArrays.BuildArray(field, x.Length); // current tightest bracketing of the root T xA = x[signChangeIndex - 1]; T yA = y[signChangeIndex - 1]; T absXA = xA.abs(); T absYA = yA.abs(); int agingA = 0; T xB = x[signChangeIndex]; T yB = y[signChangeIndex]; T absXB = xB.abs(); T absYB = yB.abs(); int agingB = 0; // search loop while (true) { // check convergence of bracketing interval T maxX = absXA.subtract(absXB).getReal() < 0 ? absXB : absXA; T maxY = absYA.subtract(absYB).getReal() < 0 ? absYB : absYA; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final T xTol = absoluteAccuracy.add(relativeAccuracy.multiply(maxX)); T xTol = absoluteAccuracy.add(relativeAccuracy.multiply(maxX)); if (xB.subtract(xA).subtract(xTol).getReal() <= 0 || maxY.subtract(functionValueAccuracy).getReal() < 0) { switch (allowedSolution) { case org.apache.commons.math3.analysis.solvers.AllowedSolution.ANY_SIDE: return(absYA.subtract(absYB).getReal() < 0 ? xA : xB); case org.apache.commons.math3.analysis.solvers.AllowedSolution.LEFT_SIDE: return(xA); case org.apache.commons.math3.analysis.solvers.AllowedSolution.RIGHT_SIDE: return(xB); case org.apache.commons.math3.analysis.solvers.AllowedSolution.BELOW_SIDE: return(yA.getReal() <= 0 ? xA : xB); case org.apache.commons.math3.analysis.solvers.AllowedSolution.ABOVE_SIDE: return(yA.getReal() < 0 ? xB : xA); default: // this should never happen throw new MathInternalError(null); } } // target for the next evaluation point T targetY; if (agingA >= MAXIMAL_AGING) { // we keep updating the high bracket, try to compensate this targetY = yB.divide(16).negate(); } else if (agingB >= MAXIMAL_AGING) { // we keep updating the low bracket, try to compensate this targetY = yA.divide(16).negate(); } else { // bracketing is balanced, try to find the root itself targetY = zero; } // make a few attempts to guess a root, T nextX; int start = 0; int end = nbPoints; do { // guess a value for current target, using inverse polynomial interpolation Array.Copy(x, start, tmpX, start, end - start); nextX = GuessX(targetY, tmpX, y, start, end); if (!((nextX.subtract(xA).getReal() > 0) && (nextX.subtract(xB).getReal() < 0))) { // 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 = nan; } } while (double.IsNaN(nextX.getReal()) && (end - start > 1)); if (double.IsNaN(nextX.getReal())) { // fall back to bisection nextX = xA.add(xB.subtract(xA).divide(2)); start = signChangeIndex - 1; end = signChangeIndex; } // evaluate the function at the guessed root evaluations.Increment(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final T nextY = f.value(nextX); T nextY = f.Value(nextX); if (Precision.Equals(nextY.getReal(), 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; Array.Copy(x, start, x, 0, nbPoints); Array.Copy(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 Array.Copy(x, 1, x, 0, nbPoints); Array.Copy(y, 1, y, 0, nbPoints); --signChangeIndex; } } // insert the last computed point //(by construction, we know it lies inside the tightest bracketing interval) Array.Copy(x, signChangeIndex, x, signChangeIndex + 1, nbPoints - signChangeIndex); x[signChangeIndex] = nextX; Array.Copy(y, signChangeIndex, y, signChangeIndex + 1, nbPoints - signChangeIndex); y[signChangeIndex] = nextY; ++nbPoints; // update the bracketing interval if (nextY.multiply(yA).getReal() <= 0) { // the sign change occurs before the inserted point xB = nextX; yB = nextY; absYB = yB.abs(); ++agingA; agingB = 0; } else { // the sign change occurs after the inserted point xA = nextX; yA = nextY; absYA = yA.abs(); agingA = 0; ++agingB; // update the sign change index signChangeIndex++; } } }
/// <summary> /// Solve for a zero in the given interval. /// A solver may require that the interval brackets a single zero root. /// Solvers that do require bracketing should be able to handle the case /// where one of the endpoints is itself a root. /// </summary> /// <param name="maxEval"> Maximum number of evaluations. </param> /// <param name="f"> Function to solve. </param> /// <param name="min"> Lower bound for the interval. </param> /// <param name="max"> Upper bound for the interval. </param> /// <param name="allowedSolution"> The kind of solutions that the root-finding algorithm may /// accept as solutions. </param> /// <returns> a value where the function is zero. </returns> /// <exception cref="NullArgumentException"> if f is null. </exception> /// <exception cref="NoBracketingException"> if root cannot be bracketed </exception> //JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET: //ORIGINAL LINE: public T solve(final int maxEval, final org.apache.commons.math3.analysis.RealFieldUnivariateFunction<T> f, final T min, final T max, final AllowedSolution allowedSolution) throws org.apache.commons.math3.exception.NullArgumentException, org.apache.commons.math3.exception.NoBracketingException public virtual T Solve(int maxEval, RealFieldUnivariateFunction <T> f, T min, T max, AllowedSolution allowedSolution) { return(Solve(maxEval, f, min, max, min.add(max).divide(2), allowedSolution)); }
/// <summary> /// Force a root found by a non-bracketing solver to lie on a specified side, /// as if the solver were a bracketing one. /// </summary> /// <param name="maxEval"> maximal number of new evaluations of the function /// (evaluations already done for finding the root should have already been subtracted /// from this number) </param> /// <param name="f"> function to solve </param> /// <param name="bracketing"> bracketing solver to use for shifting the root </param> /// <param name="baseRoot"> original root found by a previous non-bracketing solver </param> /// <param name="min"> minimal bound of the search interval </param> /// <param name="max"> maximal bound of the search interval </param> /// <param name="allowedSolution"> the kind of solutions that the root-finding algorithm may /// accept as solutions. </param> /// <returns> a root approximation, on the specified side of the exact root </returns> /// <exception cref="NoBracketingException"> if the function has the same sign at the /// endpoints. </exception> //JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET: //ORIGINAL LINE: public static double forceSide(final int maxEval, final org.apache.commons.math3.analysis.UnivariateFunction f, final BracketedUnivariateSolver<org.apache.commons.math3.analysis.UnivariateFunction> bracketing, final double baseRoot, final double min, final double max, final AllowedSolution allowedSolution) throws org.apache.commons.math3.exception.NoBracketingException public static double ForceSide(int maxEval, UnivariateFunction f, BracketedUnivariateSolver <UnivariateFunction> bracketing, double baseRoot, double min, double max, AllowedSolution allowedSolution) { if (allowedSolution == AllowedSolution.ANY_SIDE) { // no further bracketing required return(baseRoot); } // find a very small interval bracketing the root //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double step = org.apache.commons.math3.util.FastMath.max(bracketing.getAbsoluteAccuracy(), org.apache.commons.math3.util.FastMath.abs(baseRoot * bracketing.getRelativeAccuracy())); double step = FastMath.Max(bracketing.GetAbsoluteAccuracy(), FastMath.Abs(baseRoot * bracketing.GetRelativeAccuracy())); double xLo = FastMath.Max(min, baseRoot - step); double fLo = f.Value(xLo); double xHi = FastMath.Min(max, baseRoot + step); double fHi = f.Value(xHi); int remainingEval = maxEval - 2; while (remainingEval > 0) { if ((fLo >= 0 && fHi <= 0) || (fLo <= 0 && fHi >= 0)) { // compute the root on the selected side return(bracketing.Solve(remainingEval, f, xLo, xHi, baseRoot, allowedSolution)); } // try increasing the interval bool changeLo = false; bool changeHi = false; if (fLo < fHi) { // increasing function if (fLo >= 0) { changeLo = true; } else { changeHi = true; } } else if (fLo > fHi) { // decreasing function if (fLo <= 0) { changeLo = true; } else { changeHi = true; } } else { // unknown variation changeLo = true; changeHi = true; } // update the lower bound if (changeLo) { xLo = FastMath.Max(min, xLo - step); fLo = f.Value(xLo); remainingEval--; } // update the higher bound if (changeHi) { xHi = FastMath.Min(max, xHi + step); fHi = f.Value(xHi); remainingEval--; } } throw new NoBracketingException(LocalizedFormats.FAILED_BRACKETING, xLo, xHi, fLo, fHi, maxEval - remainingEval, maxEval, baseRoot, min, max); }