示例#1
0
        /*! This method returns the zero of the function \f$ f \f$, determined with the given accuracy \f$ \epsilon \f$
         *  depending on the particular solver, this might mean that the returned \f$ x \f$ is such that \f$ |f(x)| < \epsilon
         *  \f$, or that \f$ |x-\xi| < \epsilon \f$ where \f$ \xi \f$ is the real zero.
         *
         *  An initial guess must be supplied, as well as two values \f$ x_\mathrm{min} \f$ and \f$ x_\mathrm{max} \f$ which
         *  must bracket the zero (i.e., either \f$ f(x_\mathrm{min}) \leq 0 \leq f(x_\mathrm{max}) \f$, or \f$
         *  f(x_\mathrm{max}) \leq 0 \leq f(x_\mathrm{min}) \f$ must be true).
         */

        public double solve(ISolver1d f, double accuracy, double guess, double xMin, double xMax)
        {
            Utils.QL_REQUIRE(accuracy > 0.0, () => "accuracy (" + accuracy + ") must be positive");

            // check whether we really want to use epsilon
            accuracy = Math.Max(accuracy, Const.QL_EPSILON);

            xMin_ = xMin;
            xMax_ = xMax;

            Utils.QL_REQUIRE(xMin_ < xMax_, () => "invalid range: xMin_ (" + xMin_ + ") >= xMax_ (" + xMax_ + ")");
            Utils.QL_REQUIRE(!lowerBoundEnforced_ || xMin_ >= lowerBound_, () =>
                             "xMin_ (" + xMin_ + ") < enforced low bound (" + lowerBound_ + ")");
            Utils.QL_REQUIRE(!upperBoundEnforced_ || xMax_ <= upperBound_, () =>
                             "xMax_ (" + xMax_ + ") > enforced hi bound (" + upperBound_ + ")");

            fxMin_ = f.value(xMin_);
            if (Utils.close(fxMin_, 0.0))
            {
                return(xMin_);
            }

            fxMax_ = f.value(xMax_);
            if (Utils.close(fxMax_, 0.0))
            {
                return(xMax_);
            }

            evaluationNumber_ = 2;

            Utils.QL_REQUIRE(fxMin_ * fxMax_ < 0.0, () =>
                             "root not bracketed: f[" + xMin_ + "," + xMax_ + "] -> [" + fxMin_ + "," + fxMax_ + "]");
            Utils.QL_REQUIRE(guess > xMin_, () => "guess (" + guess + ") < xMin_ (" + xMin_ + ")");
            Utils.QL_REQUIRE(guess < xMax_, () => "guess (" + guess + ") > xMax_ (" + xMax_ + ")");

            root_ = guess;

            return(solveImpl(f, accuracy));
        }
示例#2
0
        protected override double solveImpl(ISolver1d f, double xAccuracy)
        {
            /* The implementation of the algorithm was inspired by
             * Press, Teukolsky, Vetterling, and Flannery,
             * "Numerical Recipes in C", 2nd edition, Cambridge
             * University Press
             */

            double fl, froot, dx, xl;

            // Pick the bound with the smaller function value
            // as the most recent guess
            if (Math.Abs(fxMin_) < Math.Abs(fxMax_))
            {
                root_ = xMin_;
                froot = fxMin_;
                xl    = xMax_;
                fl    = fxMax_;
            }
            else
            {
                root_ = xMax_;
                froot = fxMax_;
                xl    = xMin_;
                fl    = fxMin_;
            }
            while (evaluationNumber_ <= maxEvaluations_)
            {
                dx     = (xl - root_) * froot / (froot - fl);
                xl     = root_;
                fl     = froot;
                root_ += dx;
                froot  = f.value(root_);
                ++evaluationNumber_;
                if (Math.Abs(dx) < xAccuracy || Utils.close(froot, 0.0))
                {
                    return(root_);
                }
            }

            Utils.QL_FAIL("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded",
                          QLNetExceptionEnum.MaxNumberFuncEvalExceeded);
            return(0);
        }
示例#3
0
        protected override double solveImpl(ISolver1d f, double xAccuracy)
        {
            /* The implementation of the algorithm was inspired by
             * Press, Teukolsky, Vetterling, and Flannery,
             * "Numerical Recipes in C", 2nd edition, Cambridge
             * University Press
             */

            double dx, xMid, fMid;

            // Orient the search so that f>0 lies at root_+dx
            if (fxMin_ < 0.0)
            {
                dx    = xMax_ - xMin_;
                root_ = xMin_;
            }
            else
            {
                dx    = xMin_ - xMax_;
                root_ = xMax_;
            }

            while (evaluationNumber_ <= maxEvaluations_)
            {
                dx  /= 2.0;
                xMid = root_ + dx;
                fMid = f.value(xMid);
                evaluationNumber_++;
                if (fMid <= 0.0)
                {
                    root_ = xMid;
                }
                if (Math.Abs(dx) < xAccuracy || Utils.close(fMid, 0.0))
                {
                    return(root_);
                }
            }
            Utils.QL_FAIL("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded",
                          QLNetExceptionEnum.MaxNumberFuncEvalExceeded);
            return(0);
        }
