Exemplo n.º 1
0
        /// <summary>
        ///   Gets the inverse of the cumulative distribution function (icdf) for
        ///   this distribution evaluated at probability <c>p</c>. This function
        ///   is also known as the Quantile function.
        /// </summary>
        ///
        /// <param name="p">A probability value between 0 and 1.</param>
        ///
        /// <returns>
        ///   A sample which could original the given probability
        ///   value when applied in the <see cref="UnivariateContinuousDistribution.DistributionFunction(double)"/>.
        /// </returns>
        ///
        protected internal override double InnerInverseDistributionFunction(double p)
        {
            if (this.exact)
            {
                if (n1 > n2)
                {
                    Trace.TraceWarning("Warning: Using a MannWhitneyDistribution where the first sample is larger than the second.");
                    double lower = 0;
                    double upper = 0;

                    double f = DistributionFunction(0);

                    if (f > p)
                    {
                        while (f > p && !double.IsInfinity(lower))
                        {
                            lower = upper;
                            upper = 2 * upper + 1;
                            f     = DistributionFunction(upper);
                        }
                    }
                    else if (f < p)
                    {
                        while (f < p && !double.IsInfinity(upper))
                        {
                            upper = lower;
                            lower = 2 * lower - 1;
                            f     = DistributionFunction(lower);
                        }
                    }
                    else
                    {
                        return(0);
                    }

                    if (double.IsNegativeInfinity(lower))
                    {
                        lower = double.MinValue;
                    }

                    if (double.IsPositiveInfinity(upper))
                    {
                        upper = double.MaxValue;
                    }

                    double value = BrentSearch.Find(DistributionFunction, p, lower, upper);

                    return(value);
                }

                return(base.InnerInverseDistributionFunction(p));
            }

            return(approximation.InverseDistributionFunction(p));
        }
Exemplo n.º 2
0
        /// <summary>
        ///   Gets the cumulative distribution function (cdf) for
        ///   this distribution evaluated at point <c>x</c>.
        /// </summary>
        ///
        /// <param name="x">A single point in the distribution range.</param>
        ///
        public override double DistributionFunction(double x)
        {
            if (x < Support.Min)
            {
                return(0);
            }
            if (x > Support.Max)
            {
                return(1);
            }

            return(BrentSearch.Find(InverseDistributionFunction, x, 0, 1, 1e-10));
        }
        /// <summary>
        ///   Computes recommended sample size for the test to attain
        ///   the power indicated in <see cref="Power"/> considering
        ///   values of <see cref="Effect"/> and <see cref="Size"/>.
        /// </summary>
        ///
        /// <returns>Recommended sample size for attaining the given
        /// <see cref="Power"/> for size effect <see cref="Effect"/>
        /// under the given <see cref="Size"/>.</returns>
        ///
        public virtual void ComputeSamples()
        {
            double requiredPower = Power;

            // Attempt to locate the optimal sample size
            // to attain the required power by locating
            // a zero in the difference function:
            var search = new BrentSearch(n =>
            {
                Samples = n;
                ComputePower();

                return(Power);
            },

                                         lowerBound: 2,
                                         upperBound: 1e+4);

            Samples = search.Find(requiredPower) ? search.Solution : double.NaN;
            Power   = requiredPower;
        }
