weighted_tail_quantile.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // weighted_tail_quantile.hpp
  3. //
  4. // Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_QUANTILE_HPP_DE_01_01_2006
  8. #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_QUANTILE_HPP_DE_01_01_2006
  9. #include <vector>
  10. #include <limits>
  11. #include <functional>
  12. #include <sstream>
  13. #include <stdexcept>
  14. #include <boost/throw_exception.hpp>
  15. #include <boost/parameter/keyword.hpp>
  16. #include <boost/mpl/placeholders.hpp>
  17. #include <boost/mpl/if.hpp>
  18. #include <boost/type_traits/is_same.hpp>
  19. #include <boost/accumulators/numeric/functional.hpp>
  20. #include <boost/accumulators/framework/depends_on.hpp>
  21. #include <boost/accumulators/framework/accumulator_base.hpp>
  22. #include <boost/accumulators/framework/extractor.hpp>
  23. #include <boost/accumulators/framework/parameters/sample.hpp>
  24. #include <boost/accumulators/statistics_fwd.hpp>
  25. #include <boost/accumulators/statistics/tail.hpp>
  26. #include <boost/accumulators/statistics/tail_quantile.hpp>
  27. #include <boost/accumulators/statistics/parameters/quantile_probability.hpp>
  28. #ifdef _MSC_VER
  29. # pragma warning(push)
  30. # pragma warning(disable: 4127) // conditional expression is constant
  31. #endif
  32. namespace boost { namespace accumulators
  33. {
  34. namespace impl
  35. {
  36. ///////////////////////////////////////////////////////////////////////////////
  37. // weighted_tail_quantile_impl
  38. // Tail quantile estimation based on order statistics of weighted samples
  39. /**
  40. @brief Tail quantile estimation based on order statistics of weighted samples (for both left and right tails)
  41. An estimator \f$\hat{q}\f$ of tail quantiles with level \f$\alpha\f$ based on order statistics
  42. \f$X_{1:n} \leq X_{2:n} \leq\dots\leq X_{n:n}\f$ of weighted samples are given by \f$X_{\lambda:n}\f$ (left tail)
  43. and \f$X_{\rho:n}\f$ (right tail), where
  44. \f[
  45. \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\}
  46. \f]
  47. and
  48. \f[
  49. \rho = \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\},
  50. \f]
  51. \f$n\f$ being the number of samples and \f$\bar{w}_n\f$ the sum of all weights.
  52. @param quantile_probability
  53. */
  54. template<typename Sample, typename Weight, typename LeftRight>
  55. struct weighted_tail_quantile_impl
  56. : accumulator_base
  57. {
  58. typedef typename numeric::functional::fdiv<Weight, std::size_t>::result_type float_type;
  59. // for boost::result_of
  60. typedef Sample result_type;
  61. weighted_tail_quantile_impl(dont_care) {}
  62. template<typename Args>
  63. result_type result(Args const &args) const
  64. {
  65. float_type threshold = sum_of_weights(args)
  66. * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] );
  67. std::size_t n = 0;
  68. Weight sum = Weight(0);
  69. while (sum < threshold)
  70. {
  71. if (n < static_cast<std::size_t>(tail_weights(args).size()))
  72. {
  73. sum += *(tail_weights(args).begin() + n);
  74. n++;
  75. }
  76. else
  77. {
  78. if (std::numeric_limits<result_type>::has_quiet_NaN)
  79. {
  80. return std::numeric_limits<result_type>::quiet_NaN();
  81. }
  82. else
  83. {
  84. std::ostringstream msg;
  85. msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")";
  86. boost::throw_exception(std::runtime_error(msg.str()));
  87. return Sample(0);
  88. }
  89. }
  90. }
  91. // Note that the cached samples of the left are sorted in ascending order,
  92. // whereas the samples of the right tail are sorted in descending order
  93. return *(boost::begin(tail(args)) + n - 1);
  94. }
  95. };
  96. } // namespace impl
  97. ///////////////////////////////////////////////////////////////////////////////
  98. // tag::weighted_tail_quantile<>
  99. //
  100. namespace tag
  101. {
  102. template<typename LeftRight>
  103. struct weighted_tail_quantile
  104. : depends_on<sum_of_weights, tail_weights<LeftRight> >
  105. {
  106. /// INTERNAL ONLY
  107. typedef accumulators::impl::weighted_tail_quantile_impl<mpl::_1, mpl::_2, LeftRight> impl;
  108. };
  109. }
  110. ///////////////////////////////////////////////////////////////////////////////
  111. // extract::weighted_tail_quantile
  112. //
  113. namespace extract
  114. {
  115. extractor<tag::quantile> const weighted_tail_quantile = {};
  116. BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_tail_quantile)
  117. }
  118. using extract::weighted_tail_quantile;
  119. }} // namespace boost::accumulators
  120. #ifdef _MSC_VER
  121. # pragma warning(pop)
  122. #endif
  123. #endif