File indexing completed on 2025-01-18 09:28:22
0001
0002
0003
0004
0005
0006
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)
0035 #endif
0036
0037 namespace boost { namespace accumulators
0038 {
0039
0040 namespace impl
0041 {
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
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
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
0113
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_;
0127 mutable float_type mu_;
0128 mutable float_type sigma2_;
0129 mutable float_type w_sum_;
0130 float_type threshold_;
0131 mutable result_type fit_parameters_;
0132 mutable bool is_dirty_;
0133 };
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
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
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_;
0237 mutable float_type mu_;
0238 mutable float_type sigma2_;
0239 mutable float_type threshold_probability_;
0240 mutable result_type fit_parameters_;
0241 mutable bool is_dirty_;
0242 };
0243
0244 }
0245
0246
0247
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
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
0266 typedef accumulators::impl::weighted_peaks_over_threshold_prob_impl<mpl::_1, mpl::_2, LeftRight> impl;
0267 };
0268 }
0269
0270
0271
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
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
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 }}
0297
0298 #ifdef _MSC_VER
0299 # pragma warning(pop)
0300 #endif
0301
0302 #endif