Exemplo n.º 4
0
        public void FindTest()
        {
            //  Example from http://en.wikipedia.org/wiki/Brent%27s_method
            double value = 10;

            Func <double, double> f = x => (x + 3) * Math.Pow((x - 1), 2) + value;
            double a = -4;
            double b = 4 / 3.0;

            double expected = -3;
            double actual   = BrentSearch.Find(f, value, a, b);

            Assert.AreEqual(expected, actual, 1e-6);
            Assert.AreEqual(value, f(actual), 1e-5);

            var  search    = new BrentSearch(f, a, b);
            bool isSuccess = search.Find(value);

            Assert.IsTrue(isSuccess);
            Assert.AreEqual(BrentSearchStatus.Success, search.Status);
            Assert.AreEqual(expected, search.Solution, 1e-6);
            Assert.AreEqual(value, search.Value, 1e-5);
        }
        /// <summary>
        ///   Gets the inverse of the cumulative distribution function (icdf) for
        ///   this distribution evaluated at probability <c>p</c>. This function
        ///   is also known as the Quantile function.
        /// </summary>
        ///
        /// <remarks>
        ///   The Inverse Cumulative Distribution Function (ICDF) specifies, for
        ///   a given probability, the value which the random variable will be at,
        ///   or below, with that probability.
        /// </remarks>
        ///
        /// <param name="p">A probability value between 0 and 1.</param>
        ///
        /// <returns>A sample which could original the given probability
        ///   value when applied in the <see cref="DistributionFunction(double)"/>.</returns>
        ///
        public virtual double InverseDistributionFunction(
#if !NET35
            [RangeAttribute(0, 1)]
#endif
            double p)
        {
            if (p < 0.0 || p > 1.0)
            {
                throw new ArgumentOutOfRangeException("p", "Value must be between 0 and 1.");
            }

            if (Double.IsNaN(p))
            {
                throw new ArgumentOutOfRangeException("p", "Value is Not-a-Number (NaN).");
            }

            if (p == 0)
            {
                return(Support.Min);
            }

            else if (p == 1)
            {
                return(Support.Max);
            }

            bool lowerBounded = !Double.IsInfinity(Support.Min);
            bool upperBounded = !Double.IsInfinity(Support.Max);

            double lower;
            double upper;
            double f;

            if (lowerBounded && upperBounded)
            {
                lower = Support.Min;
                upper = Support.Max;
                f     = 0.5;
            }

            else if (lowerBounded && !upperBounded)
            {
                lower = Support.Min;
                upper = lower + 1;

                f = DistributionFunction(lower);

                if (f > p)
                {
                    while (f > p && !Double.IsInfinity(upper))
                    {
                        upper += 2 * (upper - lower) + 1;
                        f      = DistributionFunction(upper);
                    }
                }
                else
                {
                    while (f < p && !Double.IsInfinity(upper))
                    {
                        upper += 2 * (upper - lower) + 1;
                        f      = DistributionFunction(upper);
                    }
                }
            }

            else if (!lowerBounded && upperBounded)
            {
                upper = Support.Max;
                lower = upper - 1;

                f = DistributionFunction(upper);

                if (f > p)
                {
                    while (f > p && !Double.IsInfinity(lower))
                    {
                        lower = lower - 2 * lower;
                        f     = DistributionFunction(lower);
                    }
                }
                else
                {
                    while (f < p && !Double.IsInfinity(lower))
                    {
                        lower = lower - 2 * lower;
                        f     = DistributionFunction(lower);
                    }
                }
            }

            else // completely unbounded
            {
                lower = 0;
                upper = 0;

                f = DistributionFunction(0);

                if (f > p)
                {
                    while (f > p && !Double.IsInfinity(lower))
                    {
                        upper = lower;
                        lower = 2 * lower - 1;
                        f     = DistributionFunction(lower);
                    }
                }
                else
                {
                    while (f < p && !Double.IsInfinity(upper))
                    {
                        lower = upper;
                        upper = 2 * upper + 1;
                        f     = DistributionFunction(upper);
                    }
                }
            }

            if (Double.IsNegativeInfinity(lower))
            {
                lower = Double.MinValue;
            }

            if (Double.IsPositiveInfinity(upper))
            {
                upper = Double.MaxValue;
            }

            double value = BrentSearch.Find(DistributionFunction, p, lower, upper);

            return(value);
        }
        /// <summary>
        ///   Gets the inverse of the cumulative distribution function (icdf) for
        ///   this distribution evaluated at probability <c>p</c>. This function
        ///   is also known as the Quantile function.
        /// </summary>
        ///
        /// <remarks>
        ///   The Inverse Cumulative Distribution Function (ICDF) specifies, for
        ///   a given probability, the value which the random variable will be at,
        ///   or below, with that probability.
        /// </remarks>
        ///
        /// <param name="p">A probability value between 0 and 1.</param>
        ///
        /// <returns>A sample which could original the given probability
        ///   value when applied in the <see cref="DistributionFunction"/>.</returns>
        ///
        public virtual double InverseDistributionFunction(
#if !NET35
            [RangeAttribute(0, 1)]
#endif
            double p)
        {
            bool lowerBounded = !Double.IsInfinity(Support.Min);
            bool upperBounded = !Double.IsInfinity(Support.Max);

            if (lowerBounded && upperBounded)
            {
                return(BrentSearch.Find(DistributionFunction, p, Support.Min, Support.Max));
            }

            if (lowerBounded && !upperBounded)
            {
                double lower = Support.Min;
                double upper = lower + 1;

                double f = DistributionFunction(lower);

                if (f > p)
                {
                    while (f > p)
                    {
                        upper = 2 * upper;
                        f     = DistributionFunction(upper);
                    }
                }
                else
                {
                    while (f < p)
                    {
                        upper = 2 * upper;
                        f     = DistributionFunction(upper);
                    }
                }

                return(BrentSearch.Find(DistributionFunction, p, lower, upper));
            }

            if (!lowerBounded && upperBounded)
            {
                double upper = Support.Max;
                double lower = upper - 1;

                double f = DistributionFunction(upper);

                if (f > p)
                {
                    while (f > p)
                    {
                        lower = lower - 2 * lower;
                        f     = DistributionFunction(lower);
                    }
                }
                else
                {
                    while (f < p)
                    {
                        lower = lower - 2 * lower;
                        f     = DistributionFunction(lower);
                    }
                }

                return(BrentSearch.Find(DistributionFunction, p, lower, upper));
            }

            // completely unbounded
            {
                int lower = 0;
                int upper = 0;

                double f = DistributionFunction(0);

                if (f > p)
                {
                    while (f > p)
                    {
                        upper = lower;
                        lower = 2 * lower - 1;
                        f     = DistributionFunction(lower);
                    }
                }
                else
                {
                    while (f < p)
                    {
                        lower = upper;
                        upper = 2 * upper + 1;
                        f     = DistributionFunction(upper);
                    }
                }

                return(BrentSearch.Find(DistributionFunction, p, lower, upper));
            }
        }
Exemplo n.º 7
0
 /// <summary>
 ///   Gets the cumulative distribution function (cdf) for
 ///   this distribution evaluated at point <c>x</c>.
 /// </summary>
 ///
 /// <param name="x">A single point in the distribution range.</param>
 ///
 protected internal override double InnerDistributionFunction(double x)
 {
     return(BrentSearch.Find(InverseDistributionFunction, x, 0, 1, 1e-10));
 }