negative_binomial.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 589 行 · 第 1/2 页

HPP
589
字号
// boost\math\special_functions\negative_binomial.hpp// Copyright Paul A. Bristow 2007.// Copyright John Maddock 2007.// Use, modification and distribution are subject to the// Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt// or copy at http://www.boost.org/LICENSE_1_0.txt)// http://en.wikipedia.org/wiki/negative_binomial_distribution// http://mathworld.wolfram.com/NegativeBinomialDistribution.html// http://documents.wolfram.com/teachersedition/Teacher/Statistics/DiscreteDistributions.html// The negative binomial distribution NegativeBinomialDistribution[n, p]// is the distribution of the number (k) of failures that occur in a sequence of trials before// r successes have occurred, where the probability of success in each trial is p.// In a sequence of Bernoulli trials or events// (independent, yes or no, succeed or fail) with success_fraction probability p,// negative_binomial is the probability that k or fewer failures// preceed the r th trial's success.// random variable k is the number of failures (NOT the probability).// Negative_binomial distribution is a discrete probability distribution.// But note that the negative binomial distribution// (like others including the binomial, Poisson & Bernoulli)// is strictly defined as a discrete function: only integral values of k are envisaged.// However because of the method of calculation using a continuous gamma function,// it is convenient to treat it as if a continous function,// and permit non-integral values of k.// However, by default the policy is to use discrete_quantile_policy.// To enforce the strict mathematical model, users should use conversion// on k outside this function to ensure that k is integral.// MATHCAD cumulative negative binomial pnbinom(k, n, p)// Implementation note: much greater speed, and perhaps greater accuracy,// might be achieved for extreme values by using a normal approximation.// This is NOT been tested or implemented.#ifndef BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP#define BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP#include <boost/math/distributions/fwd.hpp>#include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x) == Ix(a, b).#include <boost/math/distributions/complement.hpp> // complement.#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks domain_error & logic_error.#include <boost/math/special_functions/fpclassify.hpp> // isnan.#include <boost/math/tools/roots.hpp> // for root finding.#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>#include <boost/type_traits/is_floating_point.hpp>#include <boost/type_traits/is_integral.hpp>#include <boost/type_traits/is_same.hpp>#include <boost/mpl/if.hpp>#include <limits> // using std::numeric_limits;#include <utility>#if defined (BOOST_MSVC)#  pragma warning(push)// This believed not now necessary, so commented out.//#  pragma warning(disable: 4702) // unreachable code.// in domain_error_imp in error_handling.#endifnamespace boost{  namespace math  {    namespace negative_binomial_detail    {      // Common error checking routines for negative binomial distribution functions:      template <class RealType, class Policy>      inline bool check_successes(const char* function, const RealType& r, RealType* result, const Policy& pol)      {        if( !(boost::math::isfinite)(r) || (r <= 0) )        {          *result = policies::raise_domain_error<RealType>(            function,            "Number of successes argument is %1%, but must be > 0 !", r, pol);          return false;        }        return true;      }      template <class RealType, class Policy>      inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol)      {        if( !(boost::math::isfinite)(p) || (p < 0) || (p > 1) )        {          *result = policies::raise_domain_error<RealType>(            function,            "Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, pol);          return false;        }        return true;      }      template <class RealType, class Policy>      inline bool check_dist(const char* function, const RealType& r, const RealType& p, RealType* result, const Policy& pol)      {        return check_success_fraction(function, p, result, pol)          && check_successes(function, r, result, pol);      }      template <class RealType, class Policy>      inline bool check_dist_and_k(const char* function, const RealType& r, const RealType& p, RealType k, RealType* result, const Policy& pol)      {        if(check_dist(function, r, p, result, pol) == false)        {          return false;        }        if( !(boost::math::isfinite)(k) || (k < 0) )        { // Check k failures.          *result = policies::raise_domain_error<RealType>(            function,            "Number of failures argument is %1%, but must be >= 0 !", k, pol);          return false;        }        return true;      } // Check_dist_and_k      template <class RealType, class Policy>      inline bool check_dist_and_prob(const char* function, const RealType& r, RealType p, RealType prob, RealType* result, const Policy& pol)      {        if(check_dist(function, r, p, result, pol) && detail::check_probability(function, prob, result, pol) == false)        {          return false;        }        return true;      } // check_dist_and_prob    } //  namespace negative_binomial_detail    template <class RealType = double, class Policy = policies::policy<> >    class negative_binomial_distribution    {    public:      typedef RealType value_type;      typedef Policy policy_type;      negative_binomial_distribution(RealType r, RealType p) : m_r(r), m_p(p)      { // Constructor.        RealType result;        negative_binomial_detail::check_dist(          "negative_binomial_distribution<%1%>::negative_binomial_distribution",          m_r, // Check successes r > 0.          m_p, // Check success_fraction 0 <= p <= 1.          &result, Policy());      } // negative_binomial_distribution constructor.      // Private data getter class member functions.      RealType success_fraction() const      { // Probability of success as fraction in range 0 to 1.        return m_p;      }      RealType successes() const      { // Total number of successes r.        return m_r;      }      static RealType find_lower_bound_on_p(        RealType trials,        RealType successes,        RealType alpha) // alpha 0.05 equivalent to 95% for one-sided test.      {        static const char* function = "boost::math::negative_binomial<%1%>::find_lower_bound_on_p";        RealType result;  // of error checks.        RealType failures = trials - successes;        if(false == detail::check_probability(function, alpha, &result, Policy())          && negative_binomial_detail::check_dist_and_k(          function, successes, RealType(0), failures, &result, Policy()))        {          return result;        }        // Use complement ibeta_inv function for lower bound.        // This is adapted from the corresponding binomial formula        // here: http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm        // This is a Clopper-Pearson interval, and may be overly conservative,        // see also "A Simple Improved Inferential Method for Some        // Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY        // http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf        //        return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(0), Policy());      } // find_lower_bound_on_p      static RealType find_upper_bound_on_p(        RealType trials,        RealType successes,        RealType alpha) // alpha 0.05 equivalent to 95% for one-sided test.      {        static const char* function = "boost::math::negative_binomial<%1%>::find_upper_bound_on_p";        RealType result;  // of error checks.        RealType failures = trials - successes;        if(false == negative_binomial_detail::check_dist_and_k(          function, successes, RealType(0), failures, &result, Policy())          && detail::check_probability(function, alpha, &result, Policy()))        {          return result;        }        if(failures == 0)           return 1;        // Use complement ibetac_inv function for upper bound.        // Note adjusted failures value: *not* failures+1 as usual.        // This is adapted from the corresponding binomial formula        // here: http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm        // This is a Clopper-Pearson interval, and may be overly conservative,        // see also "A Simple Improved Inferential Method for Some        // Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY        // http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf        //        return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(0), Policy());      } // find_upper_bound_on_p      // Estimate number of trials :      // "How many trials do I need to be P% sure of seeing k or fewer failures?"      static RealType find_minimum_number_of_trials(        RealType k,     // number of failures (k >= 0).        RealType p,     // success fraction 0 <= p <= 1.        RealType alpha) // risk level threshold 0 <= alpha <= 1.      {        static const char* function = "boost::math::negative_binomial<%1%>::find_minimum_number_of_trials";        // Error checks:        RealType result;        if(false == negative_binomial_detail::check_dist_and_k(          function, RealType(1), p, k, &result, Policy())          && detail::check_probability(function, alpha, &result, Policy()))        { return result; }        result = ibeta_inva(k + 1, p, alpha, Policy());  // returns n - k        return result + k;      } // RealType find_number_of_failures      static RealType find_maximum_number_of_trials(        RealType k,     // number of failures (k >= 0).        RealType p,     // success fraction 0 <= p <= 1.        RealType alpha) // risk level threshold 0 <= alpha <= 1.      {        static const char* function = "boost::math::negative_binomial<%1%>::find_maximum_number_of_trials";        // Error checks:        RealType result;        if(false == negative_binomial_detail::check_dist_and_k(          function, RealType(1), p, k, &result, Policy())          &&  detail::check_probability(function, alpha, &result, Policy()))        { return result; }        result = ibetac_inva(k + 1, p, alpha, Policy());  // returns n - k        return result + k;      } // RealType find_number_of_trials complemented    private:      RealType m_r; // successes.      RealType m_p; // success_fraction    }; // template <class RealType, class Policy> class negative_binomial_distribution    typedef negative_binomial_distribution<double> negative_binomial; // Reserved name of type double.    template <class RealType, class Policy>    inline const std::pair<RealType, RealType> range(const negative_binomial_distribution<RealType, Policy>& /* dist */)    { // Range of permissible values for random variable k.       using boost::math::tools::max_value;       return std::pair<RealType, RealType>(0, max_value<RealType>()); // max_integer?    }    template <class RealType, class Policy>    inline const std::pair<RealType, RealType> support(const negative_binomial_distribution<RealType, Policy>& /* dist */)    { // Range of supported values for random variable k.       // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.       using boost::math::tools::max_value;       return std::pair<RealType, RealType>(0,  max_value<RealType>()); // max_integer?    }    template <class RealType, class Policy>    inline RealType mean(const negative_binomial_distribution<RealType, Policy>& dist)    { // Mean of Negative Binomial distribution = r(1-p)/p.      return dist.successes() * (1 - dist.success_fraction() ) / dist.success_fraction();    } // mean    //template <class RealType, class Policy>    //inline RealType median(const negative_binomial_distribution<RealType, Policy>& dist)    //{ // Median of negative_binomial_distribution is not defined.    //  return policies::raise_domain_error<RealType>(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits<RealType>::quiet_NaN());    //} // median    // Now implemented via quantile(half) in derived accessors.    template <class RealType, class Policy>    inline RealType mode(const negative_binomial_distribution<RealType, Policy>& dist)    { // Mode of Negative Binomial distribution = floor[(r-1) * (1 - p)/p]      BOOST_MATH_STD_USING // ADL of std functions.      return floor((dist.successes() -1) * (1 - dist.success_fraction()) / dist.success_fraction());    } // mode    template <class RealType, class Policy>    inline RealType skewness(const negative_binomial_distribution<RealType, Policy>& dist)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?