Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:22

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // weighted_peaks_over_threshold.hpp
0003 //
0004 //  Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006
0009 #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006
0010 
0011 #include <vector>
0012 #include <limits>
0013 #include <numeric>
0014 #include <functional>
0015 #include <boost/throw_exception.hpp>
0016 #include <boost/range.hpp>
0017 #include <boost/mpl/if.hpp>
0018 #include <boost/mpl/placeholders.hpp>
0019 #include <boost/parameter/keyword.hpp>
0020 #include <boost/tuple/tuple.hpp>
0021 #include <boost/accumulators/numeric/functional.hpp>
0022 #include <boost/accumulators/framework/accumulator_base.hpp>
0023 #include <boost/accumulators/framework/extractor.hpp>
0024 #include <boost/accumulators/framework/parameters/sample.hpp>
0025 #include <boost/accumulators/framework/depends_on.hpp>
0026 #include <boost/accumulators/statistics_fwd.hpp>
0027 #include <boost/accumulators/statistics/parameters/quantile_probability.hpp>
0028 #include <boost/accumulators/statistics/peaks_over_threshold.hpp> // for named parameters pot_threshold_value and pot_threshold_probability
0029 #include <boost/accumulators/statistics/sum.hpp>
0030 #include <boost/accumulators/statistics/tail_variate.hpp>
0031 
0032 #ifdef _MSC_VER
0033 # pragma warning(push)
0034 # pragma warning(disable: 4127) // conditional expression is constant
0035 #endif
0036 
0037 namespace boost { namespace accumulators
0038 {
0039 
0040 namespace impl
0041 {
0042 
0043     ///////////////////////////////////////////////////////////////////////////////
0044     // weighted_peaks_over_threshold_impl
0045     //  works with an explicit threshold value and does not depend on order statistics of weighted samples
0046     /**
0047         @brief Weighted Peaks over Threshold Method for Weighted Quantile and Weighted Tail Mean Estimation
0048 
0049         @sa peaks_over_threshold_impl
0050 
0051         @param quantile_probability
0052         @param pot_threshold_value
0053     */
0054     template<typename Sample, typename Weight, typename LeftRight>
0055     struct weighted_peaks_over_threshold_impl
0056       : accumulator_base
0057     {
0058         typedef typename numeric::functional::multiplies<Weight, Sample>::result_type weighted_sample;
0059         typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type;
0060         // for boost::result_of
0061         typedef boost::tuple<float_type, float_type, float_type> result_type;
0062 
0063         template<typename Args>
0064         weighted_peaks_over_threshold_impl(Args const &args)
0065           : sign_((is_same<LeftRight, left>::value) ? -1 : 1)
0066           , mu_(sign_ * numeric::fdiv(args[sample | Sample()], (std::size_t)1))
0067           , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1))
0068           , w_sum_(numeric::fdiv(args[weight | Weight()], (std::size_t)1))
0069           , threshold_(sign_ * args[pot_threshold_value])
0070           , fit_parameters_(boost::make_tuple(0., 0., 0.))
0071           , is_dirty_(true)
0072         {
0073         }
0074 
0075         template<typename Args>
0076         void operator ()(Args const &args)
0077         {
0078             this->is_dirty_ = true;
0079 
0080             if (this->sign_ * args[sample] > this->threshold_)
0081             {
0082                 this->mu_ += args[weight] * args[sample];
0083                 this->sigma2_ += args[weight] * args[sample] * args[sample];
0084                 this->w_sum_ += args[weight];
0085             }
0086         }
0087 
0088         template<typename Args>
0089         result_type result(Args const &args) const
0090         {
0091             if (this->is_dirty_)
0092             {
0093                 this->is_dirty_ = false;
0094 
0095                 this->mu_ = this->sign_ * numeric::fdiv(this->mu_, this->w_sum_);
0096                 this->sigma2_ = numeric::fdiv(this->sigma2_, this->w_sum_);
0097                 this->sigma2_ -= this->mu_ * this->mu_;
0098 
0099                 float_type threshold_probability = numeric::fdiv(sum_of_weights(args) - this->w_sum_, sum_of_weights(args));
0100 
0101                 float_type tmp = numeric::fdiv(( this->mu_ - this->threshold_ )*( this->mu_ - this->threshold_ ), this->sigma2_);
0102                 float_type xi_hat = 0.5 * ( 1. - tmp );
0103                 float_type beta_hat = 0.5 * ( this->mu_ - this->threshold_ ) * ( 1. + tmp );
0104                 float_type beta_bar = beta_hat * std::pow(1. - threshold_probability, xi_hat);
0105                 float_type u_bar = this->threshold_ - beta_bar * ( std::pow(1. - threshold_probability, -xi_hat) - 1.)/xi_hat;
0106                 this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat);
0107             }
0108 
0109             return this->fit_parameters_;
0110         }
0111 
0112         // make this accumulator serializeable
0113         // TODO: do we need to split to load/save and verify that threshold did not change?
0114         template<class Archive>
0115         void serialize(Archive & ar, const unsigned int file_version)
0116         {
0117             ar & sign_;
0118             ar & mu_;
0119             ar & sigma2_;
0120             ar & threshold_;
0121             ar & fit_parameters_;
0122             ar & is_dirty_;
0123         }
0124 
0125     private:
0126         short sign_;                         // for left tail fitting, mirror the extreme values
0127         mutable float_type mu_;              // mean of samples above threshold
0128         mutable float_type sigma2_;          // variance of samples above threshold
0129         mutable float_type w_sum_;           // sum of weights of samples above threshold
0130         float_type threshold_;
0131         mutable result_type fit_parameters_; // boost::tuple that stores fit parameters
0132         mutable bool is_dirty_;
0133     };
0134 
0135     ///////////////////////////////////////////////////////////////////////////////
0136     // weighted_peaks_over_threshold_prob_impl
0137     //  determines threshold from a given threshold probability using order statistics
0138     /**
0139         @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation
0140 
0141         @sa weighted_peaks_over_threshold_impl
0142 
0143         @param quantile_probability
0144         @param pot_threshold_probability
0145     */
0146     template<typename Sample, typename Weight, typename LeftRight>
0147     struct weighted_peaks_over_threshold_prob_impl
0148       : accumulator_base
0149     {
0150         typedef typename numeric::functional::multiplies<Weight, Sample>::result_type weighted_sample;
0151         typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type;
0152         // for boost::result_of
0153         typedef boost::tuple<float_type, float_type, float_type> result_type;
0154 
0155         template<typename Args>
0156         weighted_peaks_over_threshold_prob_impl(Args const &args)
0157           : sign_((is_same<LeftRight, left>::value) ? -1 : 1)
0158           , mu_(sign_ * numeric::fdiv(args[sample | Sample()], (std::size_t)1))
0159           , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1))
0160           , threshold_probability_(args[pot_threshold_probability])
0161           , fit_parameters_(boost::make_tuple(0., 0., 0.))
0162           , is_dirty_(true)
0163         {
0164         }
0165 
0166         void operator ()(dont_care)
0167         {
0168             this->is_dirty_ = true;
0169         }
0170 
0171         template<typename Args>
0172         result_type result(Args const &args) const
0173         {
0174             if (this->is_dirty_)
0175             {
0176                 this->is_dirty_ = false;
0177 
0178                 float_type threshold = sum_of_weights(args)
0179                              * ( ( is_same<LeftRight, left>::value ) ? this->threshold_probability_ : 1. - this->threshold_probability_ );
0180 
0181                 std::size_t n = 0;
0182                 Weight sum = Weight(0);
0183 
0184                 while (sum < threshold)
0185                 {
0186                     if (n < static_cast<std::size_t>(tail_weights(args).size()))
0187                     {
0188                         mu_ += *(tail_weights(args).begin() + n) * *(tail(args).begin() + n);
0189                         sigma2_ += *(tail_weights(args).begin() + n) * *(tail(args).begin() + n) * (*(tail(args).begin() + n));
0190                         sum += *(tail_weights(args).begin() + n);
0191                         n++;
0192                     }
0193                     else
0194                     {
0195                         if (std::numeric_limits<float_type>::has_quiet_NaN)
0196                         {
0197                             return boost::make_tuple(
0198                                 std::numeric_limits<float_type>::quiet_NaN()
0199                               , std::numeric_limits<float_type>::quiet_NaN()
0200                               , std::numeric_limits<float_type>::quiet_NaN()
0201                             );
0202                         }
0203                         else
0204                         {
0205                             std::ostringstream msg;
0206                             msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")";
0207                             boost::throw_exception(std::runtime_error(msg.str()));
0208                             return boost::make_tuple(Sample(0), Sample(0), Sample(0));
0209                         }
0210                     }
0211                 }
0212 
0213                 float_type u = *(tail(args).begin() + n - 1) * this->sign_;
0214 
0215 
0216                 this->mu_ = this->sign_ * numeric::fdiv(this->mu_, sum);
0217                 this->sigma2_ = numeric::fdiv(this->sigma2_, sum);
0218                 this->sigma2_ -= this->mu_ * this->mu_;
0219 
0220                 if (is_same<LeftRight, left>::value)
0221                     this->threshold_probability_ = 1. - this->threshold_probability_;
0222 
0223                 float_type tmp = numeric::fdiv(( this->mu_ - u )*( this->mu_ - u ), this->sigma2_);
0224                 float_type xi_hat = 0.5 * ( 1. - tmp );
0225                 float_type beta_hat = 0.5 * ( this->mu_ - u ) * ( 1. + tmp );
0226                 float_type beta_bar = beta_hat * std::pow(1. - threshold_probability_, xi_hat);
0227                 float_type u_bar = u - beta_bar * ( std::pow(1. - threshold_probability_, -xi_hat) - 1.)/xi_hat;
0228                 this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat);
0229 
0230             }
0231 
0232             return this->fit_parameters_;
0233         }
0234 
0235     private:
0236         short sign_;                                // for left tail fitting, mirror the extreme values
0237         mutable float_type mu_;                     // mean of samples above threshold u
0238         mutable float_type sigma2_;                 // variance of samples above threshold u
0239         mutable float_type threshold_probability_;
0240         mutable result_type fit_parameters_;        // boost::tuple that stores fit parameters
0241         mutable bool is_dirty_;
0242     };
0243 
0244 } // namespace impl
0245 
0246 ///////////////////////////////////////////////////////////////////////////////
0247 // tag::weighted_peaks_over_threshold
0248 //
0249 namespace tag
0250 {
0251     template<typename LeftRight>
0252     struct weighted_peaks_over_threshold
0253       : depends_on<sum_of_weights>
0254       , pot_threshold_value
0255     {
0256         /// INTERNAL ONLY
0257         typedef accumulators::impl::weighted_peaks_over_threshold_impl<mpl::_1, mpl::_2, LeftRight> impl;
0258     };
0259 
0260     template<typename LeftRight>
0261     struct weighted_peaks_over_threshold_prob
0262       : depends_on<sum_of_weights, tail_weights<LeftRight> >
0263       , pot_threshold_probability
0264     {
0265         /// INTERNAL ONLY
0266         typedef accumulators::impl::weighted_peaks_over_threshold_prob_impl<mpl::_1, mpl::_2, LeftRight> impl;
0267     };
0268 }
0269 
0270 ///////////////////////////////////////////////////////////////////////////////
0271 // extract::weighted_peaks_over_threshold
0272 //
0273 namespace extract
0274 {
0275     extractor<tag::abstract_peaks_over_threshold> const weighted_peaks_over_threshold = {};
0276 
0277     BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_peaks_over_threshold)
0278 }
0279 
0280 using extract::weighted_peaks_over_threshold;
0281 
0282 // weighted_peaks_over_threshold<LeftRight>(with_threshold_value) -> weighted_peaks_over_threshold<LeftRight>
0283 template<typename LeftRight>
0284 struct as_feature<tag::weighted_peaks_over_threshold<LeftRight>(with_threshold_value)>
0285 {
0286     typedef tag::weighted_peaks_over_threshold<LeftRight> type;
0287 };
0288 
0289 // weighted_peaks_over_threshold<LeftRight>(with_threshold_probability) -> weighted_peaks_over_threshold_prob<LeftRight>
0290 template<typename LeftRight>
0291 struct as_feature<tag::weighted_peaks_over_threshold<LeftRight>(with_threshold_probability)>
0292 {
0293     typedef tag::weighted_peaks_over_threshold_prob<LeftRight> type;
0294 };
0295 
0296 }} // namespace boost::accumulators
0297 
0298 #ifdef _MSC_VER
0299 # pragma warning(pop)
0300 #endif
0301 
0302 #endif