예제 #1
0
        /** {@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));
        }
예제 #3
0
        /// <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));
        }
예제 #4
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> {@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));
        }
예제 #6
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);
        }
예제 #7
0
 /// <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));
     }
 }
예제 #9
0
        /// <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));
        }
예제 #10
0
        /// <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();
        }
예제 #13
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> {@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));
        }
예제 #14
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);
        }
예제 #15
0
        /// <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);
        }
예제 #16
0
        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);
        }
예제 #17
0
        /// <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);
        }
예제 #18
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 < 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();
 }
예제 #23
0
 public MultivariateFunctionAnonymous(BivariateFunction combiner, UnivariateFunction f, ref double initialValue)
 {
     this.combiner     = combiner;
     this.f            = f;
     this.initialValue = initialValue;
 }
예제 #24
0
 /// <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));
 }
예제 #25
0
 public UnivariateFunctionAnonymous4(BivariateFunction combiner, UnivariateFunction f, UnivariateFunction g)
 {
     this.combiner = combiner;
     this.f        = f;
     this.g        = g;
 }
예제 #26
0
 /// <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));
 }
예제 #27
0
 /// <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));
 }
예제 #28
0
 /// <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));
 }
예제 #29
0
        /// <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);
        }
예제 #30
0
        /// <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);
        }