ALPSCore reference
accumulator.hpp
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 
7 #pragma once
8 
9 #include <alps/config.hpp>
10 #include <alps/hdf5/vector.hpp>
11 
13 // #include <alps/accumulators/feature/weight_holder.hpp>
15 
16 #include <alps/hdf5/archive.hpp>
17 
18 #include <memory>
19 
20 #include <boost/variant/variant.hpp>
21 #include <boost/variant/get.hpp>
22 
23 #ifdef ALPS_HAVE_MPI
25 #endif
26 
27 #include <typeinfo>
28 #include <type_traits>
29 #include <stdexcept>
30 
31 namespace alps {
32  namespace accumulators {
33 
34  namespace detail {
35  typedef std::string printable_type;
36 
37  template<typename T> struct add_base_wrapper_pointer {
38  typedef std::shared_ptr<base_wrapper<T> > type;
39  };
40 
41  template<typename... Types> struct make_variant_type {
42  typedef boost::variant<typename add_base_wrapper_pointer<Types>::type...> type;
43  };
44 
45  typedef typename make_variant_type<ALPS_ACCUMULATOR_VALUE_TYPES>::type variant_type;
46 
47  template<typename T, typename A> struct is_valid_argument : std::conditional<
48  std::is_scalar<A>::value
49  , typename std::is_convertible<T, A>::type
50  , typename std::is_same<T, A>::type
51  >::type {};
52 
54 
57  template <typename LHSWT, typename RHSWT>
58  struct is_compatible_op
59  : std::is_same<typename alps::numeric::scalar<typename LHSWT::value_type>::type,
60  typename RHSWT::value_type>
61  { };
62 
64 
65  // FIXME: better initialize the pointer with something reasonable to begin with?
66  template <typename T>
67  void check_ptr(const std::shared_ptr<T>& ptr) {
68  if (!ptr) throw std::runtime_error("Uninitialized accumulator accessed");
69  }
70 
71  } // detail::
72 
73  // TODO: merge with accumulator_wrapper, at least make common base ...
75  public:
76 
77  // default constructor
79 
80  // constructor from raw result
81  template<typename T> result_wrapper(T arg)
82  : m_variant(typename detail::add_base_wrapper_pointer<typename value_type<T>::type>::type(
83  new derived_result_wrapper<T>(arg))
84  )
85  {}
86 
87  // constructor from base_wrapper
88  template<typename T> result_wrapper(base_wrapper<T> * arg)
89  : m_variant(typename detail::add_base_wrapper_pointer<T>::type(arg))
90  {}
91 
92  // copy constructor
93  result_wrapper(result_wrapper const & rhs);
94 
95  // constructor from hdf5
97 
98  // operator=
99  result_wrapper & operator=(std::shared_ptr<result_wrapper> const & rhs);
100 
101  private:
102  // Visitors that need access to m_variant
103  struct assign_visitor;
104 
105  // get
106  private:
107  template<typename T> struct get_visitor: public boost::static_visitor<> {
108  template<typename X> void operator()(X const & /*arg*/) {
109  throw std::runtime_error(std::string("Cannot cast observable") + typeid(X).name() + " to base type: " + typeid(T).name() + ALPS_STACKTRACE);
110  }
111  void operator()(typename detail::add_base_wrapper_pointer<T>::type const & arg) { value = arg; }
112  typename detail::add_base_wrapper_pointer<T>::type value;
113  };
114  public:
115  template <typename T> base_wrapper<T> & get() {
116  get_visitor<T> visitor;
117  boost::apply_visitor(visitor, m_variant);
118  return *visitor.value;
119  }
120 
121  // extract
122  private:
123  template<typename A> struct extract_visitor: public boost::static_visitor<A*> {
124  template<typename T> A* operator()(T const & arg) { return &arg->template extract<A>(); }
125  };
126  public:
127  template <typename A> A & extract() {
128  extract_visitor<A> visitor;
129  return *boost::apply_visitor(visitor, m_variant);
130  }
131  template <typename A> A const & extract() const {
132  extract_visitor<A> visitor;
133  return *boost::apply_visitor(visitor, m_variant);
134  }
135 
136  // cast-to-other-result visitor
137  private:
139 
141  template<template<typename> class AFROM,
142  template<typename> class ATO>
143  struct cast_visitor: public boost::static_visitor<result_wrapper> {
144  template<typename T> result_wrapper operator()(T const & arg) {
146  typedef typename AFROM<value_type>::result_type raw_result_from_type;
147  typedef typename ATO<value_type>::result_type raw_result_to_type;
148 
149  const raw_result_from_type& from=arg->template extract<raw_result_from_type>();
150  const raw_result_to_type& to=dynamic_cast<const raw_result_to_type&>(from);
151  return result_wrapper(to);
152  }
153  };
154  public:
156 
169  template <template<typename> class AFROM, template<typename> class ATO>
171  cast_visitor<AFROM,ATO> visitor;
172  return boost::apply_visitor(visitor, m_variant);
173  }
174 
175  // count
176  boost::uint64_t count() const;
177 
178  // mean, error
179  #define ALPS_ACCUMULATOR_PROPERTY_PROXY(PROPERTY, TYPE) \
180  private: \
181  template<typename T> struct PROPERTY ## _visitor: public boost::static_visitor<T> { \
182  template<typename X> T apply(typename std::enable_if< \
183  detail::is_valid_argument<typename TYPE <X>::type, T>::value, X const & \
184  >::type arg) const { \
185  return arg. PROPERTY (); \
186  } \
187  template<typename X> T apply(typename std::enable_if<! \
188  detail::is_valid_argument<typename TYPE <X>::type, T>::value, X const & \
189  >::type /*arg*/) const { \
190  throw std::logic_error(std::string("cannot convert: ") \
191  + typeid(typename TYPE <X>::type).name() + " to " \
192  + typeid(T).name() + ALPS_STACKTRACE); \
193  } \
194  template<typename X> T operator()(X const & arg) const { \
195  return apply<typename X::element_type>(*arg); \
196  } \
197  }; \
198  public: \
199  template<typename T> typename TYPE <base_wrapper<T> >::type PROPERTY () const { \
200  PROPERTY ## _visitor<typename TYPE <base_wrapper<T> >::type> visitor; \
201  return boost::apply_visitor(visitor, m_variant); \
202  }
206  #undef ALPS_ACCUMULATOR_PROPERTY_PROXY
207 
208  // save
209  void save(hdf5::archive & ar) const;
210 
211  // load
212  void load(hdf5::archive & ar);
213 
214  // print
215  void print(std::ostream & os, bool terse=false) const;
216 
217  // transform(T F(T))
218  private:
219  template<typename T> struct transform_1_visitor: public boost::static_visitor<> {
220  transform_1_visitor(boost::function<T(T)> f) : op(f) {}
221  template<typename X> void apply(typename std::enable_if<
222  detail::is_valid_argument<T, typename value_type<X>::type>::value, X &
223  >::type arg) const {
224  arg.transform(op);
225  }
226  template<typename X> void apply(typename std::enable_if<!
227  detail::is_valid_argument<T, typename value_type<X>::type>::value, X &
228  >::type /*arg*/) const {
229  throw std::logic_error(std::string("cannot convert: ") + typeid(T).name() + " to " + typeid(typename value_type<X>::type).name() + ALPS_STACKTRACE);
230  }
231  template<typename X> void operator()(X & arg) const {
232  apply<typename X::element_type>(*arg);
233  }
234  boost::function<T(T)> op;
235  };
236  public:
237  template<typename T> result_wrapper transform(boost::function<T(T)> op) const {
238  result_wrapper clone(*this);
239  boost::apply_visitor(transform_1_visitor<T>(op), clone.m_variant);
240  return clone;
241  }
242  template<typename T> result_wrapper transform(T(*op)(T)) const {
243  return transform(boost::function<T(T)>(op));
244  }
245 
246  public:
247 
248  // unary plus
249  result_wrapper operator+ () const;
250 
251  // unary minus
252  result_wrapper operator- () const;
253 
254  // operators
255  // Naming conventions:
256  // Operation is `lhs_var AUGOP rhs_var`, where AUGOP is `+=` , `-=` etc.
257  // lhsvar contains a variant over LHSPT types
258  // rhsvar contains a variant over RHSPT types
259  // LHSPT: lhs (pointer) type, which is shared_ptr<LHSWT>
260  // LHSWT: lhs (base_wrapper<...>) type
261  // RHSPT: rhs (pointer) type, which is shared_ptr<RHSWT>
262  // RHSWT: rhs (base_wrapper<...>) type
263  #define ALPS_ACCUMULATOR_OPERATOR_PROXY(OPNAME, AUGOPNAME, AUGOP, FUN) \
264  private: \
265  struct FUN ## _self_visitor; \
266  public: \
267  \
268  result_wrapper & AUGOPNAME (result_wrapper const & rhs); \
269  \
270  result_wrapper & AUGOPNAME (long double arg); \
271  result_wrapper OPNAME (result_wrapper const & arg) const; \
272  \
273  result_wrapper OPNAME (long double arg) const;
274  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator+, operator+=, +=, add)
275  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator-, operator-=, -=, sub)
276  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator*, operator*=, *=, mul)
277  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator/, operator/=, /=, div)
278  #undef ALPS_ACCUMULATOR_OPERATOR_PROXY
279 
280  // inverse
281  result_wrapper inverse() const;
282 
283  result_wrapper sin () const;
284  result_wrapper cos () const;
285  result_wrapper tan () const;
286  result_wrapper sinh () const;
287  result_wrapper cosh () const;
288  result_wrapper tanh () const;
289  result_wrapper asin () const;
290  result_wrapper acos () const;
291  result_wrapper atan () const;
292  result_wrapper abs () const;
293  result_wrapper sqrt () const;
294  result_wrapper log () const;
295  result_wrapper sq () const;
296  result_wrapper cb () const;
297  result_wrapper cbrt () const;
298 
299  private:
300 
301  detail::variant_type m_variant;
302  };
303 
304  inline result_wrapper operator+(long double arg1, result_wrapper const & arg2) {
305  return arg2 + arg1;
306  }
307  inline result_wrapper operator-(long double arg1, result_wrapper const & arg2) {
308  return -arg2 + arg1;
309  }
310  inline result_wrapper operator*(long double arg1, result_wrapper const & arg2) {
311  return arg2 * arg1;
312  }
313  inline result_wrapper operator/(long double arg1, result_wrapper const & arg2) {
314  return arg2.inverse() * arg1;
315  }
316 
317  std::ostream & operator<<(std::ostream & os, const result_wrapper & arg);
318 
320  detail::printable_type short_print(const result_wrapper& arg);
321 
323  detail::printable_type full_print(const result_wrapper& arg);
324 
326  template <typename A> A & extract(result_wrapper & m) {
327  return m.extract<A>();
328  }
329 
331  template <typename A> const A & extract(const result_wrapper & m) {
332  return m.extract<A>();
333  }
334 
336 
349  template <typename AFROM, typename ATO>
351  const AFROM& raw_res_from=extract<AFROM>(res);
352  const ATO& raw_res_to=dynamic_cast<const ATO&>(raw_res_from);
353  return result_wrapper(raw_res_to);
354  }
355 
357 
370  template <template<typename> class AFROM,
371  template<typename> class ATO>
373  return res.cast<AFROM,ATO>();
374  }
375 
376  result_wrapper sin (result_wrapper const & arg);
377  result_wrapper cos (result_wrapper const & arg);
378  result_wrapper tan (result_wrapper const & arg);
379  result_wrapper sinh (result_wrapper const & arg);
380  result_wrapper cosh (result_wrapper const & arg);
381  result_wrapper tanh (result_wrapper const & arg);
382  result_wrapper asin (result_wrapper const & arg);
383  result_wrapper acos (result_wrapper const & arg);
384  result_wrapper atan (result_wrapper const & arg);
385  result_wrapper abs (result_wrapper const & arg);
386  result_wrapper sqrt (result_wrapper const & arg);
387  result_wrapper log (result_wrapper const & arg);
388  result_wrapper sq (result_wrapper const & arg);
389  result_wrapper cb (result_wrapper const & arg);
390  result_wrapper cbrt (result_wrapper const & arg);
391 
393  private:
394 
396  template <typename T>
397  static void check_nonempty_vector(const T&) {}
398 
400 
401  template <typename T>
402  static void check_nonempty_vector(const std::vector<T>& vec) {
403  if (vec.empty()) throw std::runtime_error("Zero-sized vector observables are not allowed");
404  }
405 
406  public:
409 
411  template<typename T> accumulator_wrapper(T arg)
412  : m_variant(typename detail::add_base_wrapper_pointer<typename value_type<T>::type>::type(
413  new derived_accumulator_wrapper<T>(arg))
414  )
415  {}
416 
420 
421  // constructor from hdf5
423 
424  // operator(T)
425  private:
426  template<typename T> struct call_1_visitor: public boost::static_visitor<> {
427  call_1_visitor(T const & v) : value(v) {}
428  template<typename X> void apply(typename std::enable_if<
429  detail::is_valid_argument<T, typename value_type<X>::type>::value, X &
430  >::type arg) const {
431  arg(value);
432  }
433  template<typename X> void apply(typename std::enable_if<!
434  detail::is_valid_argument<T, typename value_type<X>::type>::value, X &
435  >::type /*arg*/) const {
436  throw std::logic_error(std::string("cannot convert: ") + typeid(T).name() + " to " + typeid(typename value_type<X>::type).name() + ALPS_STACKTRACE);
437  }
438  template<typename X> void operator()(X & arg) const {
439  check_ptr(arg);
440  apply<typename X::element_type>(*arg);
441  }
442  T const & value;
443  };
444  public:
445  template<typename T> void operator()(T const & value) {
446  check_nonempty_vector(value);
447  boost::apply_visitor(call_1_visitor<T>(value), m_variant);
448  }
449  template<typename T> accumulator_wrapper & operator<<(T const & value) {
450  (*this)(value);
451  return (*this);
452  }
453 
455  void merge(const accumulator_wrapper& rhs_acc);
456 
458  accumulator_wrapper clone() const;
459 
461  accumulator_wrapper* new_clone() const;
462 
463  // operator=
464  accumulator_wrapper & operator=(std::shared_ptr<accumulator_wrapper> const & rhs);
465 
466  // count
467  boost::uint64_t count() const;
468 
469  private:
470  // Visitors that need access to m_variant
471  struct merge_visitor;
472  struct copy_visitor;
473  struct assign_visitor;
474 
475  // get
476  private:
477  template<typename T> struct get_visitor: public boost::static_visitor<> {
478  template<typename X> void operator()(X const & /*arg*/) {
479  throw std::runtime_error(std::string("Cannot cast observable") + typeid(X).name() + " to base type: " + typeid(T).name() + ALPS_STACKTRACE);
480  }
481  void operator()(typename detail::add_base_wrapper_pointer<T>::type const & arg) { value = arg; }
482  typename detail::add_base_wrapper_pointer<T>::type value;
483  };
484  public:
485  template <typename T> base_wrapper<T> & get() {
486  get_visitor<T> visitor;
487  boost::apply_visitor(visitor, m_variant);
488  check_ptr(visitor.value);
489  return *visitor.value;
490  }
491 
492  // extract
493  private:
494  template<typename A> struct extract_visitor: public boost::static_visitor<A*> {
495  template<typename T> A* operator()(T const & arg) { check_ptr(arg); return &arg->template extract<A>(); }
496  };
497  public:
498  template <typename A> A & extract() {
499  extract_visitor<A> visitor;
500  return *boost::apply_visitor(visitor, m_variant);
501  }
502 
503  // mean, error
504  #define ALPS_ACCUMULATOR_PROPERTY_PROXY(PROPERTY, TYPE) \
505  private: \
506  template<typename T> struct PROPERTY ## _visitor: public boost::static_visitor<T> { \
507  template<typename X> T apply(typename std::enable_if< \
508  detail::is_valid_argument<typename TYPE <X>::type, T>::value, X const & \
509  >::type arg) const { \
510  return arg. PROPERTY (); \
511  } \
512  template<typename X> T apply(typename std::enable_if<! \
513  detail::is_valid_argument<typename TYPE <X>::type, T>::value, X const & \
514  >::type /*arg*/) const { \
515  throw std::logic_error(std::string("cannot convert: ") \
516  + typeid(typename TYPE <X>::type).name() + " to " \
517  + typeid(T).name() + ALPS_STACKTRACE); \
518  } \
519  template<typename X> T operator()(X const & arg) const { \
520  check_ptr(arg); \
521  return apply<typename X::element_type>(*arg); \
522  } \
523  }; \
524  public: \
525  template<typename T> typename TYPE <base_wrapper<T> >::type PROPERTY () const { \
526  PROPERTY ## _visitor<typename TYPE <base_wrapper<T> >::type> visitor; \
527  return boost::apply_visitor(visitor, m_variant); \
528  }
531  #undef ALPS_ACCUMULATOR_PROPERTY_PROXY
532 
533  // save
534  void save(hdf5::archive & ar) const;
535  // load
536  void load(hdf5::archive & ar);
537 
538  // reset
539  void reset() const;
540 
541  // result
542  std::shared_ptr<result_wrapper> result() const;
543 
544  // print
545  void print(std::ostream & os, bool terse=false) const;
546 
547 #ifdef ALPS_HAVE_MPI
548  void collective_merge(alps::mpi::communicator const & comm, int root);
549 #endif
550 
551  private:
552 
553  detail::variant_type m_variant;
554  };
555 
556  std::ostream & operator<<(std::ostream & os, const accumulator_wrapper & arg);
557 
559  detail::printable_type short_print(const accumulator_wrapper& arg);
560 
562  detail::printable_type full_print(const accumulator_wrapper& arg);
563 
564  template <typename A> A & extract(accumulator_wrapper & m) {
565  return m.extract<A>();
566  }
567 
568  void reset(accumulator_wrapper & arg);
569 
572 
573  }
574 }
result_wrapper operator-(long double arg1, result_wrapper const &arg2)
result_wrapper cast() const
Cast to the result_wrapper containing another raw result type, or throw.
result_wrapper cbrt(result_wrapper const &arg)
accumulator_wrapper(T arg)
constructor from raw accumulator
result_wrapper operator*(long double arg1, result_wrapper const &arg2)
void load(archive &ar, std::string const &path, T &value, std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:309
result_wrapper cos(result_wrapper const &arg)
impl::wrapper_set< result_wrapper > result_set
result_wrapper(base_wrapper< T > *arg)
Definition: accumulator.hpp:88
result_wrapper transform(boost::function< T(T)> op) const
result_wrapper sqrt(result_wrapper const &arg)
result_wrapper cb(result_wrapper const &arg)
result_wrapper sq(result_wrapper const &arg)
result_wrapper operator+(long double arg1, result_wrapper const &arg2)
detail::printable_type short_print(const result_wrapper &arg)
Return an "ostream-able" object to print result in a terse format.
mean_result< T > transform(no_prop, const transformer< T > &tf, const InResult &in)
Definition: transform.hpp:27
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
F::result_type apply_visitor(F &visitor, dictionary::const_iterator it)
Const-access visitor to a value by an iterator.
Definition: dictionary.hpp:110
mean_type< T >::type mean(T const &arg)
Definition: mean.hpp:47
result_wrapper cast(const result_wrapper &res)
Cast to the result_wrapper containing another raw result type, or throw.
A & extract(result_wrapper &m)
Return the "raw result" of type A held in the result_wrapper m, or throw.
result_wrapper log(result_wrapper const &arg)
std::ostream & operator<<(std::ostream &os, const result_wrapper &arg)
result_wrapper operator/(long double arg1, result_wrapper const &arg2)
void reset(accumulator_wrapper &arg)
result_wrapper cast_raw(const result_wrapper &res)
Cast to the result_wrapper containing another raw result type, or throw.
detail::printable_type full_print(const result_wrapper &arg)
Return an "ostream-able" object to print result in a verbose format.
result_wrapper tanh(result_wrapper const &arg)
error_type< T >::type error(T const &arg)
Definition: error.hpp:47
impl::wrapper_set< accumulator_wrapper > accumulator_set
#define ALPS_ACCUMULATOR_PROPERTY_PROXY(PROPERTY, TYPE)
result_wrapper acos(result_wrapper const &arg)
std::ostream & print(std::ostream &s, const dict_value &dv, bool terse)
Definition: dict_value.cpp:186
#define ALPS_ACCUMULATOR_OPERATOR_PROXY(OPNAME, AUGOPNAME, AUGOP, FUN)
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
autocorrelation_type< T >::type autocorrelation(T const &arg)
result_wrapper sin(result_wrapper const &arg)
result_wrapper asin(result_wrapper const &arg)
traits< Acc >::result_type result(const Acc &acc)
Definition: util.hpp:53
result_wrapper tan(result_wrapper const &arg)
result_wrapper abs(result_wrapper const &arg)
result_wrapper sinh(result_wrapper const &arg)
std::vector< T > & merge(std::vector< T > &left, const std::vector< T > &right)
Vector merge.
accumulator_wrapper & operator<<(T const &value)
result_wrapper cosh(result_wrapper const &arg)
count_type< T >::type count(T const &arg)
Definition: count.hpp:39
result_wrapper atan(result_wrapper const &arg)
void save(archive &ar, std::string const &path, T const &value, std::vector< std::size_t >=std::vector< std::size_t >(), std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:292
result_wrapper transform(T(*op)(T)) const