]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // Copyright 2015-2018 Hans Dembinski |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. | |
4 | // (See accompanying file LICENSE_1_0.txt | |
5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | #include <boost/core/lightweight_test.hpp> | |
8 | #include <boost/histogram/accumulators/ostream.hpp> | |
9 | #include <boost/histogram/accumulators/weighted_mean.hpp> | |
10 | #include <boost/histogram/weight.hpp> | |
11 | #include <sstream> | |
12 | #include "is_close.hpp" | |
13 | #include "throw_exception.hpp" | |
14 | #include "utility_str.hpp" | |
15 | ||
16 | using namespace boost::histogram; | |
17 | using namespace std::literals; | |
18 | ||
19 | int main() { | |
20 | using m_t = accumulators::weighted_mean<double>; | |
1e59de90 | 21 | using detail::square; |
f67539c2 | 22 | |
1e59de90 TL |
23 | // basic interface, string conversion |
24 | { | |
25 | // see https://en.wikipedia.org/wiki/Weighted_arithmetic_mean#Reliability_weights | |
f67539c2 | 26 | |
1e59de90 TL |
27 | m_t a; |
28 | BOOST_TEST_EQ(a.sum_of_weights(), 0); | |
29 | BOOST_TEST_EQ(a, m_t{}); | |
f67539c2 | 30 | |
1e59de90 TL |
31 | a(weight(0.5), 1); |
32 | a(weight(1.0), 2); | |
33 | a(weight(0.5), 3); | |
f67539c2 | 34 | |
1e59de90 TL |
35 | BOOST_TEST_EQ(a.sum_of_weights(), 1 + 2 * 0.5); |
36 | BOOST_TEST_EQ(a.sum_of_weights_squared(), 1 + 2 * 0.5 * 0.5); | |
37 | // https://en.wikipedia.org/wiki/Effective_sample_size#weighted_samples | |
38 | BOOST_TEST_EQ(a.count(), square(a.sum_of_weights()) / a.sum_of_weights_squared()); | |
39 | BOOST_TEST_EQ(a.value(), (0.5 * 1 + 1.0 * 2 + 0.5 * 3) / a.sum_of_weights()); | |
40 | const auto m = a.value(); | |
41 | BOOST_TEST_IS_CLOSE( | |
42 | a.variance(), | |
43 | (0.5 * square(1 - m) + square(2 - m) + 0.5 * square(3 - m)) / | |
44 | (a.sum_of_weights() - a.sum_of_weights_squared() / a.sum_of_weights()), | |
45 | 1e-3); | |
f67539c2 | 46 | |
1e59de90 TL |
47 | BOOST_TEST_EQ(str(a), "weighted_mean(2, 2, 0.8)"s); |
48 | BOOST_TEST_EQ(str(a, 25, false), " weighted_mean(2, 2, 0.8)"s); | |
49 | BOOST_TEST_EQ(str(a, 25, true), "weighted_mean(2, 2, 0.8) "s); | |
50 | } | |
f67539c2 | 51 | |
1e59de90 TL |
52 | // addition of zero element |
53 | { | |
54 | BOOST_TEST_EQ(m_t() += m_t(), m_t()); | |
55 | BOOST_TEST_EQ(m_t(1, 2, 3, 4) += m_t(), m_t(1, 2, 3, 4)); | |
56 | BOOST_TEST_EQ(m_t() += m_t(1, 2, 3, 4), m_t(1, 2, 3, 4)); | |
57 | } | |
58 | ||
59 | // addition | |
60 | { | |
61 | m_t a, b, c; | |
62 | ||
63 | a(weight(4), 2); | |
64 | a(weight(3), 3); | |
65 | BOOST_TEST_EQ(a.sum_of_weights(), 4 + 3); | |
66 | BOOST_TEST_EQ(a.sum_of_weights_squared(), 4 * 4 + 3 * 3); | |
67 | BOOST_TEST_EQ(a.value(), (4 * 2 + 3 * 3) / 7.); | |
68 | BOOST_TEST_IS_CLOSE(a.variance(), 0.5, 1e-3); | |
69 | ||
70 | b(weight(2), 4); | |
71 | b(weight(1), 6); | |
72 | BOOST_TEST_EQ(b.sum_of_weights(), 3); | |
73 | BOOST_TEST_EQ(b.sum_of_weights_squared(), 1 + 2 * 2); | |
74 | BOOST_TEST_EQ(b.value(), (2 * 4 + 1 * 6) / (2. + 1.)); | |
75 | BOOST_TEST_IS_CLOSE(b.variance(), 2, 1e-3); | |
76 | ||
77 | c(weight(4), 2); | |
78 | c(weight(3), 3); | |
79 | c(weight(2), 4); | |
80 | c(weight(1), 6); | |
81 | ||
82 | auto d = a; | |
83 | d += b; | |
84 | BOOST_TEST_EQ(c.sum_of_weights(), d.sum_of_weights()); | |
85 | BOOST_TEST_EQ(c.sum_of_weights_squared(), d.sum_of_weights_squared()); | |
86 | BOOST_TEST_EQ(c.value(), d.value()); | |
87 | BOOST_TEST_IS_CLOSE(c.variance(), d.variance(), 1e-3); | |
88 | } | |
89 | ||
90 | // using weights * 2 compared to adding weighted samples twice must | |
91 | // - give same for sum_of_weights and mean | |
92 | // - give twice sum_of_weights_squared | |
93 | // - give half effective count | |
94 | // - variance is complicated, but larger | |
95 | { | |
96 | m_t a, b; | |
97 | ||
98 | for (int i = 0; i < 2; ++i) { | |
99 | a(weight(0.5), 1); | |
100 | a(weight(1.0), 2); | |
101 | a(weight(0.5), 3); | |
102 | } | |
103 | ||
104 | b(weight(1), 1); | |
105 | b(weight(2), 2); | |
106 | b(weight(1), 3); | |
107 | ||
108 | BOOST_TEST_EQ(a.sum_of_weights(), b.sum_of_weights()); | |
109 | BOOST_TEST_EQ(2 * a.sum_of_weights_squared(), b.sum_of_weights_squared()); | |
110 | BOOST_TEST_EQ(a.count(), 2 * b.count()); | |
111 | BOOST_TEST_EQ(a.value(), b.value()); | |
112 | BOOST_TEST_LT(a.variance(), b.variance()); | |
113 | } | |
f67539c2 TL |
114 | |
115 | return boost::report_errors(); | |
116 | } |