示例#1
0
        public static double SolveB(double a, double x, double p, double q, double guess, double step, double lower, double upper)
        {
            Func <double, double> f;

            if (p <= q)
            {
                f = b => Math2.Ibeta(a, b, x) - p;
            }
            else
            {
                f = b => Math2.Ibetac(a, b, x) - q;
            }

#if EXTRA_DEBUG
            Debug.WriteLine("IBetaInvB(a={0}, guess?={1}, x={2}) == p({3}), q({4}); range = [{5}, {6}]", a, guess, x, p, q, lower, upper);
#endif

            RootResults r = RootFinder.Toms748Bracket(f, guess, step, FunctionShape.Unknown, lower, upper, _tol, Policies.MaxRootIterations);
            if (r == null)
            {
                Policies.ReportRootNotFoundError("Invalid parameter in root solver");
                return(double.NaN);
            }
            if (!r.Success)
            {
                Policies.ReportRootNotFoundError("Root not found after {0} iterations", r.Iterations);
                return(double.NaN);
            }

#if EXTRA_DEBUG
            Debug.WriteLine("Result = {0};  Toms748 iterations: {1}", r.SolutionX, r.Iterations);
#endif

            return(r.SolutionX);
        }
示例#2
0
        public void HalleyTest()
        {
            foreach (TestData d in _FunctionData)
            {
                double relTolerance = RootFinder.DefaultRelTolerance;
                double absTolerance = d.AbsTolerance;

                RootResults results  = RootFinder.Halley(d.FuncVal_Der1_Der2, d.Guess, d.Min, d.Max, relTolerance, absTolerance, RootFinder.DefaultIterations);
                double      solution = (results == null) ? double.NaN : results.SolutionX;
                if (!AreNear(solution, d.Expected, relTolerance, absTolerance))
                {
                    throw new AssertFailedException(" Halley Solve: (" + d.Description + ") = " + d.Expected + "; got " + solution + " Tolerance: " + d.RelTolerance);
                }
            }


            foreach (TestData d in testUnbracketedData)
            {
                double relTolerance = RootFinder.DefaultRelTolerance;
                double absTolerance = d.AbsTolerance;

                RootResults results  = RootFinder.Halley(d.FuncVal_Der1_Der2, d.Guess, d.Min, d.Max, relTolerance, absTolerance, RootFinder.DefaultIterations);
                double      solution = (results == null) ? double.NaN : results.SolutionX;
                if (!AreNear(solution, d.Expected, relTolerance, absTolerance))
                {
                    throw new AssertFailedException(" Halley Solve: (" + d.Description + ") = " + d.Expected + "; got " + solution + " Tolerance: " + d.RelTolerance);
                }
            }
        }
示例#3
0
        public void BrentTest()
        {
            foreach (TestData d in _FunctionData)
            {
                double relTolerance = RootFinder.DefaultRelTolerance;
                double absTolerance = d.AbsTolerance;

                var tol = RootFinder.GetToleranceFunc(RootFinder.DefaultRelTolerance, d.AbsTolerance);

                RootResults results  = RootFinder.Brent(d.FuncValue, d.Min, d.Max, relTolerance, absTolerance, RootFinder.DefaultIterations);
                double      solution = (results == null) ? double.NaN : results.SolutionX;
                if (!AreNear(solution, d.Expected, relTolerance, absTolerance))
                {
                    throw new AssertFailedException(" Brent Solve: (" + d.Description + ") = " + d.Expected + "; got " + solution + " Tolerance: " + d.RelTolerance);
                }


                results  = RootFinder.BrentBracket(d.FuncValue, d.Guess, d.Step, FunctionShape.Unknown, d.Lmin, d.Lmax, relTolerance, absTolerance, RootFinder.DefaultIterations);
                solution = (results == null) ? double.NaN : results.SolutionX;
                if (!AreNear(solution, d.Expected, relTolerance, absTolerance))
                {
                    throw new AssertFailedException(" Brent Solve: (" + d.Description + ") = " + d.Expected + "; got " + solution + " Tolerance: " + d.RelTolerance);
                }
            }
        }
示例#4
0
        /// <summary>
        /// Use the root finder to solve Q(a,x) == q, for x
        /// </summary>
        /// <param name="a"></param>
        /// <param name="q"></param>
        /// <param name="guess"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static double SolveGivenAQ(double a, double q, double guess, double min, double max)
        {
            Func <double, ValueTuple <double, double, double> > halleyF = (double x) => {
                // Calculate Q(x) - q and the first two derivatives

                double f  = Math2.GammaQ(a, x) - q;
                double f1 = -Math2.GammaPDerivative(a, x);
                double f2 = -f1 * (1.0 + (1.0 - a) / x);
                return(f, f1, f2);
            };


            const double relTolerance = RootFinder.DefaultRelTolerance;
            const double absTolerance = 0;
            RootResults  rr           = RootFinder.Halley(halleyF, guess, min, max, relTolerance, absTolerance, Policies.MaxRootIterations);

            if (rr == null)
            {
                Policies.ReportRootNotFoundError("Invalid parameter in root solver");
                return(double.NaN);
            }
#if EXTRA_DEBUG
            Debug.WriteLine("Halley iterations: {0}", rr.Iterations);
#endif
            if (!rr.Success)
            {
                Policies.ReportRootNotFoundError("Root not found after {0} iterations", rr.Iterations);
                return(double.NaN);
            }

            return(rr.SolutionX);
        }
示例#5
0
        public void BisectionTest()
        {
            foreach (TestData d in _FunctionData)
            {
                double relTolerance = RootFinder.DefaultRelTolerance;
                double absTolerance = d.AbsTolerance;

                // test bisection
                RootResults results = RootFinder.Bisection(d.FuncValue, d.Min, d.Max, relTolerance, absTolerance, RootFinder.DefaultIterations);

                double solution = (results == null) ? double.NaN : results.SolutionX;
                if (!AreNear(solution, d.Expected, relTolerance, absTolerance))
                {
                    throw new AssertFailedException(" Bisection Solve: (" + d.Description + ") = " + d.Expected + "; got " + solution + " Tolerance: " + d.RelTolerance);
                }
            }
        }
示例#6
0
        public static (double Result, int Iterations) SolveA(double z, double p, double q, double aGuess, double step, double min, double max)
        {
            Debug.Assert(aGuess >= min && aGuess <= max, "Guess out of range");

            Func <double, double> f;

            if (p < q)
            {
                f = a => Math2.GammaP(a, z) - p;
            }
            else
            {
                f = a => Math2.GammaQ(a, z) - q;
            }

            //
            // Use our generic derivative-free root finding procedure.
            // We could use Newton steps here, taking the PDF of the
            // Poisson distribution as our derivative, but that's
            // even worse performance-wise than the generic method :-(
            //

            // dQ/da is increasing, dP/da is decreasing
            FunctionShape fShape = (p < q) ? FunctionShape.Decreasing : FunctionShape.Increasing;
            RootResults   rr     = RootFinder.Toms748Bracket(f, aGuess, step, fShape, min, max);

            if (rr == null)
            {
                Policies.ReportRootNotFoundError($"Invalid Parameter: PQInvA(z: {z}, p: {p}, q: {q}) [{min}, {max}] g: {aGuess}");
                return(double.NaN, 0);
            }

            if (!rr.Success)
            {
                Policies.ReportRootNotFoundError("Root not found after {0} iterations", rr.Iterations);
                return(double.NaN, rr.Iterations);
            }

            return(rr.SolutionX, rr.Iterations);
        }