Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // weighted_variance.hpp Chris@16: // Chris@16: // Copyright 2005 Daniel Egloff, Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_VARIANCE_HPP_EAN_28_10_2005 Chris@16: #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_VARIANCE_HPP_EAN_28_10_2005 Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace accumulators Chris@16: { Chris@16: Chris@16: namespace impl Chris@16: { Chris@16: //! Lazy calculation of variance of weighted samples. Chris@16: /*! Chris@16: The default implementation of the variance of weighted samples is based on the second moment Chris@16: \f$\widehat{m}_n^{(2)}\f$ (weighted_moment<2>) and the mean\f$ \hat{\mu}_n\f$ (weighted_mean): Chris@16: \f[ Chris@16: \hat{\sigma}_n^2 = \widehat{m}_n^{(2)}-\hat{\mu}_n^2, Chris@16: \f] Chris@16: where \f$n\f$ is the number of samples. Chris@16: */ Chris@16: template Chris@16: struct lazy_weighted_variance_impl Chris@16: : accumulator_base Chris@16: { Chris@16: typedef typename numeric::functional::multiplies::result_type weighted_sample; Chris@16: // for boost::result_of Chris@16: typedef typename numeric::functional::fdiv::result_type result_type; Chris@16: Chris@16: lazy_weighted_variance_impl(dont_care) {} Chris@16: Chris@16: template Chris@16: result_type result(Args const &args) const Chris@16: { Chris@16: extractor const some_mean = {}; Chris@16: result_type tmp = some_mean(args); Chris@16: return accumulators::weighted_moment<2>(args) - tmp * tmp; Chris@16: } Chris@16: }; Chris@16: Chris@16: //! Iterative calculation of variance of weighted samples. Chris@16: /*! Chris@16: Iterative calculation of variance of weighted samples: Chris@16: \f[ Chris@16: \hat{\sigma}_n^2 = Chris@16: \frac{\bar{w}_n - w_n}{\bar{w}_n}\hat{\sigma}_{n - 1}^2 Chris@16: + \frac{w_n}{\bar{w}_n - w_n}\left(X_n - \hat{\mu}_n\right)^2 Chris@16: ,\quad n\ge2,\quad\hat{\sigma}_0^2 = 0. Chris@16: \f] Chris@16: where \f$\bar{w}_n\f$ is the sum of the \f$n\f$ weights \f$w_i\f$ and \f$\hat{\mu}_n\f$ Chris@16: the estimate of the mean of the weighted samples. Note that the sample variance is not defined for Chris@16: \f$n <= 1\f$. Chris@16: */ Chris@16: template Chris@16: struct weighted_variance_impl Chris@16: : accumulator_base Chris@16: { Chris@16: typedef typename numeric::functional::multiplies::result_type weighted_sample; Chris@16: // for boost::result_of Chris@16: typedef typename numeric::functional::fdiv::result_type result_type; Chris@16: Chris@16: template Chris@16: weighted_variance_impl(Args const &args) Chris@16: : weighted_variance(numeric::fdiv(args[sample | Sample()], numeric::one::value)) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: void operator ()(Args const &args) Chris@16: { Chris@16: std::size_t cnt = count(args); Chris@16: Chris@16: if(cnt > 1) Chris@16: { Chris@16: extractor const some_mean = {}; Chris@16: Chris@16: result_type tmp = args[parameter::keyword::get()] - some_mean(args); Chris@16: Chris@16: this->weighted_variance = Chris@16: numeric::fdiv(this->weighted_variance * (sum_of_weights(args) - args[weight]), sum_of_weights(args)) Chris@16: + numeric::fdiv(tmp * tmp * args[weight], sum_of_weights(args) - args[weight] ); Chris@16: } Chris@16: } Chris@16: Chris@16: result_type result(dont_care) const Chris@16: { Chris@16: return this->weighted_variance; Chris@16: } Chris@16: Chris@16: private: Chris@16: result_type weighted_variance; Chris@16: }; Chris@16: Chris@16: } // namespace impl Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // tag::weighted_variance Chris@16: // tag::immediate_weighted_variance Chris@16: // Chris@16: namespace tag Chris@16: { Chris@16: struct lazy_weighted_variance Chris@16: : depends_on, weighted_mean> Chris@16: { Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: typedef accumulators::impl::lazy_weighted_variance_impl impl; Chris@16: }; Chris@16: Chris@16: struct weighted_variance Chris@16: : depends_on Chris@16: { Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: typedef accumulators::impl::weighted_variance_impl impl; Chris@16: }; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // extract::weighted_variance Chris@16: // extract::immediate_weighted_variance Chris@16: // Chris@16: namespace extract Chris@16: { Chris@16: extractor const lazy_weighted_variance = {}; Chris@16: extractor const weighted_variance = {}; Chris@16: Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(lazy_weighted_variance) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_variance) Chris@16: } Chris@16: Chris@16: using extract::lazy_weighted_variance; Chris@16: using extract::weighted_variance; Chris@16: Chris@16: // weighted_variance(lazy) -> lazy_weighted_variance Chris@16: template<> Chris@16: struct as_feature Chris@16: { Chris@16: typedef tag::lazy_weighted_variance type; Chris@16: }; Chris@16: Chris@16: // weighted_variance(immediate) -> weighted_variance Chris@16: template<> Chris@16: struct as_feature Chris@16: { Chris@16: typedef tag::weighted_variance type; Chris@16: }; Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////// Chris@16: //// droppable_accumulator Chris@16: //// need to specialize droppable lazy weighted_variance to cache the result at the Chris@16: //// point the accumulator is dropped. Chris@16: ///// INTERNAL ONLY Chris@16: ///// Chris@16: //template Chris@16: //struct droppable_accumulator > Chris@16: // : droppable_accumulator_base< Chris@16: // with_cached_result > Chris@16: // > Chris@16: //{ Chris@16: // template Chris@16: // droppable_accumulator(Args const &args) Chris@16: // : droppable_accumulator::base(args) Chris@16: // { Chris@16: // } Chris@16: //}; Chris@16: Chris@16: }} // namespace boost::accumulators Chris@16: Chris@16: #endif