/** {@inheritDoc} */ public new ArrayRealVector mapToSelf(UnivariateFunction function) { for (int i = 0; i < data.Length; i++) { data[i] = function.value(data[i]); } return(this); }
/// <summary> /// Convenience method to find a zero of a univariate real function. A default /// solver is used. /// </summary> /// <param name="function">Function.</param> /// <param name="x0">Lower bound for the interval.</param> /// <param name="x1">Upper bound for the interval.</param> /// <param name="absoluteAccuracy">Accuracy to be used by the solver.</param> /// <returns>a value where the function is zero.</returns> /// <exception cref="NoBracketingException"> if the function has the same sign at the /// endpoints.</exception> /// <exception cref="NullArgumentException"> if <c>function</c> is <c>null</c>.</exception> public static double solve(UnivariateFunction function, double x0, double x1, double absoluteAccuracy) { if (function == null) { throw new NullArgumentException(new LocalizedFormats("FUNCTION")); } UnivariateSolver solver = new BrentSolver(absoluteAccuracy); return(solver.solve(Int32.MaxValue, function, x0, x1)); }
/// <summary> /// Convenience method to find a zero of a univariate real function. A default /// solver is used. /// </summary> /// <param name="function"> Function. </param> /// <param name="x0"> Lower bound for the interval. </param> /// <param name="x1"> Upper bound for the interval. </param> /// <param name="absoluteAccuracy"> Accuracy to be used by the solver. </param> /// <returns> a value where the function is zero. </returns> /// <exception cref="NoBracketingException"> if the function has the same sign at the /// endpoints. </exception> /// <exception cref="NullArgumentException"> if {@code function} is {@code null}. </exception> public static double Solve(UnivariateFunction function, double x0, double x1, double absoluteAccuracy) { if (function == null) { throw new ArgumentNullException("LocalizedFormats.FUNCTION"); } UnivariateSolver solver = new BrentSolver(absoluteAccuracy); return(solver.Solve(int.MaxValue, function, x0, x1)); }
/// <summary> /// Check whether the interval bounds bracket a root. That is, if the /// values at the endpoints are not equal to zero, then the function takes /// opposite signs at the endpoints. /// </summary> /// <param name="function"> Function. </param> /// <param name="lower"> Lower endpoint. </param> /// <param name="upper"> Upper endpoint. </param> /// <returns> {@code true} if the function values have opposite signs at the /// given points. </returns> /// <exception cref="NullArgumentException"> if {@code function} is {@code null}. </exception> public static bool IsBracketing(UnivariateFunction function, double lower, double upper) { if (function == null) { throw new ArgumentNullException("LocalizedFormats.FUNCTION"); } double fLo = function.Value(lower); double fHi = function.Value(upper); return((fLo >= 0 && fHi <= 0) || (fLo <= 0 && fHi >= 0)); }
/// <summary> /// Check whether the interval bounds bracket a root. That is, if the /// values at the endpoints are not equal to zero, then the function takes /// opposite signs at the endpoints. /// </summary> /// <param name="function">Function.</param> /// <param name="lower">Lower endpoint.</param> /// <param name="upper">Upper endpoint.</param> /// <returns><c>true</c> if the function values have opposite signs at the /// given points.</returns> /// <exception cref="NullArgumentException"> if <c>function</c> is <c>null</c>.</exception> public static Boolean isBracketing(UnivariateFunction function, double lower, double upper) { if (function == null) { throw new NullArgumentException(new LocalizedFormats("FUNCTION")); } double fLo = function.value(lower); double fHi = function.value(upper); return((fLo >= 0 && fHi <= 0) || (fLo <= 0 && fHi >= 0)); }
/** * Acts as if it is implemented as: * <pre> * Entry e = null; * for(Iterator<Entry> it = iterator(); it.hasNext(); e = it.next()) { * e.setValue(function.value(e.getValue())); * } * </pre> * Entries of this vector are modified in-place by this method. * * @param function Function to apply to each entry. * @return a reference to this vector. */ public virtual RealVector mapToSelf(UnivariateFunction function) { var it = iterator(); while (it.MoveNext()) { Entry e = it.Current; e.setValue(function.value(e.getValue())); } return(this); }
/// <summary> /// Check that the endpoints specify an interval and the end points /// bracket a root. /// </summary> /// <param name="function"> Function. </param> /// <param name="lower"> Lower endpoint. </param> /// <param name="upper"> Upper endpoint. </param> /// <exception cref="NoBracketingException"> if the function has the same sign at the /// endpoints. </exception> /// <exception cref="NullArgumentException"> if {@code function} is {@code null}. </exception> public static void VerifyBracketing(UnivariateFunction function, double lower, double upper) { if (function == null) { throw new ArgumentNullException("LocalizedFormats.FUNCTION"); } VerifyInterval(lower, upper); if (!IsBracketing(function, lower, upper)) { throw new NoBracketingException(lower, upper, function.Value(lower), function.Value(upper)); } }
/// <summary> /// Check that the endpoints specify an interval and the end points /// bracket a root. /// </summary> /// <param name="function">Function.</param> /// <param name="lower">Lower endpoint.</param> /// <param name="upper">Upper endpoint.</param> /// <exception cref="NoBracketingException"> if the function has the same sign at the /// endpoints.</exception> /// <exception cref="NullArgumentException"> if <c>function</c> is <c>null</c>.</exception> public static void verifyBracketing(UnivariateFunction function, double lower, double upper) { if (function == null) { throw new NullArgumentException(new LocalizedFormats("FUNCTION")); } verifyInterval(lower, upper); if (!isBracketing(function, lower, upper)) { throw new NoBracketingException(lower, upper, function.value(lower), function.value(upper)); } }
/// <summary> /// Convenience method to find a zero of a univariate real function. A default /// solver is used. /// </summary> /// <param name="function"> Function. </param> /// <param name="x0"> Lower bound for the interval. </param> /// <param name="x1"> Upper bound for the interval. </param> /// <param name="absoluteAccuracy"> Accuracy to be used by the solver. </param> /// <returns> a value where the function is zero. </returns> /// <exception cref="NoBracketingException"> if the function has the same sign at the /// endpoints. </exception> /// <exception cref="NullArgumentException"> if {@code function} is {@code null}. </exception> public static double Solve(UnivariateFunction function, double x0, double x1, double absoluteAccuracy) { if (function == null) { throw new NullArgumentException(LocalizedFormats.FUNCTION); } //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final UnivariateSolver solver = new BrentSolver(absoluteAccuracy); UnivariateSolver solver = new BrentSolver(absoluteAccuracy); return(solver.solve(int.MaxValue, function, x0, x1)); }
/// <summary> /// Prepare for computation. /// Subclasses must call this method if they override any of the /// {@code solve} methods. /// </summary> /// <param name="maxEval"> Maximum number of evaluations. </param> /// <param name="f"> the integrand function </param> /// <param name="lower"> the min bound for the interval </param> /// <param name="upper"> the upper bound for the interval </param> /// <exception cref="NullArgumentException"> if {@code f} is {@code null}. </exception> /// <exception cref="MathIllegalArgumentException"> if {@code min >= max}. </exception> //JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET: //ORIGINAL LINE: protected void setup(final int maxEval, final org.apache.commons.math3.analysis.UnivariateFunction f, final double lower, final double upper) throws org.apache.commons.math3.exception.NullArgumentException, org.apache.commons.math3.exception.MathIllegalArgumentException protected internal virtual void Setup(int maxEval, UnivariateFunction f, double lower, double upper) { // Checks. MathUtils.CheckNotNull(f); UnivariateSolverUtils.VerifyInterval(lower, upper); // Reset. min = lower; max = upper; function = f; evaluations = evaluations.WithMaximalCount(maxEval).withStart(0); count = count.WithStart(0); }
/// <summary> /// {@inheritDoc} </summary> /// <exception cref="MathException"> If the Commons method could not evaluate the function; /// if the Commons method could not converge. </exception> public override double?getRoot(System.Func <double, double> function, double?xLow, double?xHigh) { checkInputs(function, xLow, xHigh); UnivariateFunction wrapped = CommonsMathWrapper.wrapUnivariate(function); try { return(_ridder.solve(MAX_ITER, wrapped, xLow, xHigh)); } catch (Exception e) when(e is TooManyEvaluationsException || e is NoBracketingException) { throw new MathException(e); } }
/// <summary> /// Prepare for computation. /// Subclasses must call this method if they override any of the /// {@code solve} methods. /// </summary> /// <param name="maxEval"> Maximum number of evaluations. </param> /// <param name="f"> the integrand function </param> /// <param name="lower"> the min bound for the interval </param> /// <param name="upper"> the upper bound for the interval </param> /// <exception cref="NullArgumentException"> if {@code f} is {@code null}. </exception> /// <exception cref="MathIllegalArgumentException"> if {@code min >= max}. </exception> protected internal virtual void Setup(int maxEval, UnivariateFunction f, double lower, double upper) { // Checks. MyUtils.CheckNotNull(f); UnivariateSolverUtils.VerifyInterval(lower, upper); // Reset. this.min = lower; this.max = upper; this.function = f; this.evaluations.MaximalCount = maxEval; this.evaluations.ResetCount(); this.iterations.ResetCount(); }
/// <summary> /// Check whether the interval bounds bracket a root. That is, if the /// values at the endpoints are not equal to zero, then the function takes /// opposite signs at the endpoints. /// </summary> /// <param name="function"> Function. </param> /// <param name="lower"> Lower endpoint. </param> /// <param name="upper"> Upper endpoint. </param> /// <returns> {@code true} if the function values have opposite signs at the /// given points. </returns> /// <exception cref="NullArgumentException"> if {@code function} is {@code null}. </exception> //JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET: //ORIGINAL LINE: public static boolean isBracketing(org.apache.commons.math3.analysis.UnivariateFunction function, final double lower, final double upper) throws org.apache.commons.math3.exception.NullArgumentException public static bool IsBracketing(UnivariateFunction function, double lower, double upper) { if (function == null) { throw new NullArgumentException(LocalizedFormats.FUNCTION); } //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double fLo = function.value(lower); double fLo = function.Value(lower); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double fHi = function.value(upper); double fHi = function.Value(upper); return((fLo >= 0 && fHi <= 0) || (fLo <= 0 && fHi >= 0)); }
/// <summary> /// Returns an estimate of the integral of {@code f(x) * w(x)}, /// where {@code w} is a weight function that depends on the actual /// flavor of the Gauss integration scheme. /// The algorithm uses the points and associated weights, as passed /// to the <seealso cref="#GaussIntegrator(double[],double[]) constructor"/>. /// </summary> /// <param name="f"> Function to integrate. </param> /// <returns> the integral of the weighted function. </returns> public virtual double Integrate(UnivariateFunction f) { double s = 0; double c = 0; for (int i = 0; i < this.points.Length; i++) { double x = this.points[i]; double w = this.weights[i]; double y = w * f.Value(x) - c; double t = s + y; c = (t - s) - y; s = t; } return(s); }
/// <summary> /// Samples the specified univariate real function on the specified interval. /// <para/> /// The interval is divided equally into <c>n</c> sections and sample points /// are taken from <c>min</c> to <c>max - (max - min) / n</c>; therefore /// <c>f</c> is not sampled at the upper bound <c>max</c>. /// </summary> /// <param name="f">Function to be sampled</param> /// <param name="min">Lower bound of the interval (included).</param> /// <param name="max">Upper bound of the interval (excluded).</param> /// <param name="n">Number of sample points.</param> /// <returns>the array of samples.</returns> /// <exception cref="NumberIsTooLargeException"> if the lower bound <c>min</c> is /// greater than, or equal to the upper bound <c>max</c>.</exception> /// <exception cref="NotStrictlyPositiveException"> if the number of sample points /// <c>n</c> is negative.</exception> public static double[] sample(UnivariateFunction f, double min, double max, int n) { if (n <= 0) { throw new NotStrictlyPositiveException <Int32>(new LocalizedFormats("NOT_POSITIVE_NUMBER_OF_SAMPLES"), n); } if (min >= max) { throw new NumberIsTooLargeException <Double, Double>(min, max, false); } double[] s = new double[n]; double h = (max - min) / n; for (int i = 0; i < n; i++) { s[i] = f.value(min + i * h); } return(s); }
public static void Test() { double min = -4.0; double max = 0.0; int maxEval = 1000; UnivariateFunction f1 = (UnivariateFunction) new DelegateUnivariateFunction((Func <double, double>)(x => (x + 3.0) * (x - 1.0) * (x - 1.0))); DifferentiableUnivariateFunction f2 = (DifferentiableUnivariateFunction) new DelegateDifferentiableUnivariateFunction((Func <double, double>)(x => (x + 3.0) * (x - 1.0) * (x - 1.0)), (Func <double, double>)(x => 2.0 * (x - 1.0) * (x + 3.0) + (x - 1.0) * (x - 1.0))); new BisectionSolver().Solve(maxEval, f1, min, max); new BrentSolver().Solve(maxEval, f1, min, max); new RegulaFalsiSolver().Solve(maxEval, f1, min, max); new IllinoisSolver().Solve(maxEval, f1, min, max); new PegasusSolver().Solve(maxEval, f1, min, max); new RiddersSolver().Solve(maxEval, f1, min, max); new SecantSolver().Solve(maxEval, f1, min, max); new MullerSolver().Solve(maxEval, f1, min, max); new MullerSolver2().Solve(maxEval, f1, min, max); new BracketingNthOrderBrentSolver().Solve(maxEval, f1, min, max); new NewtonSolver().Solve(maxEval, f2, min, max); }
/// <summary> /// {@inheritDoc} /// </summary> public override double Integrate(UnivariateFunction f) { int ruleLength = this.NumberOfPoints; if (ruleLength == 1) { return(this.GetWeight(0) * f.Value(0d)); } int iMax = ruleLength / 2; double s = 0; double c = 0; for (int i = 0; i < iMax; i++) { double p = this.GetPoint(i); double w = this.GetWeight(i); double f1 = f.Value(p); double f2 = f.Value(-p); double y = w * (f1 + f2) - c; double t = s + y; c = (t - s) - y; s = t; } if (ruleLength % 2 != 0) { double w = this.GetWeight(iMax); double y = w * f.Value(0d) - c; double t = s + y; s = t; } return(s); }
/// <summary> /// Returns an estimate of the integral of {@code f(x) * w(x)}, /// where {@code w} is a weight function that depends on the actual /// flavor of the Gauss integration scheme. /// The algorithm uses the points and associated weights, as passed /// to the <seealso cref="#GaussIntegrator(double[],double[]) constructor"/>. /// </summary> /// <param name="f"> Function to integrate. </param> /// <returns> the integral of the weighted function. </returns> public virtual double Integrate(UnivariateFunction f) { double s = 0; double c = 0; for (int i = 0; i < points.Length; i++) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double x = points[i]; double x = points[i]; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double w = weights[i]; double w = weights[i]; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double y = w * f.value(x) - c; double y = w * f.Value(x) - c; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double t = s + y; double t = s + y; c = (t - s) - y; s = t; } return(s); }
public static UnivariateFunction Compose(this UnivariateFunction function, UnivariateFunction inner) { return(x => function(inner(x))); }
public static UnivariateFunction Wrap(UnivariateFunction function) { return(function); }
public static UnivariateFunction OutCompose(this UnivariateFunction function, UnivariateFunction outer) { return(x => outer(function(x))); }
/// <summary> /// {@inheritDoc} /// </summary> protected internal override void Setup(int maxEval, DifferentiableUnivariateFunction f, double min, double max, double startValue) { base.Setup(maxEval, f, min, max, startValue); this.functionDerivative = f.Derivative(); }
public MultivariateFunctionAnonymous(BivariateFunction combiner, UnivariateFunction f, ref double initialValue) { this.combiner = combiner; this.f = f; this.initialValue = initialValue; }
/// <summary> /// This method simply calls {@link #bracket(UnivariateFunction, double, double, double, /// double, double, int) bracket(function, initial, lowerBound, upperBound, q, r, maximumIterations)} /// with {@code q} and {@code r} set to 1.0 and {@code maximumIterations} set to {@code Integer.MAX_VALUE}. /// <strong>Note: </strong> this method can take /// <code>Integer.MAX_VALUE</code> iterations to throw a /// <code>ConvergenceException.</code> Unless you are confident that there /// is a root between <code>lowerBound</code> and <code>upperBound</code> /// near <code>initial,</code> it is better to use /// {@link #bracket(UnivariateFunction, double, double, double, double, /// double, int) bracket(function, initial, lowerBound, upperBound, q, r, maximumIterations)}, /// explicitly specifying the maximum number of iterations.</p> /// </summary> /// <param name="function"> Function. </param> /// <param name="initial"> Initial midpoint of interval being expanded to /// bracket a root. </param> /// <param name="lowerBound"> Lower bound (a is never lower than this value) </param> /// <param name="upperBound"> Upper bound (b never is greater than this /// value). </param> /// <returns> a two-element array holding a and b. </returns> /// <exception cref="NoBracketingException"> if a root cannot be bracketted. </exception> /// <exception cref="NotStrictlyPositiveException"> if {@code maximumIterations <= 0}. </exception> /// <exception cref="NullArgumentException"> if {@code function} is {@code null}. </exception> public static double[] Bracket(UnivariateFunction function, double initial, double lowerBound, double upperBound) { return(Bracket(function, initial, lowerBound, upperBound, 1.0, 1.0, int.MaxValue)); }
public UnivariateFunctionAnonymous4(BivariateFunction combiner, UnivariateFunction f, UnivariateFunction g) { this.combiner = combiner; this.f = f; this.g = g; }
/// <summary> /// Returns a MultivariateFunction h(x[]) defined by <code> /// h(x[]) = combiner(...combiner(combiner(initialValue,f(x[0])),f(x[1]))...),f(x[x.Length-1])) /// </code> /// </summary> /// <param name="combiner">Combiner function.</param> /// <param name="f">Function.</param> /// <param name="initialValue">Initial value.</param> /// <returns>a collector function.</returns> public static MultivariateFunction collector(BivariateFunction combiner, UnivariateFunction f, double initialValue) { return(new MultivariateFunctionAnonymous(combiner, f, ref initialValue)); }
/// <summary> /// Returns the univariate function <para/> /// <c>h(x) = combiner(f(x), g(x))</c>. /// </summary> /// <param name="combiner">Combiner function.</param> /// <param name="f">Function.</param> /// <param name="g">Function.</param> /// <returns>the composite function.</returns> public static UnivariateFunction combine(BivariateFunction combiner, UnivariateFunction f, UnivariateFunction g) { return(new UnivariateFunctionAnonymous4(combiner, f, g)); }
/// <summary> /// This method simply calls {@link #bracket(UnivariateFunction, double, double, double, /// double, double, int) bracket(function, initial, lowerBound, upperBound, q, r, maximumIterations)} /// with {@code q} and {@code r} set to 1.0. </summary> /// <param name="function"> Function. </param> /// <param name="initial"> Initial midpoint of interval being expanded to /// bracket a root. </param> /// <param name="lowerBound"> Lower bound (a is never lower than this value). </param> /// <param name="upperBound"> Upper bound (b never is greater than this /// value). </param> /// <param name="maximumIterations"> Maximum number of iterations to perform </param> /// <returns> a two element array holding a and b. </returns> /// <exception cref="NoBracketingException"> if the algorithm fails to find a and b /// satisfying the desired conditions. </exception> /// <exception cref="NotStrictlyPositiveException"> if {@code maximumIterations <= 0}. </exception> /// <exception cref="NullArgumentException"> if {@code function} is {@code null}. </exception> public static double[] Bracket(UnivariateFunction function, double initial, double lowerBound, double upperBound, int maximumIterations) { return(Bracket(function, initial, lowerBound, upperBound, 1.0, 1.0, maximumIterations)); }
/// <summary> /// This method attempts to find two values a and b satisfying <ul> /// <li> {@code lowerBound <= a < initial < b <= upperBound} </li> /// <li> {@code f(a) * f(b) <= 0} </li> /// </ul> /// If {@code f} is continuous on {@code [a,b]}, this means that {@code a} /// and {@code b} bracket a root of {@code f}. /// <para> /// The algorithm checks the sign of \( f(l_k) \) and \( f(u_k) \) for increasing /// values of k, where \( l_k = max(lower, initial - \delta_k) \), /// \( u_k = min(upper, initial + \delta_k) \), using recurrence /// \( \delta_{k+1} = r \delta_k + q, \delta_0 = 0\) and starting search with \( k=1 \). /// The algorithm stops when one of the following happens: <ul> /// <li> at least one positive and one negative value have been found -- success!</li> /// <li> both endpoints have reached their respective limites -- NoBracketingException </li> /// <li> {@code maximumIterations} iterations elapse -- NoBracketingException </li></ul></para> /// <para> /// If different signs are found at first iteration ({@code k=1}), then the returned /// interval will be \( [a, b] = [l_1, u_1] \). If different signs are found at a later /// iteration ({code k>1}, then the returned interval will be either /// \( [a, b] = [l_{k+1}, l_{k}] \) or ( [a, b] = [u_{k}, u_{k+1}] \). A root solver called /// with these parameters will therefore start with the smallest bracketing interval known /// at this step. /// </para> /// <para> /// Interval expansion rate is tuned by changing the recurrence parameters {@code r} and /// {@code q}. When the multiplicative factor {@code r} is set to 1, the sequence is a /// simple arithmetic sequence with linear increase. When the multiplicative factor {@code r} /// is larger than 1, the sequence has an asymtotically exponential rate. Note than the /// additive parameter {@code q} should never be set to zero, otherwise the interval would /// degenerate to the single initial point for all values of {@code k}. /// </para> /// <para> /// As a rule of thumb, when the location of the root is expected to be approximately known /// within some error margin, {@code r} should be set to 1 and {@code q} should be set to the /// order of magnitude of the error margin. When the location of the root is really a wild guess, /// then {@code r} should be set to a value larger than 1 (typically 2 to double the interval /// length at each iteration) and {@code q} should be set according to half the initial /// search interval length. /// </para> /// <para> /// As an example, if we consider the trivial function {@code f(x) = 1 - x} and use /// {@code initial = 4}, {@code r = 1}, {@code q = 2}, the algorithm will compute /// {@code f(4-2) = f(2) = -1} and {@code f(4+2) = f(6) = -5} for {@code k = 1}, then /// {@code f(4-4) = f(0) = +1} and {@code f(4+4) = f(8) = -7} for {@code k = 2}. Then it will /// return the interval {@code [0, 2]} as the smallest one known to be bracketing the root. /// As shown by this example, the initial value (here {@code 4}) may lie outside of the returned /// bracketing interval. /// </para> </summary> /// <param name="function"> function to check </param> /// <param name="initial"> Initial midpoint of interval being expanded to /// bracket a root. </param> /// <param name="lowerBound"> Lower bound (a is never lower than this value). </param> /// <param name="upperBound"> Upper bound (b never is greater than this /// value). </param> /// <param name="q"> additive offset used to compute bounds sequence (must be strictly positive) </param> /// <param name="r"> multiplicative factor used to compute bounds sequence </param> /// <param name="maximumIterations"> Maximum number of iterations to perform </param> /// <returns> a two element array holding the bracketing values. </returns> /// <exception cref="NoBracketingException"> if function cannot be bracketed in the search interval </exception> public static double[] Bracket(UnivariateFunction function, double initial, double lowerBound, double upperBound, double q, double r, int maximumIterations) { if (function == null) { throw new ArgumentNullException("LocalizedFormats.FUNCTION"); } if (q <= 0) { throw new NotStrictlyPositiveException(q); } if (maximumIterations <= 0) { throw new NotStrictlyPositiveException("LocalizedFormats.INVALID_MAX_ITERATIONS", maximumIterations); } VerifySequence(lowerBound, initial, upperBound); // initialize the recurrence double a = initial; double b = initial; double fa = double.NaN; double fb = double.NaN; double delta = 0; for (int numIterations = 0; (numIterations < maximumIterations) && (a > lowerBound || b > upperBound); ++numIterations) { double previousA = a; double previousFa = fa; double previousB = b; double previousFb = fb; delta = r * delta + q; a = FastMath.Max(initial - delta, lowerBound); b = FastMath.Min(initial + delta, upperBound); fa = function.Value(a); fb = function.Value(b); if (numIterations == 0) { // at first iteration, we don't have a previous interval // we simply compare both sides of the initial interval if (fa * fb <= 0) { // the first interval already brackets a root return(new double[] { a, b }); } } else { // we have a previous interval with constant sign and expand it, // we expect sign changes to occur at boundaries if (fa * previousFa <= 0) { // sign change detected at near lower bound return(new double[] { a, previousA }); } else if (fb * previousFb <= 0) { // sign change detected at near upper bound return(new double[] { previousB, b }); } } } // no bracketing found throw new NoBracketingException(a, b, fa, fb); }
/// <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); }