Example #1
0
        /// <summary>
        /// Construct an integrator with given accuracies and iteration counts.
        /// <para>
        /// The meanings of the various parameters are:
        /// <ul>
        ///   <li>relative accuracy:
        ///       this is used to stop iterations if the absolute accuracy can't be
        ///       achieved due to large values or short mantissa length. If this
        ///       should be the primary criterion for convergence rather then a
        ///       safety measure, set the absolute accuracy to a ridiculously small value,
        ///       like <seealso cref="org.apache.commons.math3.util.Precision#SAFE_MIN Precision.SAFE_MIN"/>.</li>
        ///   <li>absolute accuracy:
        ///       The default is usually chosen so that results in the interval
        ///       -10..-0.1 and +0.1..+10 can be found with a reasonable accuracy. If the
        ///       expected absolute value of your results is of much smaller magnitude, set
        ///       this to a smaller value.</li>
        ///   <li>minimum number of iterations:
        ///       minimal iteration is needed to avoid false early convergence, e.g.
        ///       the sample points happen to be zeroes of the function. Users can
        ///       use the default value or choose one that they see as appropriate.</li>
        ///   <li>maximum number of iterations:
        ///       usually a high iteration count indicates convergence problems. However,
        ///       the "reasonable value" varies widely for different algorithms. Users are
        ///       advised to use the default value supplied by the algorithm.</li>
        /// </ul>
        ///
        /// </para>
        /// </summary>
        /// <param name="relativeAccuracy"> relative accuracy of the result </param>
        /// <param name="absoluteAccuracy"> absolute accuracy of the result </param>
        /// <param name="minimalIterationCount"> minimum number of iterations </param>
        /// <param name="maximalIterationCount"> maximum number of iterations </param>
        /// <exception cref="NotStrictlyPositiveException"> if minimal number of iterations
        /// is not strictly positive </exception>
        /// <exception cref="NumberIsTooSmallException"> if maximal number of iterations
        /// is lesser than or equal to the minimal number of iterations </exception>
//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
//ORIGINAL LINE: protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy, final double absoluteAccuracy, final int minimalIterationCount, final int maximalIterationCount) throws org.apache.commons.math3.exception.NotStrictlyPositiveException, org.apache.commons.math3.exception.NumberIsTooSmallException
        protected internal BaseAbstractUnivariateIntegrator(double relativeAccuracy, double absoluteAccuracy, int minimalIterationCount, int maximalIterationCount)
        {
            // accuracy settings
            this.relativeAccuracy = relativeAccuracy;
            this.absoluteAccuracy = absoluteAccuracy;

            // iterations count settings
            if (minimalIterationCount <= 0)
            {
                throw new NotStrictlyPositiveException(minimalIterationCount);
            }
            if (maximalIterationCount <= minimalIterationCount)
            {
                throw new NumberIsTooSmallException(maximalIterationCount, minimalIterationCount, false);
            }
            this.minimalIterationCount = minimalIterationCount;
            this.count = IntegerSequence.Incrementor.Create().withMaximalCount(maximalIterationCount);

//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("deprecation") org.apache.commons.math3.util.Incrementor wrapped = org.apache.commons.math3.util.Incrementor.wrap(count);
            org.apache.commons.math3.util.Incrementor wrapped = org.apache.commons.math3.util.Incrementor.Wrap(count);
            this.iterations = wrapped;

            // prepare evaluations counter, but do not set it yet
            evaluations = IntegerSequence.Incrementor.Create();
        }
Example #2
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>
        /// Construct a solver.
        /// </summary>
        /// <param name="relativeAccuracy"> Relative accuracy. </param>
        /// <param name="absoluteAccuracy"> Absolute accuracy. </param>
        /// <param name="functionValueAccuracy"> Function value 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 FieldBracketingNthOrderBrentSolver(final T relativeAccuracy, final T absoluteAccuracy, final T functionValueAccuracy, final int maximalOrder) throws org.apache.commons.math3.exception.NumberIsTooSmallException
        public FieldBracketingNthOrderBrentSolver(T relativeAccuracy, T absoluteAccuracy, T functionValueAccuracy, int maximalOrder)
        {
            if (maximalOrder < 2)
            {
                throw new NumberIsTooSmallException(maximalOrder, 2, true);
            }
            this.field                 = relativeAccuracy.getField();
            this.maximalOrder          = maximalOrder;
            this.absoluteAccuracy      = absoluteAccuracy;
            this.relativeAccuracy      = relativeAccuracy;
            this.functionValueAccuracy = functionValueAccuracy;
            this.evaluations           = IntegerSequence.Incrementor.Create();
        }
        /// <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++;
                }
            }
        }