1 ///////////////////////////////////////////////////////////////////////////////
2 // pot_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 
8 #ifndef BOOST_ACCUMULATORS_STATISTICS_POT_QUANTILE_HPP_DE_01_01_2006
9 #define BOOST_ACCUMULATORS_STATISTICS_POT_QUANTILE_HPP_DE_01_01_2006
10 
11 #include <vector>
12 #include <limits>
13 #include <numeric>
14 #include <functional>
15 #include <boost/parameter/keyword.hpp>
16 #include <boost/tuple/tuple.hpp>
17 #include <boost/mpl/if.hpp>
18 #include <boost/type_traits/is_same.hpp>
19 #include <boost/mpl/placeholders.hpp>
20 #include <boost/accumulators/framework/accumulator_base.hpp>
21 #include <boost/accumulators/framework/extractor.hpp>
22 #include <boost/accumulators/numeric/functional.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/peaks_over_threshold.hpp>
27 #include <boost/accumulators/statistics/weighted_peaks_over_threshold.hpp>
28 
29 namespace boost { namespace accumulators
30 {
31 
32 namespace impl
33 {
34     ///////////////////////////////////////////////////////////////////////////////
35     // pot_quantile_impl
36     //
37     /**
38         @brief Quantile Estimation based on Peaks over Threshold Method (for both left and right tails)
39 
40         Computes an estimate
41         \f[
42             \hat{q}_{\alpha} = \bar{u} + \frac{\bar{\beta}}{\xi}\left[(1-\alpha)^{-\xi}-1\right]
43         \f]
44         for a right or left extreme quantile, \f$\bar[u]\f$, \f$\bar{\beta}\f$ and \f$\xi\f$ being the parameters of the
45         generalized Pareto distribution that approximates the right tail of the distribution (or the mirrored left tail,
46         in case the left tail is used). In the latter case, the result is mirrored back, yielding the correct result.
47     */
48     template<typename Sample, typename Impl, typename LeftRight>
49     struct pot_quantile_impl
50       : accumulator_base
51     {
52         typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type;
53         // for boost::result_of
54         typedef float_type result_type;
55 
pot_quantile_implboost::accumulators::impl::pot_quantile_impl56         pot_quantile_impl(dont_care)
57           : sign_((is_same<LeftRight, left>::value) ? -1 : 1)
58         {
59         }
60 
61         template<typename Args>
resultboost::accumulators::impl::pot_quantile_impl62         result_type result(Args const &args) const
63         {
64             typedef
65                 typename mpl::if_<
66                     is_same<Impl, weighted>
67                   , tag::weighted_peaks_over_threshold<LeftRight>
68                   , tag::peaks_over_threshold<LeftRight>
69                 >::type
70             peaks_over_threshold_tag;
71 
72             extractor<peaks_over_threshold_tag> const some_peaks_over_threshold = {};
73 
74             float_type u_bar    = some_peaks_over_threshold(args).template get<0>();
75             float_type beta_bar = some_peaks_over_threshold(args).template get<1>();
76             float_type xi_hat   = some_peaks_over_threshold(args).template get<2>();
77 
78             return this->sign_ * (u_bar + beta_bar/xi_hat * ( std::pow(
79                     is_same<LeftRight, left>::value ? args[quantile_probability] : 1. - args[quantile_probability]
80                 , -xi_hat
81               ) - 1.));
82         }
83 
84         // make this accumulator serializeable
85         template<class Archive>
serializeboost::accumulators::impl::pot_quantile_impl86         void serialize(Archive & ar, const unsigned int file_version)
87         {
88             ar & sign_;
89         }
90 
91     private:
92         short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result
93     };
94 
95 } // namespace impl
96 
97 ///////////////////////////////////////////////////////////////////////////////
98 // tag::pot_quantile<>
99 // tag::pot_quantile_prob<>
100 // tag::weighted_pot_quantile<>
101 // tag::weighted_pot_quantile_prob<>
102 //
103 namespace tag
104 {
105     template<typename LeftRight>
106     struct pot_quantile
107       : depends_on<peaks_over_threshold<LeftRight> >
108     {
109         /// INTERNAL ONLY
110         ///
111         typedef accumulators::impl::pot_quantile_impl<mpl::_1, unweighted, LeftRight> impl;
112     };
113     template<typename LeftRight>
114     struct pot_quantile_prob
115       : depends_on<peaks_over_threshold_prob<LeftRight> >
116     {
117         /// INTERNAL ONLY
118         ///
119         typedef accumulators::impl::pot_quantile_impl<mpl::_1, unweighted, LeftRight> impl;
120     };
121     template<typename LeftRight>
122     struct weighted_pot_quantile
123       : depends_on<weighted_peaks_over_threshold<LeftRight> >
124     {
125         /// INTERNAL ONLY
126         ///
127         typedef accumulators::impl::pot_quantile_impl<mpl::_1, weighted, LeftRight> impl;
128     };
129     template<typename LeftRight>
130     struct weighted_pot_quantile_prob
131       : depends_on<weighted_peaks_over_threshold_prob<LeftRight> >
132     {
133         /// INTERNAL ONLY
134         ///
135         typedef accumulators::impl::pot_quantile_impl<mpl::_1, weighted, LeftRight> impl;
136     };
137 }
138 
139 // pot_quantile<LeftRight>(with_threshold_value) -> pot_quantile<LeftRight>
140 template<typename LeftRight>
141 struct as_feature<tag::pot_quantile<LeftRight>(with_threshold_value)>
142 {
143     typedef tag::pot_quantile<LeftRight> type;
144 };
145 
146 // pot_quantile<LeftRight>(with_threshold_probability) -> pot_quantile_prob<LeftRight>
147 template<typename LeftRight>
148 struct as_feature<tag::pot_quantile<LeftRight>(with_threshold_probability)>
149 {
150     typedef tag::pot_quantile_prob<LeftRight> type;
151 };
152 
153 // weighted_pot_quantile<LeftRight>(with_threshold_value) -> weighted_pot_quantile<LeftRight>
154 template<typename LeftRight>
155 struct as_feature<tag::weighted_pot_quantile<LeftRight>(with_threshold_value)>
156 {
157     typedef tag::weighted_pot_quantile<LeftRight> type;
158 };
159 
160 // weighted_pot_quantile<LeftRight>(with_threshold_probability) -> weighted_pot_quantile_prob<LeftRight>
161 template<typename LeftRight>
162 struct as_feature<tag::weighted_pot_quantile<LeftRight>(with_threshold_probability)>
163 {
164     typedef tag::weighted_pot_quantile_prob<LeftRight> type;
165 };
166 
167 // for the purposes of feature-based dependency resolution,
168 // pot_quantile<LeftRight> and pot_quantile_prob<LeftRight> provide
169 // the same feature as quantile
170 template<typename LeftRight>
171 struct feature_of<tag::pot_quantile<LeftRight> >
172   : feature_of<tag::quantile>
173 {
174 };
175 
176 template<typename LeftRight>
177 struct feature_of<tag::pot_quantile_prob<LeftRight> >
178   : feature_of<tag::quantile>
179 {
180 };
181 
182 // So that pot_quantile can be automatically substituted
183 // with weighted_pot_quantile when the weight parameter is non-void.
184 template<typename LeftRight>
185 struct as_weighted_feature<tag::pot_quantile<LeftRight> >
186 {
187     typedef tag::weighted_pot_quantile<LeftRight> type;
188 };
189 
190 template<typename LeftRight>
191 struct feature_of<tag::weighted_pot_quantile<LeftRight> >
192   : feature_of<tag::pot_quantile<LeftRight> >
193 {
194 };
195 
196 // So that pot_quantile_prob can be automatically substituted
197 // with weighted_pot_quantile_prob when the weight parameter is non-void.
198 template<typename LeftRight>
199 struct as_weighted_feature<tag::pot_quantile_prob<LeftRight> >
200 {
201     typedef tag::weighted_pot_quantile_prob<LeftRight> type;
202 };
203 
204 template<typename LeftRight>
205 struct feature_of<tag::weighted_pot_quantile_prob<LeftRight> >
206   : feature_of<tag::pot_quantile_prob<LeftRight> >
207 {
208 };
209 
210 }} // namespace boost::accumulators
211 
212 #endif
213