ALPSCore reference
variance.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 #include <alps/alea/variance.hpp>
7 #include <alps/alea/util.hpp>
9 
12 
13 namespace alps { namespace alea {
14 
15 template <typename T, typename Str>
17  : data_(size)
18  , data2_(size)
19 {
20  reset();
21 }
22 
23 template <typename T, typename Str>
25 {
26  data_.fill(0);
27  data2_.fill(0);
28  count_ = 0;
29  count2_ = 0;
30 }
31 
32 template <typename T, typename Str>
34 {
35  // This also works for count_ == 0
36  data_ /= count_;
37  data2_ -= count_ * data_.cwiseAbs2();
38 
39  // In case of zero unbiased information, the variance is infinite.
40  // However, data2_ is 0 in this case as well, so we need to handle it
41  // specially to avoid 0/0 = nan while propagating intrinsic NaN's.
42  const double nunbiased = count_ - count2_/count_;
43  if (nunbiased == 0) {
44  data2_ = data2_.array().isNaN().select(data2_, INFINITY);
45  } else {
46  // HACK: this is written in out-of-place notation to work around Eigen
47  data2_ = data2_ / nunbiased;
48  }
49 }
50 
51 template <typename T, typename Str>
53 {
54  // "empty" sets must be handled specially here because of NaNs
55  if (count_ == 0) {
56  reset();
57  return;
58  }
59 
60  // Care must be taken again for zero unbiased info since inf/0 is NaN.
61  const double nunbiased = count_ - count2_/count_;
62  if (nunbiased == 0)
63  data2_ = data2_.array().isNaN().select(data2_, 0);
64  else
65  data2_ = data2_ * nunbiased;
66 
67  data2_ += count_ * data_.cwiseAbs2();
68  data_ *= count_;
69 }
70 
71 template class var_data<double>;
74 
75 
76 template <typename T, typename Str>
77 var_acc<T,Str>::var_acc(size_t size, size_t batch_size)
78  : store_(new var_data<T,Str>(size))
79  , current_(size, batch_size)
80 { }
81 
82 // We need an explicit copy constructor, as we need to copy the data
83 template <typename T, typename Str>
85  : store_(other.store_ ? new var_data<T,Str>(*other.store_) : nullptr)
86  , current_(other.current_)
87 { }
88 
89 template <typename T, typename Str>
91 {
92  store_.reset(other.store_ ? new var_data<T,Str>(*other.store_) : nullptr);
93  current_ = other.current_;
94  return *this;
95 }
96 
97 template <typename T, typename Str>
99 {
100  current_.reset();
101  if (valid())
102  store_->reset();
103  else
104  store_.reset(new var_data<T,Str>(size()));
105 }
106 
107 template <typename T, typename Str>
109 {
110  current_ = bundle<T>(size, current_.target());
111  if (valid())
112  store_.reset(new var_data<T,Str>(size));
113 }
114 
115 template <typename T, typename Str>
117 {
118  // TODO: allow resizing with reset
119  current_.target() = batch_size;
120  current_.reset();
121 }
122 
123 template <typename T, typename Str>
124 void var_acc<T,Str>::add(const computed<T> &source, size_t count,
125  var_acc<T,Str> *cascade)
126 {
127  internal::check_valid(*this);
128  source.add_to(view<T>(current_.sum().data(), current_.size()));
129  current_.count() += count;
130 
131  if (current_.is_full())
132  add_bundle(cascade);
133 }
134 
135 template <typename T, typename Str>
137 {
138  internal::check_valid(*this);
139  if (size() != other.size())
140  throw size_mismatch();
141 
142  // NOTE partial sums are unchanged
143  // HACK we need this for "outwardly constant" manipulation
144  var_data<T,Str> &other_store = const_cast<var_data<T,Str> &>(other.store());
145  other_store.convert_to_sum();
146  store_->data() += other_store.data();
147  store_->data2() += other_store.data2();
148  store_->count() += other_store.count();
149  store_->count2() += other_store.count2();
150  other_store.convert_to_mean();
151  return *this;
152 }
153 
154 template <typename T, typename Str>
156 {
157  internal::check_valid(*this);
159  var_acc<T,Str>(*this).finalize_to(result, nullptr);
160  return result;
161 }
162 
163 template <typename T, typename Str>
165 {
167  finalize_to(result, nullptr);
168  return result;
169 }
170 
171 template <typename T, typename Str>
173 {
174  internal::check_valid(*this);
175 
176  // add leftover data to the variance. The upwards propagation must be
177  // handled by going through a hierarchy in ascending order.
178  if (current_.count() != 0)
179  add_bundle(cascade);
180 
181  // data swap
182  result.store_.reset();
183  result.store_.swap(store_);
184 
185  // post-processing to result
186  result.store_->convert_to_mean();
187 }
188 
189 template <typename T, typename Str>
191 {
192  typename bind<Str, T>::abs2_op abs2;
193 
194  // add batch to average and squared
195  store_->data().noalias() += current_.sum();
196  store_->data2().noalias() += current_.sum().unaryExpr(abs2) / current_.count();
197  store_->count() += current_.count();
198  store_->count2() += current_.count() * current_.count();
199 
200  // add batch mean also to uplevel
201  if (cascade != nullptr)
202  cascade->add(make_adapter(current_.sum()), current_.count(), cascade+1);
203 
204  current_.reset();
205 }
206 
207 template class var_acc<double>;
208 template class var_acc<std::complex<double>, circular_var>;
209 template class var_acc<std::complex<double>, elliptic_var>;
210 
211 // We need an explicit copy constructor, as we need to copy the data
212 template <typename T, typename Str>
214  : store_(other.store_ ? new var_data<T,Str>(*other.store_) : nullptr)
215 { }
216 
217 template <typename T, typename Str>
219 {
220  store_.reset(other.store_ ? new var_data<T,Str>(*other.store_) : nullptr);
221  return *this;
222 }
223 
224 template <typename T, typename Strategy>
226 {
227  if (r1.count() == 0 && r2.count() == 0)
228  return true;
229 
230  return r1.count() == r2.count()
231  && r1.count2() == r2.count2()
232  && r1.store().data() == r2.store().data()
233  && r1.store().data2() == r2.store().data2();
234 }
235 
236 template bool operator==(const var_result<double> &r1, const var_result<double> &r2);
237 template bool operator==(const var_result<std::complex<double>, circular_var> &r1,
238  const var_result<std::complex<double>, circular_var> &r2);
239 template bool operator==(const var_result<std::complex<double>, elliptic_var> &r1,
240  const var_result<std::complex<double>, elliptic_var> &r2);
241 
242 template <typename T, typename Str>
244 {
245  internal::check_valid(*this);
246  return (store_->data2() / observations()).cwiseSqrt();
247 }
248 
249 template <typename T, typename Str>
250 void var_result<T,Str>::reduce(const reducer &r, bool pre_commit, bool post_commit)
251 {
252  internal::check_valid(*this);
253  if (pre_commit) {
254  store_->convert_to_sum();
255  r.reduce(view<T>(store_->data().data(), store_->data().rows()));
256  r.reduce(view<var_type>(store_->data2().data(), store_->data2().rows()));
257  r.reduce(view<size_t>(&store_->count(), 1));
258  r.reduce(view<double>(&store_->count2(), 1));
259  }
260  if (pre_commit && post_commit) {
261  r.commit();
262  }
263  if (post_commit) {
264  reducer_setup setup = r.get_setup();
265  if (setup.have_result)
266  store_->convert_to_mean();
267  else
268  store_.reset(); // free data
269  }
270 }
271 
272 template class var_result<double>;
273 template class var_result<std::complex<double>, circular_var>;
274 template class var_result<std::complex<double>, elliptic_var>;
275 
276 
277 template <typename T, typename Str>
278 void serialize(serializer &s, const std::string &key, const var_result<T,Str> &self)
279 {
280  internal::check_valid(self);
281  internal::serializer_sentry group(s, key);
282 
283  serialize(s, "@size", self.store_->data_.size());
284  serialize(s, "count", self.store_->count_);
285  serialize(s, "count2", self.store_->count2_);
286  s.enter("mean");
287  serialize(s, "value", self.store_->data_);
288  serialize(s, "error", self.stderror()); // TODO temporary
289  s.exit();
290  serialize(s, "var", self.store_->data2_);
291 }
292 
293 template <typename T, typename Str>
294 void deserialize(deserializer &s, const std::string &key, var_result<T,Str> &self)
295 {
296  typedef typename var_result<T,Str>::var_type var_type;
297  internal::deserializer_sentry group(s, key);
298 
299  // first deserialize the fundamentals and make sure that the target fits
300  size_t new_size;
301  deserialize(s, "@size", new_size);
302  if (!self.valid() || self.size() != new_size)
303  self.store_.reset(new var_data<T,Str>(new_size));
304 
305  // deserialize data
306  deserialize(s, "count", self.store_->count_);
307  deserialize(s, "count2", self.store_->count2_);
308  s.enter("mean");
309  deserialize(s, "value", self.store_->data_);
310  s.read("error", ndview<var_type>(nullptr, &new_size, 1)); // discard
311  s.exit();
312  deserialize(s, "var", self.store_->data2_);
313 }
314 
315 template void serialize(serializer &, const std::string &key, const var_result<double, circular_var> &);
316 template void serialize(serializer &, const std::string &key, const var_result<std::complex<double>, circular_var> &);
317 template void serialize(serializer &, const std::string &key, const var_result<std::complex<double>, elliptic_var> &);
318 
319 template void deserialize(deserializer &, const std::string &key, var_result<double, circular_var> &);
320 template void deserialize(deserializer &, const std::string &key, var_result<std::complex<double>, circular_var> &);
321 template void deserialize(deserializer &, const std::string &key, var_result<std::complex<double>, elliptic_var> &);
322 
323 
324 template <typename T, typename Str>
325 std::ostream &operator<<(std::ostream &str, const var_result<T,Str> &self)
326 {
327  internal::check_valid(self);
328  internal::format_sentry sentry(str);
330 
331  if (verb == PRINT_VERBOSE)
332  str << "<X> = ";
333  str << self.mean() << " +- " << self.stderror();
334  return str;
335 }
336 
337 template std::ostream &operator<<(std::ostream &, const var_result<double, circular_var> &);
338 template std::ostream &operator<<(std::ostream &, const var_result<std::complex<double>, circular_var> &);
339 template std::ostream &operator<<(std::ostream &, const var_result<std::complex<double>, elliptic_var> &);
340 
341 }}
size_t size() const
Definition: variance.hpp:145
void finalize_to(var_result< T, Strategy > &result, var_acc *cascade)
Definition: variance.cpp:172
size_t count() const
Definition: variance.hpp:157
var_result< T, Strategy > result() const
Definition: variance.cpp:155
column< var_type > stderror() const
Definition: variance.cpp:243
void check_valid(const Acc &acc)
Definition: util.hpp:17
size_t size() const
Definition: variance.hpp:224
size_t size() const
Definition: variance.hpp:65
const column< value_type > & data() const
Definition: variance.hpp:79
std::enable_if<!is_sequence< T >::value, std::size_t >::type size(T const &)
Definition: size.hpp:20
const var_data< T, Strategy > & store() const
Definition: variance.hpp:252
double count2() const
Definition: variance.hpp:233
size_t batch_size() const
Definition: variance.hpp:148
size_t size() const
Definition: bundle.hpp:31
virtual void exit()=0
void set_size(size_t size)
Definition: variance.cpp:108
void add_bundle(var_acc *cascade)
Definition: variance.cpp:190
column< T > & sum()
Definition: bundle.hpp:41
var_result & operator=(const var_result &other)
Definition: variance.cpp:218
var_result< T, Strategy > finalize()
Definition: variance.cpp:164
void reduce(const reducer &r)
Definition: variance.hpp:258
friend void serialize(serializer &, const std::string &, const var_result &)
size_t count() const
Definition: variance.hpp:68
var_data(size_t size)
Definition: variance.cpp:16
size_t & target()
Definition: bundle.hpp:33
void add(const computed< T > &source, size_t count, var_acc *cascade)
Definition: variance.cpp:124
virtual void commit() const =0
bool valid() const
Definition: variance.hpp:142
double count2() const
Definition: variance.hpp:74
bind< Strategy, T >::var_type var_type
Definition: variance.hpp:207
const column< var_type > & data2() const
Definition: variance.hpp:83
T & get_format(std::ios_base &stream, T initial_value=T())
Definition: format.hpp:90
size_t count() const
Definition: variance.hpp:230
var_acc & operator=(const var_acc &other)
Definition: variance.cpp:90
var_acc(size_t size=1, size_t batch_size=1)
Definition: variance.cpp:77
virtual void read(const std::string &key, ndview< double >)=0
size_t & count()
Definition: bundle.hpp:37
virtual void add_to(view< T > out) const =0
bool valid() const
Definition: variance.hpp:221
friend void deserialize(deserializer &, const std::string &, var_result &)
bool operator==(const autocorr_result< T > &r1, const autocorr_result< T > &r2)
Definition: autocorr.cpp:136
virtual reducer_setup get_setup() const =0
virtual void enter(const std::string &group)=0
T r(T x, T y=T(), T z=T())
eigen_adapter< typename Derived::Scalar, Derived > make_adapter(const Eigen::DenseBase< Derived > &in)
Definition: computed.hpp:34
var_acc & operator<<(const computed< T > &src)
Definition: variance.hpp:151
virtual void reduce(view< double > data) const =0
virtual void enter(const std::string &group)=0
virtual void exit()=0
double observations() const
Definition: variance.hpp:236
void set_batch_size(size_t batch_size)
Definition: variance.cpp:116