示例#4
0
        protected override double solveImpl(ISolver1d f, double xAccuracy)
        {
            /* The implementation of the algorithm was inspired by Press, Teukolsky, Vetterling, and Flannery,
             * "Numerical Recipes in C", 2nd edition, Cambridge University Press */

            double min1, min2;
            double froot, p, q, r, s, xAcc1, xMid;
            // dummy assignements to avoid compiler warning
            double d = 0.0, e = 0.0;

            root_ = xMax_;
            froot = fxMax_;
            while (evaluationNumber_ <= maxEvaluations_)
            {
                if ((froot > 0.0 && fxMax_ > 0.0) ||
                    (froot < 0.0 && fxMax_ < 0.0))
                {
                    // Rename xMin_, root_, xMax_ and adjust bounds
                    xMax_  = xMin_;
                    fxMax_ = fxMin_;
                    e      = d = root_ - xMin_;
                }
                if (Math.Abs(fxMax_) < Math.Abs(froot))
                {
                    xMin_  = root_;
                    root_  = xMax_;
                    xMax_  = xMin_;
                    fxMin_ = froot;
                    froot  = fxMax_;
                    fxMax_ = fxMin_;
                }
                // Convergence check
                xAcc1 = 2.0 * Const.QL_EPSILON * Math.Abs(root_) + 0.5 * xAccuracy;
                xMid  = (xMax_ - root_) / 2.0;
                if (Math.Abs(xMid) <= xAcc1 || Utils.close(froot, 0.0))
                {
                    return(root_);
                }
                if (Math.Abs(e) >= xAcc1 &&
                    Math.Abs(fxMin_) > Math.Abs(froot))
                {
                    // Attempt inverse quadratic interpolation
                    s = froot / fxMin_;
                    if (Utils.close(xMin_, xMax_))
                    {
                        p = 2.0 * xMid * s;
                        q = 1.0 - s;
                    }
                    else
                    {
                        q = fxMin_ / fxMax_;
                        r = froot / fxMax_;
                        p = s * (2.0 * xMid * q * (q - r) - (root_ - xMin_) * (r - 1.0));
                        q = (q - 1.0) * (r - 1.0) * (s - 1.0);
                    }
                    if (p > 0.0)
                    {
                        q = -q; // Check whether in bounds
                    }
                    p    = Math.Abs(p);
                    min1 = 3.0 * xMid * q - Math.Abs(xAcc1 * q);
                    min2 = Math.Abs(e * q);
                    if (2.0 * p < (min1 < min2 ? min1 : min2))
                    {
                        e = d;          // Accept interpolation
                        d = p / q;
                    }
                    else
                    {
                        d = xMid; // Interpolation failed, use bisection
                        e = d;
                    }
                }
                else
                {
                    // Bounds decreasing too slowly, use bisection
                    d = xMid;
                    e = d;
                }
                xMin_  = root_;
                fxMin_ = froot;
                if (Math.Abs(d) > xAcc1)
                {
                    root_ += d;
                }
                else
                {
                    root_ += Math.Abs(xAcc1) * Math.Sign(xMid);
                }
                froot = f.value(root_);
                evaluationNumber_++;
            }
            Utils.QL_FAIL("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded",
                          QLNetExceptionEnum.MaxNumberFuncEvalExceeded);
            return(0);
        }
