1 /////////////////////////////////////////////////////////////////////////////// 2 // weighted_tail_variate_means.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 8 #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 9 #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 10 11 #include <numeric> 12 #include <vector> 13 #include <limits> 14 #include <functional> 15 #include <sstream> 16 #include <stdexcept> 17 #include <boost/throw_exception.hpp> 18 #include <boost/parameter/keyword.hpp> 19 #include <boost/mpl/placeholders.hpp> 20 #include <boost/type_traits/is_same.hpp> 21 #include <boost/accumulators/numeric/functional.hpp> 22 #include <boost/accumulators/framework/accumulator_base.hpp> 23 #include <boost/accumulators/framework/extractor.hpp> 24 #include <boost/accumulators/framework/parameters/sample.hpp> 25 #include <boost/accumulators/statistics_fwd.hpp> 26 #include <boost/accumulators/statistics/tail.hpp> 27 #include <boost/accumulators/statistics/tail_variate.hpp> 28 #include <boost/accumulators/statistics/tail_variate_means.hpp> 29 #include <boost/accumulators/statistics/weighted_tail_mean.hpp> 30 #include <boost/accumulators/statistics/parameters/quantile_probability.hpp> 31 32 #ifdef _MSC_VER 33 # pragma warning(push) 34 # pragma warning(disable: 4127) // conditional expression is constant 35 #endif 36 37 namespace boost 38 { 39 // for _BinaryOperatrion2 in std::inner_product below 40 // multiplies two values and promotes the result to double 41 namespace numeric { namespace functional 42 { 43 /////////////////////////////////////////////////////////////////////////////// 44 // numeric::functional::multiply_and_promote_to_double 45 template<typename T, typename U> 46 struct multiply_and_promote_to_double 47 : multiplies<T, double const> 48 { 49 }; 50 }} 51 } 52 53 namespace boost { namespace accumulators 54 { 55 56 namespace impl 57 { 58 /** 59 @brief Estimation of the absolute and relative weighted tail variate means (for both left and right tails) 60 61 For all \f$j\f$-th variates associated to the 62 63 \f[ 64 \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\} 65 \f] 66 67 smallest samples (left tail) or the weighted mean of the 68 69 \f[ 70 n + 1 - \rho = n + 1 - \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\} 71 \f] 72 73 largest samples (right tail), the absolute weighted tail means \f$\widehat{ATM}_{n,\alpha}(X, j)\f$ 74 are computed and returned as an iterator range. Alternatively, the relative weighted tail means 75 \f$\widehat{RTM}_{n,\alpha}(X, j)\f$ are returned, which are the absolute weighted tail means 76 normalized with the weighted (non-coherent) sample tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$. 77 78 \f[ 79 \widehat{ATM}_{n,\alpha}^{\mathrm{right}}(X, j) = 80 \frac{1}{\sum_{i=\rho}^n w_i} 81 \sum_{i=\rho}^n w_i \xi_{j,i} 82 \f] 83 84 \f[ 85 \widehat{ATM}_{n,\alpha}^{\mathrm{left}}(X, j) = 86 \frac{1}{\sum_{i=1}^{\lambda}} 87 \sum_{i=1}^{\lambda} w_i \xi_{j,i} 88 \f] 89 90 \f[ 91 \widehat{RTM}_{n,\alpha}^{\mathrm{right}}(X, j) = 92 \frac{\sum_{i=\rho}^n w_i \xi_{j,i}} 93 {\sum_{i=\rho}^n w_i \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X)} 94 \f] 95 96 \f[ 97 \widehat{RTM}_{n,\alpha}^{\mathrm{left}}(X, j) = 98 \frac{\sum_{i=1}^{\lambda} w_i \xi_{j,i}} 99 {\sum_{i=1}^{\lambda} w_i \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X)} 100 \f] 101 */ 102 103 /////////////////////////////////////////////////////////////////////////////// 104 // weighted_tail_variate_means_impl 105 // by default: absolute weighted_tail_variate_means 106 template<typename Sample, typename Weight, typename Impl, typename LeftRight, typename VariateType> 107 struct weighted_tail_variate_means_impl 108 : accumulator_base 109 { 110 typedef typename numeric::functional::fdiv<Weight, Weight>::result_type float_type; 111 typedef typename numeric::functional::fdiv<typename numeric::functional::multiplies<VariateType, Weight>::result_type, Weight>::result_type array_type; 112 // for boost::result_of 113 typedef iterator_range<typename array_type::iterator> result_type; 114 weighted_tail_variate_means_implboost::accumulators::impl::weighted_tail_variate_means_impl115 weighted_tail_variate_means_impl(dont_care) {} 116 117 template<typename Args> resultboost::accumulators::impl::weighted_tail_variate_means_impl118 result_type result(Args const &args) const 119 { 120 float_type threshold = sum_of_weights(args) 121 * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ); 122 123 std::size_t n = 0; 124 Weight sum = Weight(0); 125 126 while (sum < threshold) 127 { 128 if (n < static_cast<std::size_t>(tail_weights(args).size())) 129 { 130 sum += *(tail_weights(args).begin() + n); 131 n++; 132 } 133 else 134 { 135 if (std::numeric_limits<float_type>::has_quiet_NaN) 136 { 137 std::fill( 138 this->tail_means_.begin() 139 , this->tail_means_.end() 140 , std::numeric_limits<float_type>::quiet_NaN() 141 ); 142 } 143 else 144 { 145 std::ostringstream msg; 146 msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; 147 boost::throw_exception(std::runtime_error(msg.str())); 148 } 149 } 150 } 151 152 std::size_t num_variates = tail_variate(args).begin()->size(); 153 154 this->tail_means_.clear(); 155 this->tail_means_.resize(num_variates, Sample(0)); 156 157 this->tail_means_ = std::inner_product( 158 tail_variate(args).begin() 159 , tail_variate(args).begin() + n 160 , tail_weights(args).begin() 161 , this->tail_means_ 162 , numeric::functional::plus<array_type const, array_type const>() 163 , numeric::functional::multiply_and_promote_to_double<VariateType const, Weight const>() 164 ); 165 166 float_type factor = sum * ( (is_same<Impl, relative>::value) ? non_coherent_weighted_tail_mean(args) : 1. ); 167 168 std::transform( 169 this->tail_means_.begin() 170 , this->tail_means_.end() 171 , this->tail_means_.begin() 172 #ifdef BOOST_NO_CXX98_BINDERS 173 , std::bind(numeric::functional::divides<typename array_type::value_type const, float_type const>(), std::placeholders::_1, factor) 174 #else 175 , std::bind2nd(numeric::functional::divides<typename array_type::value_type const, float_type const>(), factor) 176 #endif 177 ); 178 179 return make_iterator_range(this->tail_means_); 180 } 181 182 // make this accumulator serializeable 183 template<class Archive> serializeboost::accumulators::impl::weighted_tail_variate_means_impl184 void serialize(Archive & ar, const unsigned int file_version) 185 { 186 ar & tail_means_; 187 } 188 189 private: 190 191 mutable array_type tail_means_; 192 193 }; 194 195 } // namespace impl 196 197 /////////////////////////////////////////////////////////////////////////////// 198 // tag::absolute_weighted_tail_variate_means 199 // tag::relative_weighted_tail_variate_means 200 // 201 namespace tag 202 { 203 template<typename LeftRight, typename VariateType, typename VariateTag> 204 struct absolute_weighted_tail_variate_means 205 : depends_on<non_coherent_weighted_tail_mean<LeftRight>, tail_variate<VariateType, VariateTag, LeftRight>, tail_weights<LeftRight> > 206 { 207 typedef accumulators::impl::weighted_tail_variate_means_impl<mpl::_1, mpl::_2, absolute, LeftRight, VariateType> impl; 208 }; 209 template<typename LeftRight, typename VariateType, typename VariateTag> 210 struct relative_weighted_tail_variate_means 211 : depends_on<non_coherent_weighted_tail_mean<LeftRight>, tail_variate<VariateType, VariateTag, LeftRight>, tail_weights<LeftRight> > 212 { 213 typedef accumulators::impl::weighted_tail_variate_means_impl<mpl::_1, mpl::_2, relative, LeftRight, VariateType> impl; 214 }; 215 } 216 217 /////////////////////////////////////////////////////////////////////////////// 218 // extract::weighted_tail_variate_means 219 // extract::relative_weighted_tail_variate_means 220 // 221 namespace extract 222 { 223 extractor<tag::abstract_absolute_tail_variate_means> const weighted_tail_variate_means = {}; 224 extractor<tag::abstract_relative_tail_variate_means> const relative_weighted_tail_variate_means = {}; 225 226 BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_tail_variate_means) 227 BOOST_ACCUMULATORS_IGNORE_GLOBAL(relative_weighted_tail_variate_means) 228 } 229 230 using extract::weighted_tail_variate_means; 231 using extract::relative_weighted_tail_variate_means; 232 233 // weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(absolute) -> absolute_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> 234 template<typename LeftRight, typename VariateType, typename VariateTag> 235 struct as_feature<tag::weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(absolute)> 236 { 237 typedef tag::absolute_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> type; 238 }; 239 240 // weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(relative) -> relative_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> 241 template<typename LeftRight, typename VariateType, typename VariateTag> 242 struct as_feature<tag::weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(relative)> 243 { 244 typedef tag::relative_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> type; 245 }; 246 247 }} // namespace boost::accumulators 248 249 #ifdef _MSC_VER 250 # pragma warning(pop) 251 #endif 252 253 #endif 254