Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
Accumulator.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef CORE_UTILS_ACCUMULATOR
20#define CORE_UTILS_ACCUMULATOR
21
22#include <boost/serialization/access.hpp>
23#include <boost/serialization/vector.hpp>
24
25#include <algorithm>
26#include <cmath>
27#include <cstddef>
28#include <limits>
29#include <stdexcept>
30#include <vector>
31
32namespace Utils {
33
34template <typename T> struct AccumulatorData {
35 T mean = T{};
36 T m = T{};
37
38private:
39 // Allow serialization to access non-public data members.
41
42 template <typename Archive>
43 void serialize(Archive &ar, const unsigned /*version*/) {
44 ar & mean & m;
45 }
46};
47
49public:
50 explicit Accumulator(std::size_t N) : m_n(0u), m_acc_data(N) {}
51 void operator()(const std::vector<double> &);
52 std::vector<double> mean() const;
53 std::vector<double> variance() const;
54 std::vector<double> std_error() const;
55
56private:
57 std::size_t m_n;
58 std::vector<AccumulatorData<double>> m_acc_data;
59 // Allow serialization to access non-public data members.
61
62 template <typename Archive>
63 void serialize(Archive &ar, const unsigned /*version*/) {
64 ar & m_n & m_acc_data;
65 }
66};
67
68inline void Accumulator::operator()(const std::vector<double> &data) {
69 if (data.size() != m_acc_data.size())
70 throw std::runtime_error(
71 "The given data size does not fit the initialized size!");
72 ++m_n;
73 if (m_n == 1u) {
74 std::ranges::transform(
75 data, m_acc_data.begin(),
76 [](double d) -> AccumulatorData<double> { return {d, 0.0}; });
77 } else {
78 auto const denominator = static_cast<double>(m_n);
79 std::ranges::transform(m_acc_data, data, m_acc_data.begin(),
80 [denominator](auto const &a, double d) {
81 auto const old_mean = a.mean;
82 auto const new_mean =
83 old_mean + (d - old_mean) / denominator;
84 auto const new_m =
85 a.m + (d - old_mean) * (d - new_mean);
86 return AccumulatorData<double>{new_mean, new_m};
87 });
88 }
89}
90
91/**
92 * @brief Compute the sample mean.
93 */
94inline std::vector<double> Accumulator::mean() const {
95 std::vector<double> res{};
96 std::ranges::transform(m_acc_data, std::back_inserter(res),
97 [](auto const &acc_data) { return acc_data.mean; });
98 return res;
99}
100
101/**
102 * @brief Compute the Bessel-corrected sample variance,
103 * assuming uncorrelated data.
104 */
105inline std::vector<double> Accumulator::variance() const {
106 std::vector<double> res{};
107 if (m_n == 1u) {
108 res = std::vector<double>(m_acc_data.size(),
109 std::numeric_limits<double>::max());
110 } else {
111 auto const denominator = static_cast<double>(m_n) - 1.;
112 std::ranges::transform(m_acc_data, std::back_inserter(res),
113 [denominator](auto const &acc_data) {
114 return acc_data.m / denominator;
115 });
116 }
117 return res;
118}
119
120/**
121 * @brief Compute the standard error of the mean, assuming uncorrelated data.
122 */
123inline std::vector<double> Accumulator::std_error() const {
124 auto const var = variance();
125 std::vector<double> err{};
126 auto const denominator = static_cast<double>(m_n);
127 std::ranges::transform(var, std::back_inserter(err), [denominator](double d) {
128 return std::sqrt(d / denominator);
129 });
130 return err;
131}
132
133} // namespace Utils
134
135#endif
std::vector< double > std_error() const
Compute the standard error of the mean, assuming uncorrelated data.
Accumulator(std::size_t N)
std::vector< double > variance() const
Compute the Bessel-corrected sample variance, assuming uncorrelated data.
void operator()(const std::vector< double > &)
std::vector< double > mean() const
Compute the sample mean.
friend class boost::serialization::access
friend class boost::serialization::access