1 ///////////////////////////////////////////////////////////////////////////////
2 // main.hpp
3 //
4 // Copyright 2005 Eric Niebler. 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 #include <iostream>
9 #include <fstream> // needed for de/serialization example (4)
10 #include <algorithm>
11 #include <boost/ref.hpp>
12 #include <boost/bind.hpp>
13 #include <boost/array.hpp>
14 #include <boost/foreach.hpp>
15 #include <boost/accumulators/accumulators.hpp>
16 #include <boost/accumulators/statistics.hpp>
17 // needed for de/serialization example (4)
18 #include <boost/archive/text_oarchive.hpp>
19 #include <boost/archive/text_iarchive.hpp>
20
21 using namespace boost;
22 using namespace boost::accumulators;
23
24 // Helper that uses BOOST_FOREACH to display a range of doubles
25 template<typename Range>
output_range(Range const & rng)26 void output_range(Range const &rng)
27 {
28 bool first = true;
29 BOOST_FOREACH(double d, rng)
30 {
31 if(!first) std::cout << ", ";
32 std::cout << d;
33 first = false;
34 }
35 std::cout << '\n';
36 }
37
38 ///////////////////////////////////////////////////////////////////////////////
39 // example1
40 //
41 // Calculate some useful stats using accumulator_set<> and std::for_each()
42 //
example1()43 void example1()
44 {
45 accumulator_set<
46 double
47 , stats<tag::min, tag::mean(immediate), tag::sum, tag::moment<2> >
48 > acc;
49
50 boost::array<double, 4> data = {0., 1., -1., 3.14159};
51
52 // std::for_each pushes each sample into the accumulator one at a
53 // time, and returns a copy of the accumulator.
54 acc = std::for_each(data.begin(), data.end(), acc);
55
56 // The following would be equivalent, and could be more efficient
57 // because it doesn't pass and return the entire accumulator set
58 // by value.
59 //std::for_each(data.begin(), data.end(), bind<void>(ref(acc), _1));
60
61 std::cout << " min""(acc) = " << (min)(acc) << std::endl; // Extra quotes are to prevent complaints from Boost inspect tool
62 std::cout << " mean(acc) = " << mean(acc) << std::endl;
63
64 // since mean depends on count and sum, we can get their results, too.
65 std::cout << " count(acc) = " << count(acc) << std::endl;
66 std::cout << " sum(acc) = " << sum(acc) << std::endl;
67 std::cout << " moment<2>(acc) = " << accumulators::moment<2>(acc) << std::endl;
68 }
69
70 ///////////////////////////////////////////////////////////////////////////////
71 // example2
72 //
73 // Calculate some tail statistics. This demonstrates how to specify
74 // constructor and accumulator parameters. Note that the tail statistics
75 // return multiple values, which are returned in an iterator_range.
76 //
77 // It pushes data in and displays the intermediate results to demonstrate
78 // how the tail statistics are updated.
example2()79 void example2()
80 {
81 // An accumulator which tracks the right tail (largest N items) and
82 // some data that are covariate with them. N == 4.
83 accumulator_set<
84 double
85 , stats<tag::tail_variate<double, tag::covariate1, right> >
86 > acc(tag::tail<right>::cache_size = 4);
87
88 acc(2.1, covariate1 = .21);
89 acc(1.1, covariate1 = .11);
90 acc(2.1, covariate1 = .21);
91 acc(1.1, covariate1 = .11);
92
93 std::cout << " tail = "; output_range(tail(acc));
94 std::cout << " tail_variate = "; output_range(tail_variate(acc));
95 std::cout << std::endl;
96
97 acc(21.1, covariate1 = 2.11);
98 acc(11.1, covariate1 = 1.11);
99 acc(21.1, covariate1 = 2.11);
100 acc(11.1, covariate1 = 1.11);
101
102 std::cout << " tail = "; output_range(tail(acc));
103 std::cout << " tail_variate = "; output_range(tail_variate(acc));
104 std::cout << std::endl;
105
106 acc(42.1, covariate1 = 4.21);
107 acc(41.1, covariate1 = 4.11);
108 acc(42.1, covariate1 = 4.21);
109 acc(41.1, covariate1 = 4.11);
110
111 std::cout << " tail = "; output_range(tail(acc));
112 std::cout << " tail_variate = "; output_range(tail_variate(acc));
113 std::cout << std::endl;
114
115 acc(32.1, covariate1 = 3.21);
116 acc(31.1, covariate1 = 3.11);
117 acc(32.1, covariate1 = 3.21);
118 acc(31.1, covariate1 = 3.11);
119
120 std::cout << " tail = "; output_range(tail(acc));
121 std::cout << " tail_variate = "; output_range(tail_variate(acc));
122 }
123
124 ///////////////////////////////////////////////////////////////////////////////
125 // example3
126 //
127 // Demonstrate how to calculate weighted statistics. This example demonstrates
128 // both a simple weighted statistical calculation, and a more complicated
129 // calculation where the weight statistics are calculated and stored in an
130 // external weight accumulator.
example3()131 void example3()
132 {
133 // weight == double
134 double w = 1.;
135
136 // Simple weighted calculation
137 {
138 // stats that depend on the weight are made external
139 accumulator_set<double, stats<tag::mean>, double> acc;
140
141 acc(0., weight = w);
142 acc(1., weight = w);
143 acc(-1., weight = w);
144 acc(3.14159, weight = w);
145
146 std::cout << " mean(acc) = " << mean(acc) << std::endl;
147 }
148
149 // Weighted calculation with an external weight accumulator
150 {
151 // stats that depend on the weight are made external
152 accumulator_set<double, stats<tag::mean>, external<double> > acc;
153
154 // Here's an external weight accumulator
155 accumulator_set<void, stats<tag::sum_of_weights>, double> weight_acc;
156
157 weight_acc(weight = w); acc(0., weight = w);
158 weight_acc(weight = w); acc(1., weight = w);
159 weight_acc(weight = w); acc(-1., weight = w);
160 weight_acc(weight = w); acc(3.14159, weight = w);
161
162 std::cout << " mean(acc) = " << mean(acc, weights = weight_acc) << std::endl;
163 }
164 }
165
166 ///////////////////////////////////////////////////////////////////////////////
167 // example4
168 //
169 // Show how accumulators could be persisted into a file, and then continued
170 // from where they were left of
171 //
example4()172 void example4()
173 {
174 accumulator_set<
175 double
176 , stats<tag::min, tag::mean(immediate), tag::sum, tag::moment<2>, tag::p_square_quantile, tag::kurtosis >
177 > acc(quantile_probability = 0.9);
178
179 {
180 // accumulate values from array
181 boost::array<double, 10> data = {-10., -8., -7., -6., -5., -4., -3., -2., -1., 0.};
182
183 acc = std::for_each(data.begin(), data.end(), acc);
184 }
185
186 std::cout << " min = " << (min)(acc) << std::endl;
187 std::cout << " mean = " << mean(acc) << std::endl;
188 std::cout << " count = " << count(acc) << std::endl;
189 std::cout << " sum = " << sum(acc) << std::endl;
190 std::cout << " moment<2> = " << accumulators::moment<2>(acc) << std::endl;
191 std::cout << " p_square_quantile = " << accumulators::p_square_quantile(acc) << std::endl;
192 std::cout << " kurtosis = " << accumulators::kurtosis(acc) << std::endl;
193
194 // save accumulator list into a file called "saved-stats"
195 const unsigned ACC_VER = 0;
196 const char* file_name = "saved-stats";
197 {
198 std::ofstream ofs(file_name);
199 boost::archive::text_oarchive oa(ofs);
200 acc.serialize(oa, ACC_VER);
201 }
202
203 // create a new accumulator set and initialize from data saved into the file
204 accumulator_set<
205 double
206 , stats<tag::min, tag::mean(immediate), tag::sum, tag::moment<2>, tag::p_square_quantile, tag::kurtosis >
207 > restored_acc(quantile_probability = 0.9);
208
209 {
210 std::ifstream ifs(file_name);
211 boost::archive::text_iarchive ia(ifs);
212 restored_acc.serialize(ia, ACC_VER);
213 }
214
215 // continue accumulating into both sets
216 {
217 // accumulate values from array
218 boost::array<double, 10> data = {10., 8., 7., 6., 5., 4., 3., 2., 1., 0.};
219
220 acc = std::for_each(data.begin(), data.end(), acc);
221 restored_acc = std::for_each(data.begin(), data.end(), restored_acc);
222 }
223
224 // validate that both return th same values
225 std::cout << std::endl << "Values in original set:" << std::endl;
226 std::cout << " min""(acc) = " << (min)(acc) << std::endl;
227 std::cout << " mean(acc) = " << mean(acc) << std::endl;
228 std::cout << " count(acc) = " << count(acc) << std::endl;
229 std::cout << " sum(acc) = " << sum(acc) << std::endl;
230 std::cout << " moment<2>(acc) = " << accumulators::moment<2>(acc) << std::endl;
231 std::cout << " p_square_quantile(acc) = " << accumulators::p_square_quantile(acc) << std::endl;
232 std::cout << " kurtosis(acc) = " << accumulators::kurtosis(acc) << std::endl;
233
234 std::cout << std::endl << "Values in restored set:" << std::endl;
235 std::cout << " min""(acc) = " << (min)(restored_acc) << std::endl;
236 std::cout << " mean(acc) = " << mean(restored_acc) << std::endl;
237 std::cout << " count(acc) = " << count(restored_acc) << std::endl;
238 std::cout << " sum(acc) = " << sum(restored_acc) << std::endl;
239 std::cout << " moment<2>(acc) = " << accumulators::moment<2>(restored_acc) << std::endl;
240 std::cout << " p_square_quantile(acc) = " << accumulators::p_square_quantile(restored_acc) << std::endl;
241 std::cout << " kurtosis(acc) = " << accumulators::kurtosis(restored_acc) << std::endl;
242
243 }
244
245 ///////////////////////////////////////////////////////////////////////////////
246 // main
main()247 int main()
248 {
249 std::cout << "Example 1:\n";
250 example1();
251
252 std::cout << "\nExample 2:\n";
253 example2();
254
255 std::cout << "\nExample 3:\n";
256 example3();
257
258 std::cout << "\nExample 4:\n";
259 example4();
260
261 return 0;
262 }
263