/// <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)); }
/// <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; }
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)); } }
/// <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)); }