Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:43

0001 // Copyright 2022 Jay Gohil, Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_ACCUMULATORS_FRACTION_HPP
0008 #define BOOST_HISTOGRAM_ACCUMULATORS_FRACTION_HPP
0009 
0010 #include <boost/core/nvp.hpp>
0011 #include <boost/histogram/fwd.hpp> // for fraction<>
0012 #include <boost/histogram/utility/wilson_interval.hpp>
0013 #include <type_traits> // for std::common_type
0014 
0015 namespace boost {
0016 namespace histogram {
0017 namespace accumulators {
0018 
0019 /**
0020   Accumulate boolean samples and compute the fraction of true samples.
0021 
0022   This accumulator should be used to calculate the efficiency or success fraction of a
0023   random process as a function of process parameters. It returns the fraction of
0024   successes, the variance of this fraction, and a two-sided confidence interval with 68.3
0025   % confidence level for this fraction.
0026 
0027   There is no unique way to compute an interval for a success fraction. This class returns
0028   the Wilson score interval, because it is widely recommended in the literature for
0029   general use. More interval computers can be found in `boost/histogram/utility`, which
0030   can be used to compute intervals for other confidence levels.
0031 */
0032 template <class ValueType>
0033 class fraction {
0034 public:
0035   using value_type = ValueType;
0036   using const_reference = const value_type&;
0037   using real_type = typename std::conditional<std::is_floating_point<value_type>::value,
0038                                               value_type, double>::type;
0039   using interval_type = typename utility::wilson_interval<real_type>::interval_type;
0040 
0041   fraction() noexcept = default;
0042 
0043   /// Initialize to external successes and failures.
0044   fraction(const_reference successes, const_reference failures) noexcept
0045       : succ_(successes), fail_(failures) {}
0046 
0047   /// Allow implicit conversion from fraction with a different value type.
0048   template <class T>
0049   fraction(const fraction<T>& e) noexcept
0050       : fraction{static_cast<value_type>(e.successes()),
0051                  static_cast<value_type>(e.failures())} {}
0052 
0053   /// Insert boolean sample x.
0054   void operator()(bool x) noexcept {
0055     if (x)
0056       ++succ_;
0057     else
0058       ++fail_;
0059   }
0060 
0061   /// Add another accumulator.
0062   fraction& operator+=(const fraction& rhs) noexcept {
0063     succ_ += rhs.succ_;
0064     fail_ += rhs.fail_;
0065     return *this;
0066   }
0067 
0068   /// Return number of boolean samples that were true.
0069   const_reference successes() const noexcept { return succ_; }
0070 
0071   /// Return number of boolean samples that were false.
0072   const_reference failures() const noexcept { return fail_; }
0073 
0074   /// Return total number of boolean samples.
0075   value_type count() const noexcept { return succ_ + fail_; }
0076 
0077   /// Return success fraction of boolean samples.
0078   real_type value() const noexcept { return static_cast<real_type>(succ_) / count(); }
0079 
0080   /// Return variance of the success fraction.
0081   real_type variance() const noexcept {
0082     // We want to compute Var(p) for p = X / n with Var(X) = n p (1 - p)
0083     // For Var(X) see
0084     // https://en.wikipedia.org/wiki/Binomial_distribution#Expected_value_and_variance
0085     // Error propagation: Var(p) = p'(X)^2 Var(X) = p (1 - p) / n
0086     const real_type p = value();
0087     return p * (1 - p) / count();
0088   }
0089 
0090   /// Return standard interval with 68.3 % confidence level (Wilson score interval).
0091   interval_type confidence_interval() const noexcept {
0092     return utility::wilson_interval<real_type>()(static_cast<real_type>(successes()),
0093                                                  static_cast<real_type>(failures()));
0094   }
0095 
0096   bool operator==(const fraction& rhs) const noexcept {
0097     return succ_ == rhs.succ_ && fail_ == rhs.fail_;
0098   }
0099 
0100   bool operator!=(const fraction& rhs) const noexcept { return !operator==(rhs); }
0101 
0102   template <class Archive>
0103   void serialize(Archive& ar, unsigned /* version */) {
0104     ar& make_nvp("successes", succ_);
0105     ar& make_nvp("failures", fail_);
0106   }
0107 
0108 private:
0109   value_type succ_{};
0110   value_type fail_{};
0111 };
0112 
0113 } // namespace accumulators
0114 } // namespace histogram
0115 } // namespace boost
0116 
0117 #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
0118 
0119 namespace std {
0120 template <class T, class U>
0121 /// Specialization for boost::histogram::accumulators::fraction.
0122 struct common_type<boost::histogram::accumulators::fraction<T>,
0123                    boost::histogram::accumulators::fraction<U>> {
0124   using type = boost::histogram::accumulators::fraction<common_type_t<T, U>>;
0125 };
0126 } // namespace std
0127 
0128 #endif
0129 
0130 #endif