示例#5
0
        /*! This method returns the zero of the function \f$ f \f$, determined with the given accuracy \f$ \epsilon \f$
         *          depending on the particular solver, this might mean that the returned \f$ x \f$ is such that \f$ |f(x)| < \epsilon
         *          \f$, or that \f$ |x-\xi| < \epsilon \f$ where \f$ \xi \f$ is the real zero.
         *
         *          This method contains a bracketing routine to which an initial guess must be supplied as well as a step used to
         *          scan the range of the possible bracketing values.
         */

        public double solve(ISolver1d f, double accuracy, double guess, double step)
        {
            Utils.QL_REQUIRE(accuracy > 0.0, () => "accuracy (" + accuracy + ") must be positive");

            // check whether we really want to use epsilon
            accuracy = Math.Max(accuracy, Const.QL_EPSILON);

            const double growthFactor = 1.6;
            int          flipflop     = -1;

            root_  = guess;
            fxMax_ = f.value(root_);

            // monotonically crescent bias, as in optionValue(volatility)
            if (Utils.close(fxMax_, 0.0))
            {
                return(root_);
            }
            else if (fxMax_ > 0.0)
            {
                xMin_  = enforceBounds_(root_ - step);
                fxMin_ = f.value(xMin_);
                xMax_  = root_;
            }
            else
            {
                xMin_  = root_;
                fxMin_ = fxMax_;
                xMax_  = enforceBounds_(root_ + step);
                fxMax_ = f.value(xMax_);
            }

            evaluationNumber_ = 2;
            while (evaluationNumber_ <= maxEvaluations_)
            {
                if (fxMin_ * fxMax_ <= 0.0)
                {
                    if (Utils.close(fxMin_, 0.0))
                    {
                        return(xMin_);
                    }
                    if (Utils.close(fxMax_, 0.0))
                    {
                        return(xMax_);
                    }
                    root_ = (xMax_ + xMin_) / 2.0;
                    return(solveImpl(f, accuracy));
                }
                if (Math.Abs(fxMin_) < Math.Abs(fxMax_))
                {
                    xMin_  = enforceBounds_(xMin_ + growthFactor * (xMin_ - xMax_));
                    fxMin_ = f.value(xMin_);
                }
                else if (Math.Abs(fxMin_) > Math.Abs(fxMax_))
                {
                    xMax_  = enforceBounds_(xMax_ + growthFactor * (xMax_ - xMin_));
                    fxMax_ = f.value(xMax_);
                }
                else if (flipflop == -1)
                {
                    xMin_  = enforceBounds_(xMin_ + growthFactor * (xMin_ - xMax_));
                    fxMin_ = f.value(xMin_);
                    evaluationNumber_++;
                    flipflop = 1;
                }
                else if (flipflop == 1)
                {
                    xMax_    = enforceBounds_(xMax_ + growthFactor * (xMax_ - xMin_));
                    fxMax_   = f.value(xMax_);
                    flipflop = -1;
                }
                evaluationNumber_++;
            }

            Utils.QL_FAIL("unable to bracket root in " + maxEvaluations_
                          + " function evaluations (last bracket attempt: " + "f[" + xMin_ + "," + xMax_ +
                          "] "
                          + "-> [" + fxMin_ + "," + fxMax_ + "])",
                          QLNetExceptionEnum.RootNotBracketException);
            return(0);
        }
示例#6
0
        protected override double solveImpl(ISolver1d f, double xAcc)
        {
            /* The implementation of the algorithm was inspired by
             * Press, Teukolsky, Vetterling, and Flannery,
             * "Numerical Recipes in C", 2nd edition, Cambridge
             * University Press
             */

            double fxMid, froot, s, xMid, nextRoot;

            // test on Black-Scholes implied volatility show that
            // Ridder solver algorithm actually provides an
            // accuracy 100 times below promised
            double xAccuracy = xAcc / 100.0;

            // Any highly unlikely value, to simplify logic below
            root_ = double.MinValue;

            while (evaluationNumber_ <= maxEvaluations_)
            {
                xMid = 0.5 * (xMin_ + xMax_);
                // First of two function evaluations per iteraton
                fxMid = f.value(xMid);
                ++evaluationNumber_;
                s = Math.Sqrt(fxMid * fxMid - fxMin_ * fxMax_);
                if (Utils.close(s, 0.0))
                {
                    return(root_);
                }
                // Updating formula
                nextRoot = xMid + (xMid - xMin_) *
                           ((fxMin_ >= fxMax_ ? 1.0 : -1.0) * fxMid / s);
                if (Math.Abs(nextRoot - root_) <= xAccuracy)
                {
                    return(root_);
                }

                root_ = nextRoot;
                // Second of two function evaluations per iteration
                froot = f.value(root_);
                ++evaluationNumber_;
                if (Utils.close(froot, 0.0))
                {
                    return(root_);
                }

                // Bookkeeping to keep the root bracketed on next iteration
                if (sign(fxMid, froot).IsNotEqual(fxMid))
                {
                    xMin_  = xMid;
                    fxMin_ = fxMid;
                    xMax_  = root_;
                    fxMax_ = froot;
                }
                else if (sign(fxMin_, froot).IsNotEqual(fxMin_))
                {
                    xMax_  = root_;
                    fxMax_ = froot;
                }
                else if (sign(fxMax_, froot).IsNotEqual(fxMax_))
                {
                    xMin_  = root_;
                    fxMin_ = froot;
                }
                else
                {
                    Utils.QL_FAIL("never get here.");
                }

                if (Math.Abs(xMax_ - xMin_) <= xAccuracy)
                {
                    return(root_);
                }
            }

            Utils.QL_FAIL("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded",
                          QLNetExceptionEnum.MaxNumberFuncEvalExceeded);
            return(0);
        }
