7 changed files with 901 additions and 5 deletions
@ -0,0 +1,582 @@ |
|||
// <copyright file="BetaScaled.cs" company="Math.NET">
|
|||
// Math.NET Numerics, part of the Math.NET Project
|
|||
// http://numerics.mathdotnet.com
|
|||
// http://github.com/mathnet/mathnet-numerics
|
|||
// http://mathnetnumerics.codeplex.com
|
|||
//
|
|||
// Copyright (c) 2009-2015 Math.NET
|
|||
//
|
|||
// Permission is hereby granted, free of charge, to any person
|
|||
// obtaining a copy of this software and associated documentation
|
|||
// files (the "Software"), to deal in the Software without
|
|||
// restriction, including without limitation the rights to use,
|
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||
// copies of the Software, and to permit persons to whom the
|
|||
// Software is furnished to do so, subject to the following
|
|||
// conditions:
|
|||
//
|
|||
// The above copyright notice and this permission notice shall be
|
|||
// included in all copies or substantial portions of the Software.
|
|||
//
|
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|||
// OTHER DEALINGS IN THE SOFTWARE.
|
|||
// </copyright>
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using MathNet.Numerics.Properties; |
|||
using MathNet.Numerics.Random; |
|||
using MathNet.Numerics.Threading; |
|||
|
|||
namespace MathNet.Numerics.Distributions |
|||
{ |
|||
public class BetaScaled : IContinuousDistribution |
|||
{ |
|||
System.Random _random; |
|||
|
|||
readonly double _shapeA; |
|||
readonly double _shapeB; |
|||
readonly double _location; |
|||
readonly double _scale; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the BetaScaled class.
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
public BetaScaled(double a, double b, double location, double scale) |
|||
{ |
|||
if (!IsValidParameterSet(a, b, location, scale)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
_random = SystemRandomSource.Default; |
|||
_shapeA = a; |
|||
_shapeB = b; |
|||
_location = location; |
|||
_scale = scale; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the BetaScaled class.
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
|
|||
public BetaScaled(double a, double b, double location, double scale, System.Random randomSource) |
|||
{ |
|||
if (!IsValidParameterSet(a, b, location, scale)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
_random = SystemRandomSource.Default; |
|||
_shapeA = a; |
|||
_shapeB = b; |
|||
_location = location; |
|||
_scale = scale; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A string representation of the distribution.
|
|||
/// </summary>
|
|||
/// <returns>A string representation of the BetaScaled distribution.</returns>
|
|||
public override string ToString() |
|||
{ |
|||
return "BetaScaled(α = " + _shapeA + ", β = " + _shapeB + ", μ = " + _location + ", σ = " + _scale + ")"; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests whether the provided values are valid parameters for this distribution.
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
public static bool IsValidParameterSet(double a, double b, double location, double scale) |
|||
{ |
|||
return a > 0.0 && b > 0.0 && scale > 0.0 && !double.IsNaN(location); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the α shape parameter of the BetaScaled distribution. Range: α > 0.
|
|||
/// </summary>
|
|||
public double A |
|||
{ |
|||
get { return _shapeA; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the β shape parameter of the BetaScaled distribution. Range: β > 0.
|
|||
/// </summary>
|
|||
public double B |
|||
{ |
|||
get { return _shapeB; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the location (μ) of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Location |
|||
{ |
|||
get { return _location; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the scale (σ) of the BetaScaled distribution. Range: σ > 0.
|
|||
/// </summary>
|
|||
public double Scale |
|||
{ |
|||
get { return _scale; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the random number generator which is used to draw random samples.
|
|||
/// </summary>
|
|||
public System.Random RandomSource |
|||
{ |
|||
get { return _random; } |
|||
set { _random = value ?? SystemRandomSource.Default; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the mean of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Mean |
|||
{ |
|||
get |
|||
{ |
|||
if (double.IsPositiveInfinity(_shapeA) && double.IsPositiveInfinity(_shapeB)) |
|||
{ |
|||
return _location + 0.5 * _scale; |
|||
} |
|||
|
|||
if (double.IsPositiveInfinity(_shapeA)) |
|||
{ |
|||
return _location + _scale; |
|||
} |
|||
|
|||
if (double.IsPositiveInfinity(_shapeB)) |
|||
{ |
|||
return _location; |
|||
} |
|||
|
|||
return (_shapeB*_location + _shapeA*(_location + _scale))/(_shapeA + _shapeB); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the variance of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Variance |
|||
{ |
|||
get |
|||
{ |
|||
double sum = _shapeA + _shapeB; |
|||
return (_shapeA*_shapeB*_scale*_scale)/(sum*sum*(1.0 + sum)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the standard deviation of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double StdDev |
|||
{ |
|||
get { return Math.Sqrt(Variance); } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the entropy of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Entropy |
|||
{ |
|||
get { throw new NotSupportedException(); } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the skewness of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Skewness |
|||
{ |
|||
get |
|||
{ |
|||
if (double.IsPositiveInfinity(_shapeA) && double.IsPositiveInfinity(_shapeB)) |
|||
{ |
|||
return 0.0; |
|||
} |
|||
|
|||
if (double.IsPositiveInfinity(_shapeA)) |
|||
{ |
|||
return -2.0*_scale/Math.Sqrt(_shapeB*_scale*_scale); |
|||
} |
|||
|
|||
if (double.IsPositiveInfinity(_shapeB)) |
|||
{ |
|||
return 2.0*_scale/Math.Sqrt(_shapeA*_scale*_scale); |
|||
} |
|||
|
|||
double sum = _shapeA + _shapeB; |
|||
double variance = (_shapeA * _shapeB * _scale * _scale) / (sum * sum * (1.0 + sum)); |
|||
return 2.0*(_shapeB - _shapeA)*_scale/(sum*(2.0 + sum)*Math.Sqrt(variance)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the mode of the BetaScaled distribution; when there are multiple answers, this routine will return 0.5.
|
|||
/// </summary>
|
|||
public double Mode |
|||
{ |
|||
get |
|||
{ |
|||
if (double.IsPositiveInfinity(_shapeA) && double.IsPositiveInfinity(_shapeB)) |
|||
{ |
|||
return _location + 0.5 * _scale; |
|||
} |
|||
|
|||
if (double.IsPositiveInfinity(_shapeA)) |
|||
{ |
|||
return _location + _scale; |
|||
} |
|||
|
|||
if (double.IsPositiveInfinity(_shapeB)) |
|||
{ |
|||
return _location; |
|||
} |
|||
|
|||
if (_shapeA == 1.0 && _shapeB == 1.0) |
|||
{ |
|||
return _location + 0.5 * _scale; |
|||
} |
|||
|
|||
return ((_shapeA - 1)/(_shapeA + _shapeB - 2))*_scale + _location; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the median of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Median |
|||
{ |
|||
get { throw new NotSupportedException(); } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the minimum of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Minimum |
|||
{ |
|||
get { return _location; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the maximum of the BetaScaled distribution.
|
|||
/// </summary>
|
|||
public double Maximum |
|||
{ |
|||
get { return _location + _scale; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the probability density of the distribution (PDF) at x, i.e. ∂P(X ≤ x)/∂x.
|
|||
/// </summary>
|
|||
/// <param name="x">The location at which to compute the density.</param>
|
|||
/// <returns>the density at <paramref name="x"/>.</returns>
|
|||
/// <seealso cref="PDF"/>
|
|||
public double Density(double x) |
|||
{ |
|||
return PDF(_shapeA, _shapeB, _location, _scale, x); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the log probability density of the distribution (lnPDF) at x, i.e. ln(∂P(X ≤ x)/∂x).
|
|||
/// </summary>
|
|||
/// <param name="x">The location at which to compute the log density.</param>
|
|||
/// <returns>the log density at <paramref name="x"/>.</returns>
|
|||
/// <seealso cref="PDFLn"/>
|
|||
public double DensityLn(double x) |
|||
{ |
|||
return PDFLn(_shapeA, _shapeB, _location, _scale, x); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the cumulative distribution (CDF) of the distribution at x, i.e. P(X ≤ x).
|
|||
/// </summary>
|
|||
/// <param name="x">The location at which to compute the cumulative distribution function.</param>
|
|||
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
|
|||
/// <seealso cref="CDF"/>
|
|||
public double CumulativeDistribution(double x) |
|||
{ |
|||
return CDF(_shapeA, _shapeB, _location, _scale, x); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the inverse of the cumulative distribution function (InvCDF) for the distribution
|
|||
/// at the given probability. This is also known as the quantile or percent point function.
|
|||
/// </summary>
|
|||
/// <param name="p">The location at which to compute the inverse cumulative density.</param>
|
|||
/// <returns>the inverse cumulative density at <paramref name="p"/>.</returns>
|
|||
/// <seealso cref="InvCDF"/>
|
|||
/// <remarks>WARNING: currently not an explicit implementation, hence slow and unreliable.</remarks>
|
|||
public double InverseCumulativeDistribution(double p) |
|||
{ |
|||
return InvCDF(_shapeA, _shapeB, _location, _scale, p); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sample from the distribution.
|
|||
/// </summary>
|
|||
/// <returns>a sample from the distribution.</returns>
|
|||
public double Sample() |
|||
{ |
|||
return SampleUnchecked(_random, _shapeA, _shapeB, _location, _scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Fills an array with samples generated from the distribution.
|
|||
/// </summary>
|
|||
public void Samples(double[] values) |
|||
{ |
|||
SamplesUnchecked(_random, values, _shapeA, _shapeB, _location, _scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sequence of samples from the distribution.
|
|||
/// </summary>
|
|||
/// <returns>a sequence of samples from the distribution.</returns>
|
|||
public IEnumerable<double> Samples() |
|||
{ |
|||
return SamplesUnchecked(_random, _shapeA, _shapeB, _location, _scale); |
|||
} |
|||
|
|||
static double SampleUnchecked(System.Random rnd, double a, double b, double location, double scale) |
|||
{ |
|||
return Beta.SampleUnchecked(rnd, a, b)*scale + location; |
|||
} |
|||
|
|||
static void SamplesUnchecked(System.Random rnd, double[] values, double a, double b, double location, double scale) |
|||
{ |
|||
Beta.SamplesUnchecked(rnd, values, a, b); |
|||
CommonParallel.For(0, values.Length, 4096, (aa, bb) => |
|||
{ |
|||
for (int i = aa; i < bb; i++) |
|||
{ |
|||
values[i] = values[i]*scale + location; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
static IEnumerable<double> SamplesUnchecked(System.Random rnd, double a, double b, double location, double scale) |
|||
{ |
|||
while (true) |
|||
{ |
|||
yield return SampleUnchecked(rnd, a, b, location, scale); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the probability density of the distribution (PDF) at x, i.e. ∂P(X ≤ x)/∂x.
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <param name="x">The location at which to compute the density.</param>
|
|||
/// <returns>the density at <paramref name="x"/>.</returns>
|
|||
/// <seealso cref="Density"/>
|
|||
public static double PDF(double a, double b, double location, double scale, double x) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return Beta.PDF(a, b, (x - location)/scale)/Math.Abs(scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the log probability density of the distribution (lnPDF) at x, i.e. ln(∂P(X ≤ x)/∂x).
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <param name="x">The location at which to compute the density.</param>
|
|||
/// <returns>the log density at <paramref name="x"/>.</returns>
|
|||
/// <seealso cref="DensityLn"/>
|
|||
public static double PDFLn(double a, double b, double location, double scale, double x) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return Beta.PDFLn(a, b, (x - location)/scale) - Math.Log(Math.Abs(scale)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the cumulative distribution (CDF) of the distribution at x, i.e. P(X ≤ x).
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <param name="x">The location at which to compute the cumulative distribution function.</param>
|
|||
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
|
|||
/// <seealso cref="CumulativeDistribution"/>
|
|||
public static double CDF(double a, double b, double location, double scale, double x) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return Beta.CDF(a, b, (x - location) / scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the inverse of the cumulative distribution function (InvCDF) for the distribution
|
|||
/// at the given probability. This is also known as the quantile or percent point function.
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <param name="p">The location at which to compute the inverse cumulative density.</param>
|
|||
/// <returns>the inverse cumulative density at <paramref name="p"/>.</returns>
|
|||
/// <seealso cref="InverseCumulativeDistribution"/>
|
|||
/// <remarks>WARNING: currently not an explicit implementation, hence slow and unreliable.</remarks>
|
|||
public static double InvCDF(double a, double b, double location, double scale, double p) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return Beta.InvCDF(a, b, p)*scale + location; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sample from the distribution.
|
|||
/// </summary>
|
|||
/// <param name="rnd">The random number generator to use.</param>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <returns>a sample from the distribution.</returns>
|
|||
public static double Sample(System.Random rnd, double a, double b, double location, double scale) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return SampleUnchecked(rnd, a, b, location, scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sequence of samples from the distribution.
|
|||
/// </summary>
|
|||
/// <param name="rnd">The random number generator to use.</param>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <returns>a sequence of samples from the distribution.</returns>
|
|||
public static IEnumerable<double> Samples(System.Random rnd, double a, double b, double location, double scale) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return SamplesUnchecked(rnd, a, b, location, scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Fills an array with samples generated from the distribution.
|
|||
/// </summary>
|
|||
/// <param name="rnd">The random number generator to use.</param>
|
|||
/// <param name="values">The array to fill with the samples.</param>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <returns>a sequence of samples from the distribution.</returns>
|
|||
public static void Samples(System.Random rnd, double[] values, double a, double b, double location, double scale) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
SamplesUnchecked(rnd, values, a, b, location, scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sample from the distribution.
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <returns>a sample from the distribution.</returns>
|
|||
public static double Sample(double a, double b, double location, double scale) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return SampleUnchecked(SystemRandomSource.Default, a, b, location, scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sequence of samples from the distribution.
|
|||
/// </summary>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <returns>a sequence of samples from the distribution.</returns>
|
|||
public static IEnumerable<double> Samples(double a, double b, double location, double scale) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
return SamplesUnchecked(SystemRandomSource.Default, a, b, location, scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Fills an array with samples generated from the distribution.
|
|||
/// </summary>
|
|||
/// <param name="values">The array to fill with the samples.</param>
|
|||
/// <param name="a">The α shape parameter of the BetaScaled distribution. Range: α > 0.</param>
|
|||
/// <param name="b">The β shape parameter of the BetaScaled distribution. Range: β > 0.</param>
|
|||
/// <param name="location">The location (μ) of the distribution.</param>
|
|||
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
|
|||
/// <returns>a sequence of samples from the distribution.</returns>
|
|||
public static void Samples(double[] values, double a, double b, double location, double scale) |
|||
{ |
|||
if (!(a > 0.0 && b > 0.0 && scale > 0.0) || double.IsNaN(location)) |
|||
{ |
|||
throw new ArgumentException(Resources.InvalidDistributionParameters); |
|||
} |
|||
|
|||
SamplesUnchecked(SystemRandomSource.Default, values, a, b, location, scale); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,311 @@ |
|||
// <copyright file="BetaTests.cs" company="Math.NET">
|
|||
// Math.NET Numerics, part of the Math.NET Project
|
|||
// http://numerics.mathdotnet.com
|
|||
// http://github.com/mathnet/mathnet-numerics
|
|||
// http://mathnetnumerics.codeplex.com
|
|||
//
|
|||
// Copyright (c) 2009-2015 Math.NET
|
|||
//
|
|||
// Permission is hereby granted, free of charge, to any person
|
|||
// obtaining a copy of this software and associated documentation
|
|||
// files (the "Software"), to deal in the Software without
|
|||
// restriction, including without limitation the rights to use,
|
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||
// copies of the Software, and to permit persons to whom the
|
|||
// Software is furnished to do so, subject to the following
|
|||
// conditions:
|
|||
//
|
|||
// The above copyright notice and this permission notice shall be
|
|||
// included in all copies or substantial portions of the Software.
|
|||
//
|
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|||
// OTHER DEALINGS IN THE SOFTWARE.
|
|||
// </copyright>
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using MathNet.Numerics.Distributions; |
|||
using NUnit.Framework; |
|||
|
|||
namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous |
|||
{ |
|||
using Random = System.Random; |
|||
|
|||
/// <summary>
|
|||
/// BetaScaled distribution tests.
|
|||
/// </summary>
|
|||
[TestFixture, Category("Distributions")] |
|||
public class BetaScaledTests |
|||
{ |
|||
/// <summary>
|
|||
/// Can create BetaScaled distribution.
|
|||
/// </summary>
|
|||
[TestCase(1.0, 1.0, -1.0, 1.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0)] |
|||
[TestCase(5.0, 100.0, 0.0, 1.0)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, Double.PositiveInfinity)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, Double.PositiveInfinity, 1.0)] |
|||
public void CanCreateBetaScaled(double a, double b, double location, double scale) |
|||
{ |
|||
var n = new BetaScaled(a, b, location, scale); |
|||
Assert.AreEqual(a, n.A); |
|||
Assert.AreEqual(b, n.B); |
|||
Assert.AreEqual(location, n.Location); |
|||
Assert.AreEqual(scale, n.Scale); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// BetaScaled create fails with bad parameters.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void BetaScaledCreateFailsWithBadParameters() |
|||
{ |
|||
Assert.That(() => new BetaScaled(Double.NaN, 1.0, 0.0, 1.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(1.0, Double.NaN, 0.0, 1.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(Double.NaN, Double.NaN, 0.0, 1.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(1.0, 1.0, Double.NaN, 1.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(1.0, 1.0, 1.0, Double.NaN), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(1.0, 0.0, 0.0, 1.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(0.0, 1.0, 0.0, 1.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(-1.0, -1.0, 0.0, 1.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(1.0, 1.0, 1.0, 0.0), Throws.ArgumentException); |
|||
Assert.That(() => new BetaScaled(1.0, 1.0, 1.0, -1.0), Throws.ArgumentException); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validate to string.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void ValidateToString() |
|||
{ |
|||
var n = new BetaScaled(1d, 2d, 0.0, 1.0); |
|||
Assert.AreEqual("BetaScaled(α = 1, β = 2, μ = 0, σ = 1)", n.ToString()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validate mean.
|
|||
/// </summary>
|
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.5)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.9)] |
|||
[TestCase(5.0, 100.0, 0.0, 1.0, 0.047619047619047619047616)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 1.0)] |
|||
public void ValidateMean(double a, double b, double location, double scale, double mean) |
|||
{ |
|||
var n = new BetaScaled(a, b, location, scale); |
|||
Assert.AreEqual(mean, n.Mean); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validate skewness.
|
|||
/// </summary>
|
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, -1.4740554623801777107177478829647496373009282424841579)] |
|||
[TestCase(5.0, 100.0, 0.0, 1.0, 0.81759410927553430354583159143895018978562196953345572)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 2.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, -2.0)] |
|||
public void ValidateSkewness(double a, double b, double location, double scale, double skewness) |
|||
{ |
|||
var n = new BetaScaled(a, b, location, scale); |
|||
AssertHelpers.AlmostEqualRelative(skewness, n.Skewness, 14); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validate mode.
|
|||
/// </summary>
|
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.5)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 1.0)] |
|||
[TestCase(5.0, 100.0, 0.0, 1.0, 0.038834951456310676243255386452801758423447608947753906)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 1.0)] |
|||
public void ValidateMode(double a, double b, double location, double scale, double mode) |
|||
{ |
|||
var n = new BetaScaled(a, b, location, scale); |
|||
Assert.AreEqual(mode, n.Mode); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validate median throws <c>NotSupportedException</c>.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void ValidateMedianThrowsNotSupportedException() |
|||
{ |
|||
var n = new BetaScaled(1.0, 1.0, 0.0, 1.0); |
|||
Assert.Throws<NotSupportedException>(() => { var m = n.Median; }); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validate minimum.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void ValidateMinimum() |
|||
{ |
|||
var n = new BetaScaled(1.0, 1.0, 0.0, 1.0); |
|||
Assert.AreEqual(0.0, n.Minimum); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validate maximum.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void ValidateMaximum() |
|||
{ |
|||
var n = new BetaScaled(1.0, 1.0, 0.0, 1.0); |
|||
Assert.AreEqual(1.0, n.Maximum); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Can sample static.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void CanSampleStatic() |
|||
{ |
|||
BetaScaled.Sample(new Random(0), 2.0, 3.0, 0.0, 1.0); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Can sample sequence static.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void CanSampleSequenceStatic() |
|||
{ |
|||
var ied = BetaScaled.Samples(new Random(0), 2.0, 3.0, 0.0, 1.0); |
|||
GC.KeepAlive(ied.Take(5).ToArray()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Fail sample static with wrong parameters.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void FailSampleStatic() |
|||
{ |
|||
Assert.That(() => BetaScaled.Sample(new Random(0), 1.0, -1.0, 0.0, 1.0), Throws.ArgumentException); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Fail sample sequence static with wrong parameters.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void FailSampleSequenceStatic() |
|||
{ |
|||
Assert.That(() => BetaScaled.Samples(new Random(0), 1.0, -1.0, 0.0, 1.0).First(), Throws.ArgumentException); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Can sample.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void CanSample() |
|||
{ |
|||
var n = new BetaScaled(2.0, 3.0, 0.0, 1.0); |
|||
n.Sample(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Can sample sequence.
|
|||
/// </summary>
|
|||
[Test] |
|||
public void CanSampleSequence() |
|||
{ |
|||
var n = new BetaScaled(2.0, 3.0, 0.0, 1.0); |
|||
var ied = n.Samples(); |
|||
GC.KeepAlive(ied.Take(5).ToArray()); |
|||
} |
|||
|
|||
/// <remarks>Reference: N[PDF[TransformedDistribution[l + s d, d \[Distributed] BetaDistribution[a, b]], x], 20]</remarks>
|
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.0, 1.0)] |
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.5, 1.0)] |
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 1.0, 1.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.5, 0.03515625)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 1.0, 9.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, -1.0, 0.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 2.0, 0.0)] |
|||
[TestCase(9.0, 1.0, -2.0, 2.0, -0.5, 0.450508)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 0.5, 1.0881845516040810386311829462908430145307026037926335e-21)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 1.0, 0.0)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.0, Double.PositiveInfinity)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.5, 0.0)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 1.0, 0.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 0.5, 0.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 1.0, Double.PositiveInfinity)] |
|||
public void ValidateDensity(double a, double b, double location, double scale, double x, double pdf) |
|||
{ |
|||
var n = new BetaScaled(a, b, location, scale); |
|||
AssertHelpers.AlmostEqualRelative(pdf, n.Density(x), 5); |
|||
AssertHelpers.AlmostEqualRelative(pdf, BetaScaled.PDF(a, b, location, scale, x), 5); |
|||
} |
|||
|
|||
/// <remarks>Reference: N[Log[PDF[TransformedDistribution[l + s d, d \[Distributed] BetaDistribution[a, b]], x]], 20]</remarks>
|
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.5, 0.0)] |
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 1.0, 0.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.0, Double.NegativeInfinity)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.5, -3.3479528671433430925473664978203611353090199592365458)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 1.0, 2.1972245773362193827904904738450514092949811156454996)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, -1.0, Double.NegativeInfinity)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 2.0, Double.NegativeInfinity)] |
|||
[TestCase(9.0, 1.0, -2.0, 2.0, -0.5, -0.797379)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 0.0, Double.NegativeInfinity)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 0.5, -51.447830024537682154565870837960406410586196074573801)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 1.0, Double.NegativeInfinity)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.0, Double.PositiveInfinity)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.5, Double.NegativeInfinity)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 1.0, Double.NegativeInfinity)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 0.0, Double.NegativeInfinity)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 0.5, Double.NegativeInfinity)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 1.0, Double.PositiveInfinity)] |
|||
public void ValidateDensityLn(double a, double b, double location, double scale, double x, double pdfln) |
|||
{ |
|||
var n = new BetaScaled(a, b, location, scale); |
|||
AssertHelpers.AlmostEqualRelative(pdfln, n.DensityLn(x), 5); |
|||
AssertHelpers.AlmostEqualRelative(pdfln, BetaScaled.PDFLn(a, b, location, scale, x), 5); |
|||
} |
|||
|
|||
/// <remarks>Reference: N[CDF[TransformedDistribution[l + s d, d \[Distributed] BetaDistribution[a, b]], x], 20]</remarks>
|
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 0.5, 0.5)] |
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 1.0, 1.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.5, 0.001953125)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 1.0, 1.0)] |
|||
[TestCase(9.0, 1.0, -2.0, 2.0, -0.5, 0.0750847)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 0.5, 1.0)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 1.0, 1.0)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.0, 1.0)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 0.5, 1.0)] |
|||
[TestCase(1.0, Double.PositiveInfinity, 0.0, 1.0, 1.0, 1.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 0.5, 0.0)] |
|||
[TestCase(Double.PositiveInfinity, 1.0, 0.0, 1.0, 1.0, 1.0)] |
|||
public void ValidateCumulativeDistribution(double a, double b, double location, double scale, double x, double p) |
|||
{ |
|||
var dist = new BetaScaled(a, b, location, scale); |
|||
Assert.That(dist.CumulativeDistribution(x), Is.EqualTo(p).Within(1e-5)); |
|||
Assert.That(BetaScaled.CDF(a, b, location, scale, x), Is.EqualTo(p).Within(1e-5)); |
|||
} |
|||
|
|||
[TestCase(1.0, 1.0, 0.0, 1.0, 1.0, 1.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.0, 0.0)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 0.5, 0.001953125)] |
|||
[TestCase(9.0, 1.0, 0.0, 1.0, 1.0, 1.0)] |
|||
[TestCase(5.0, 100, 0.0, 1.0, 0.0, 0.0)] |
|||
public void ValidateInverseCumulativeDistribution(double a, double b, double location, double scale, double x, double p) |
|||
{ |
|||
var dist = new BetaScaled(a, b, location, scale); |
|||
Assert.That(dist.InverseCumulativeDistribution(p), Is.EqualTo(x).Within(1e-6)); |
|||
Assert.That(BetaScaled.InvCDF(a, b, location, scale, p), Is.EqualTo(x).Within(1e-6)); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue