📄 triangular.hpp
字号:
// Copyright John Maddock 2006, 2007.// Copyright Paul A. Bristow 2006, 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)#ifndef BOOST_STATS_TRIANGULAR_HPP#define BOOST_STATS_TRIANGULAR_HPP// http://mathworld.wolfram.com/TriangularDistribution.html// http://en.wikipedia.org/wiki/Triangular_distribution#include <boost/math/distributions/fwd.hpp>#include <boost/math/special_functions/expm1.hpp>#include <boost/math/distributions/detail/common_error_handling.hpp>#include <boost/math/distributions/complement.hpp>#include <boost/math/constants/constants.hpp>#include <utility>namespace boost{ namespace math{ namespace detail { template <class RealType, class Policy> inline bool check_triangular_lower( const char* function, RealType lower, RealType* result, const Policy& pol) { if((boost::math::isfinite)(lower)) { // Any finite value is OK. return true; } else { // Not finite: infinity or NaN. *result = policies::raise_domain_error<RealType>( function, "Lower parameter is %1%, but must be finite!", lower, pol); return false; } } // bool check_triangular_lower( template <class RealType, class Policy> inline bool check_triangular_mode( const char* function, RealType mode, RealType* result, const Policy& pol) { if((boost::math::isfinite)(mode)) { // any finite value is OK. return true; } else { // Not finite: infinity or NaN. *result = policies::raise_domain_error<RealType>( function, "Mode parameter is %1%, but must be finite!", mode, pol); return false; } } // bool check_triangular_mode( template <class RealType, class Policy> inline bool check_triangular_upper( const char* function, RealType upper, RealType* result, const Policy& pol) { if((boost::math::isfinite)(upper)) { // any finite value is OK. return true; } else { // Not finite: infinity or NaN. *result = policies::raise_domain_error<RealType>( function, "Upper parameter is %1%, but must be finite!", upper, pol); return false; } } // bool check_triangular_upper( template <class RealType, class Policy> inline bool check_triangular_x( const char* function, RealType const& x, RealType* result, const Policy& pol) { if((boost::math::isfinite)(x)) { // Any finite value is OK return true; } else { // Not finite: infinity or NaN. *result = policies::raise_domain_error<RealType>( function, "x parameter is %1%, but must be finite!", x, pol); return false; } } // bool check_triangular_x template <class RealType, class Policy> inline bool check_triangular( const char* function, RealType lower, RealType mode, RealType upper, RealType* result, const Policy& pol) { if ((check_triangular_lower(function, lower, result, pol) == false) || (check_triangular_mode(function, mode, result, pol) == false) || (check_triangular_upper(function, upper, result, pol) == false)) { // Some parameter not finite. return false; } else if (lower >= upper) // lower == upper NOT useful. { // lower >= upper. *result = policies::raise_domain_error<RealType>( function, "lower parameter is %1%, but must be less than upper!", lower, pol); return false; } else { // Check lower <= mode <= upper. if (mode < lower) { *result = policies::raise_domain_error<RealType>( function, "mode parameter is %1%, but must be >= than lower!", lower, pol); return false; } if (mode > upper) { *result = policies::raise_domain_error<RealType>( function, "mode parameter is %1%, but must be <= than upper!", upper, pol); return false; } return true; // All OK. } } // bool check_triangular } // namespace detail template <class RealType = double, class Policy = policies::policy<> > class triangular_distribution { public: typedef RealType value_type; typedef Policy policy_type; triangular_distribution(RealType lower = -1, RealType mode = 0, RealType upper = 1) : m_lower(lower), m_mode(mode), m_upper(upper) // Constructor. { // Evans says 'standard triangular' is lower 0, mode 1/2, upper 1, // has median sqrt(c/2) for c <=1/2 and 1 - sqrt(1-c)/2 for c >= 1/2 // But this -1, 0, 1 is more useful in most applications to approximate normal distribution, // where the central value is the most likely and deviations either side equally likely. RealType result; detail::check_triangular("boost::math::triangular_distribution<%1%>::triangular_distribution",lower, mode, upper, &result, Policy()); } // Accessor functions. RealType lower()const { return m_lower; } RealType mode()const { return m_mode; } RealType upper()const { return m_upper; } private: // Data members: RealType m_lower; // distribution lower aka a RealType m_mode; // distribution mode aka c RealType m_upper; // distribution upper aka b }; // class triangular_distribution typedef triangular_distribution<double> triangular; template <class RealType, class Policy> inline const std::pair<RealType, RealType> range(const triangular_distribution<RealType, Policy>& /* dist */) { // Range of permissible values for random variable x. using boost::math::tools::max_value; return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); } template <class RealType, class Policy> inline const std::pair<RealType, RealType> support(const triangular_distribution<RealType, Policy>& dist) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. return std::pair<RealType, RealType>(dist.lower(), dist.upper()); } template <class RealType, class Policy> RealType pdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x) { static const char* function = "boost::math::pdf(const triangular_distribution<%1%>&, %1%)"; RealType lower = dist.lower(); RealType mode = dist.mode(); RealType upper = dist.upper(); RealType result; // of checks. if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy())) { return result; } if(false == detail::check_triangular_x(function, x, &result, Policy())) { return result; } if((x < lower) || (x > upper)) { return 0; } if (x == lower) { // (mode - lower) == 0 which would lead to divide by zero! return (mode == lower) ? 2 / (upper - lower) : 0; } else if (x == upper) { return (mode == upper) ? 2 / (upper - lower) : 0; } else if (x <= mode) { return 2 * (x - lower) / ((upper - lower) * (mode - lower)); } else { // (x > mode) return 2 * (upper - x) / ((upper - lower) * (upper - mode)); } } // RealType pdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x) template <class RealType, class Policy> inline RealType cdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x) { static const char* function = "boost::math::cdf(const triangular_distribution<%1%>&, %1%)"; RealType lower = dist.lower(); RealType mode = dist.mode(); RealType upper = dist.upper(); RealType result; // of checks. if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy())) { return result; } if(false == detail::check_triangular_x(function, x, &result, Policy())) { return result; } if((x <= lower)) { return 0; } if (x >= upper) { return 1; } // else lower < x < upper if (x <= mode) { return ((x - lower) * (x - lower)) / ((upper - lower) * (mode - lower)); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -