annotate DEPENDENCIES/generic/include/boost/accumulators/statistics/weighted_median.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 // weighted_median.hpp
Chris@16 3 //
Chris@16 4 // Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost
Chris@16 5 // Software License, Version 1.0. (See accompanying file
Chris@16 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7
Chris@16 8 #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEDIAN_HPP_EAN_28_10_2005
Chris@16 9 #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEDIAN_HPP_EAN_28_10_2005
Chris@16 10
Chris@16 11 #include <boost/mpl/placeholders.hpp>
Chris@16 12 #include <boost/range/iterator_range.hpp>
Chris@16 13 #include <boost/accumulators/framework/accumulator_base.hpp>
Chris@16 14 #include <boost/accumulators/framework/extractor.hpp>
Chris@16 15 #include <boost/accumulators/numeric/functional.hpp>
Chris@16 16 #include <boost/accumulators/framework/parameters/sample.hpp>
Chris@16 17 #include <boost/accumulators/framework/depends_on.hpp>
Chris@16 18 #include <boost/accumulators/statistics_fwd.hpp>
Chris@16 19 #include <boost/accumulators/statistics/count.hpp>
Chris@16 20 #include <boost/accumulators/statistics/median.hpp>
Chris@16 21 #include <boost/accumulators/statistics/weighted_p_square_quantile.hpp>
Chris@16 22 #include <boost/accumulators/statistics/weighted_density.hpp>
Chris@16 23 #include <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>
Chris@16 24
Chris@16 25 namespace boost { namespace accumulators
Chris@16 26 {
Chris@16 27
Chris@16 28 namespace impl
Chris@16 29 {
Chris@16 30 ///////////////////////////////////////////////////////////////////////////////
Chris@16 31 // weighted_median_impl
Chris@16 32 //
Chris@16 33 /**
Chris@16 34 @brief Median estimation for weighted samples based on the \f$P^2\f$ quantile estimator
Chris@16 35
Chris@16 36 The \f$P^2\f$ algorithm for weighted samples is invoked with a quantile probability of 0.5.
Chris@16 37 */
Chris@16 38 template<typename Sample>
Chris@16 39 struct weighted_median_impl
Chris@16 40 : accumulator_base
Chris@16 41 {
Chris@16 42 // for boost::result_of
Chris@16 43 typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type;
Chris@16 44
Chris@16 45 weighted_median_impl(dont_care) {}
Chris@16 46
Chris@16 47 template<typename Args>
Chris@16 48 result_type result(Args const &args) const
Chris@16 49 {
Chris@16 50 return weighted_p_square_quantile_for_median(args);
Chris@16 51 }
Chris@16 52 };
Chris@16 53
Chris@16 54 ///////////////////////////////////////////////////////////////////////////////
Chris@16 55 // with_density_weighted_median_impl
Chris@16 56 //
Chris@16 57 /**
Chris@16 58 @brief Median estimation for weighted samples based on the density estimator
Chris@16 59
Chris@16 60 The algorithm determines the bin in which the \f$0.5*cnt\f$-th sample lies, \f$cnt\f$ being
Chris@16 61 the total number of samples. It returns the approximate horizontal position of this sample,
Chris@16 62 based on a linear interpolation inside the bin.
Chris@16 63 */
Chris@16 64 template<typename Sample>
Chris@16 65 struct with_density_weighted_median_impl
Chris@16 66 : accumulator_base
Chris@16 67 {
Chris@16 68 typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type;
Chris@16 69 typedef std::vector<std::pair<float_type, float_type> > histogram_type;
Chris@16 70 typedef iterator_range<typename histogram_type::iterator> range_type;
Chris@16 71 // for boost::result_of
Chris@16 72 typedef float_type result_type;
Chris@16 73
Chris@16 74 template<typename Args>
Chris@16 75 with_density_weighted_median_impl(Args const &args)
Chris@16 76 : sum(numeric::fdiv(args[sample | Sample()], (std::size_t)1))
Chris@16 77 , is_dirty(true)
Chris@16 78 {
Chris@16 79 }
Chris@16 80
Chris@16 81 void operator ()(dont_care)
Chris@16 82 {
Chris@16 83 this->is_dirty = true;
Chris@16 84 }
Chris@16 85
Chris@16 86 template<typename Args>
Chris@16 87 result_type result(Args const &args) const
Chris@16 88 {
Chris@16 89 if (this->is_dirty)
Chris@16 90 {
Chris@16 91 this->is_dirty = false;
Chris@16 92
Chris@16 93 std::size_t cnt = count(args);
Chris@16 94 range_type histogram = weighted_density(args);
Chris@16 95 typename range_type::iterator it = histogram.begin();
Chris@16 96 while (this->sum < 0.5 * cnt)
Chris@16 97 {
Chris@16 98 this->sum += it->second * cnt;
Chris@16 99 ++it;
Chris@16 100 }
Chris@16 101 --it;
Chris@16 102 float_type over = numeric::fdiv(this->sum - 0.5 * cnt, it->second * cnt);
Chris@16 103 this->median = it->first * over + (it + 1)->first * ( 1. - over );
Chris@16 104 }
Chris@16 105
Chris@16 106 return this->median;
Chris@16 107 }
Chris@16 108
Chris@16 109 private:
Chris@16 110 mutable float_type sum;
Chris@16 111 mutable bool is_dirty;
Chris@16 112 mutable float_type median;
Chris@16 113 };
Chris@16 114
Chris@16 115 ///////////////////////////////////////////////////////////////////////////////
Chris@16 116 // with_p_square_cumulative_distribution_weighted_median_impl
Chris@16 117 //
Chris@16 118 /**
Chris@16 119 @brief Median estimation for weighted samples based on the \f$P^2\f$ cumulative distribution estimator
Chris@16 120
Chris@16 121 The algorithm determines the first (leftmost) bin with a height exceeding 0.5. It
Chris@16 122 returns the approximate horizontal position of where the cumulative distribution
Chris@16 123 equals 0.5, based on a linear interpolation inside the bin.
Chris@16 124 */
Chris@16 125 template<typename Sample, typename Weight>
Chris@16 126 struct with_p_square_cumulative_distribution_weighted_median_impl
Chris@16 127 : accumulator_base
Chris@16 128 {
Chris@16 129 typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample;
Chris@16 130 typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type;
Chris@16 131 typedef std::vector<std::pair<float_type, float_type> > histogram_type;
Chris@16 132 typedef iterator_range<typename histogram_type::iterator> range_type;
Chris@16 133 // for boost::result_of
Chris@16 134 typedef float_type result_type;
Chris@16 135
Chris@16 136 with_p_square_cumulative_distribution_weighted_median_impl(dont_care)
Chris@16 137 : is_dirty(true)
Chris@16 138 {
Chris@16 139 }
Chris@16 140
Chris@16 141 void operator ()(dont_care)
Chris@16 142 {
Chris@16 143 this->is_dirty = true;
Chris@16 144 }
Chris@16 145
Chris@16 146 template<typename Args>
Chris@16 147 result_type result(Args const &args) const
Chris@16 148 {
Chris@16 149 if (this->is_dirty)
Chris@16 150 {
Chris@16 151 this->is_dirty = false;
Chris@16 152
Chris@16 153 range_type histogram = weighted_p_square_cumulative_distribution(args);
Chris@16 154 typename range_type::iterator it = histogram.begin();
Chris@16 155 while (it->second < 0.5)
Chris@16 156 {
Chris@16 157 ++it;
Chris@16 158 }
Chris@16 159 float_type over = numeric::fdiv(it->second - 0.5, it->second - (it - 1)->second);
Chris@16 160 this->median = it->first * over + (it + 1)->first * ( 1. - over );
Chris@16 161 }
Chris@16 162
Chris@16 163 return this->median;
Chris@16 164 }
Chris@16 165 private:
Chris@16 166 mutable bool is_dirty;
Chris@16 167 mutable float_type median;
Chris@16 168 };
Chris@16 169
Chris@16 170 } // namespace impl
Chris@16 171
Chris@16 172 ///////////////////////////////////////////////////////////////////////////////
Chris@16 173 // tag::weighted_median
Chris@16 174 // tag::with_density_weighted_median
Chris@16 175 // tag::with_p_square_cumulative_distribution_weighted_median
Chris@16 176 //
Chris@16 177 namespace tag
Chris@16 178 {
Chris@16 179 struct weighted_median
Chris@16 180 : depends_on<weighted_p_square_quantile_for_median>
Chris@16 181 {
Chris@16 182 /// INTERNAL ONLY
Chris@16 183 ///
Chris@16 184 typedef accumulators::impl::weighted_median_impl<mpl::_1> impl;
Chris@16 185 };
Chris@16 186 struct with_density_weighted_median
Chris@16 187 : depends_on<count, weighted_density>
Chris@16 188 {
Chris@16 189 /// INTERNAL ONLY
Chris@16 190 ///
Chris@16 191 typedef accumulators::impl::with_density_weighted_median_impl<mpl::_1> impl;
Chris@16 192 };
Chris@16 193 struct with_p_square_cumulative_distribution_weighted_median
Chris@16 194 : depends_on<weighted_p_square_cumulative_distribution>
Chris@16 195 {
Chris@16 196 /// INTERNAL ONLY
Chris@16 197 ///
Chris@16 198 typedef accumulators::impl::with_p_square_cumulative_distribution_weighted_median_impl<mpl::_1, mpl::_2> impl;
Chris@16 199 };
Chris@16 200
Chris@16 201 }
Chris@16 202
Chris@16 203 ///////////////////////////////////////////////////////////////////////////////
Chris@16 204 // extract::weighted_median
Chris@16 205 //
Chris@16 206 namespace extract
Chris@16 207 {
Chris@16 208 extractor<tag::median> const weighted_median = {};
Chris@16 209
Chris@16 210 BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_median)
Chris@16 211 }
Chris@16 212
Chris@16 213 using extract::weighted_median;
Chris@16 214 // weighted_median(with_p_square_quantile) -> weighted_median
Chris@16 215 template<>
Chris@16 216 struct as_feature<tag::weighted_median(with_p_square_quantile)>
Chris@16 217 {
Chris@16 218 typedef tag::weighted_median type;
Chris@16 219 };
Chris@16 220
Chris@16 221 // weighted_median(with_density) -> with_density_weighted_median
Chris@16 222 template<>
Chris@16 223 struct as_feature<tag::weighted_median(with_density)>
Chris@16 224 {
Chris@16 225 typedef tag::with_density_weighted_median type;
Chris@16 226 };
Chris@16 227
Chris@16 228 // weighted_median(with_p_square_cumulative_distribution) -> with_p_square_cumulative_distribution_weighted_median
Chris@16 229 template<>
Chris@16 230 struct as_feature<tag::weighted_median(with_p_square_cumulative_distribution)>
Chris@16 231 {
Chris@16 232 typedef tag::with_p_square_cumulative_distribution_weighted_median type;
Chris@16 233 };
Chris@16 234
Chris@16 235 }} // namespace boost::accumulators
Chris@16 236
Chris@16 237 #endif