示例#7
0
        protected override double solveImpl(ISolver1d f, double xAccuracy)
        {
            // Orient the search so that f(xl) < 0
            double xh, xl;

            if (fxMin_ < 0.0)
            {
                xl = xMin_;
                xh = xMax_;
            }
            else
            {
                xh = xMin_;
                xl = xMax_;
            }

            double froot = f.value(root_);

            ++evaluationNumber_;
            // first order finite difference derivative
            double dfroot = xMax_ - root_ < root_ - xMin_ ?
                            (fxMax_ - froot) / (xMax_ - root_) :
                            (fxMin_ - froot) / (xMin_ - root_);

            // xMax_-xMin_>0 is verified in the constructor
            double dx = xMax_ - xMin_;

            while (evaluationNumber_ <= maxEvaluations_)
            {
                double frootold = froot;
                double rootold  = root_;
                double dxold    = dx;
                // Bisect if (out of range || not decreasing fast enough)
                if ((((root_ - xh) * dfroot - froot) *
                     ((root_ - xl) * dfroot - froot) > 0.0) ||
                    (Math.Abs(2.0 * froot) > Math.Abs(dxold * dfroot)))
                {
                    dx    = (xh - xl) / 2.0;
                    root_ = xl + dx;
                }
                else // Newton
                {
                    dx     = froot / dfroot;
                    root_ -= dx;
                }

                // Convergence criterion
                if (Math.Abs(dx) < xAccuracy)
                {
                    return(root_);
                }

                froot = f.value(root_);
                ++evaluationNumber_;
                dfroot = (frootold - froot) / (rootold - root_);

                if (froot < 0.0)
                {
                    xl = root_;
                }
                else
                {
                    xh = root_;
                }
            }

            Utils.QL_FAIL("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded",
                          QLNetExceptionEnum.MaxNumberFuncEvalExceeded);
            return(0);
        }
示例#8
0
        //! safe %Newton 1-D solver

        /*! \note This solver requires that the passed function object
         *        implement a method <tt>Real derivative(Real)</tt>.
         */
        protected override double solveImpl(ISolver1d f, double xAccuracy)
        {
            /* The implementation of the algorithm was inspired by Press, Teukolsky, Vetterling, and Flannery,
             * "Numerical Recipes in C", 2nd edition, Cambridge University Press */

            double froot, dfroot, dx, dxold;
            double xh, xl;

            // Orient the search so that f(xl) < 0
            if (fxMin_ < 0.0)
            {
                xl = xMin_;
                xh = xMax_;
            }
            else
            {
                xh = xMin_;
                xl = xMax_;
            }

            // the "stepsize before last"
            dxold = xMax_ - xMin_;
            // it was dxold=std::fabs(xMax_-xMin_); in Numerical Recipes
            // here (xMax_-xMin_ > 0) is verified in the constructor

            // and the last step
            dx = dxold;

            froot  = f.value(root_);
            dfroot = f.derivative(root_);
            if (dfroot.IsEqual(default(double)))
            {
                throw new ArgumentException("Newton requires function's derivative");
            }
            ++evaluationNumber_;

            while (evaluationNumber_ <= maxEvaluations_)
            {
                // Bisect if (out of range || not decreasing fast enough)
                if ((((root_ - xh) * dfroot - froot) *
                     ((root_ - xl) * dfroot - froot) > 0.0) ||
                    (Math.Abs(2.0 * froot) > Math.Abs(dxold * dfroot)))
                {
                    dxold = dx;
                    dx    = (xh - xl) / 2.0;
                    root_ = xl + dx;
                }
                else
                {
                    dxold  = dx;
                    dx     = froot / dfroot;
                    root_ -= dx;
                }
                // Convergence criterion
                if (Math.Abs(dx) < xAccuracy)
                {
                    return(root_);
                }
                froot  = f.value(root_);
                dfroot = f.derivative(root_);
                evaluationNumber_++;
                if (froot < 0.0)
                {
                    xl = root_;
                }
                else
                {
                    xh = root_;
                }
            }

            Utils.QL_FAIL("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded",
                          QLNetExceptionEnum.MaxNumberFuncEvalExceeded);
            return(0);
        }