Tomographer  v5.2
Tomographer C++ Framework Documentation
mhrwstatscollectors.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef TOMOGRAPHER_MHRWSTATSCOLLECTORS_H
29 #define TOMOGRAPHER_MHRWSTATSCOLLECTORS_H
30 
31 #include <cstddef>
32 
33 #include <limits>
34 #include <tuple>
35 #include <utility>
36 #include <type_traits>
37 #include <typeinfo>
38 
39 
42 #include <tomographer/tools/statusprovider.h>
43 #include <tomographer/histogram.h>
44 #include <tomographer/mhrw.h> // MHRWStatusReport
46 
57 namespace Tomographer {
58 
62 struct TOMOGRAPHER_EXPORT MHRWStatsCollectorNoResult {};
63 
64 
65 namespace tomo_internal {
66 
67 typedef MHRWStatsCollectorNoResult NoResult; // convenience alias
68 
69 template<typename MHRWStatsCollector, typename dummy = void>
70 struct multistatscoll_result_type_helper {
71  // static constexpr bool HasResultType = false;
72  typedef NoResult ResultType;
73  static inline ResultType getResult(const MHRWStatsCollector & ) { return NoResult(); }
74  static inline ResultType stealResult(MHRWStatsCollector & ) { return NoResult(); }
75 };
76 template<typename MHRWStatsCollector>
77 struct multistatscoll_result_type_helper<
78  MHRWStatsCollector,
79  // ignore specialization (SFINAE) if either ResultType is not defined or if ResultType is void
80  typename std::enable_if<
81  !std::is_same<typename MHRWStatsCollector::ResultType,void>::value,
82  void
83  >::type
84  >
85 {
86  // static constexpr bool HasResultType = true;
87  typedef typename MHRWStatsCollector::ResultType ResultType;
88  static inline ResultType getResult(const MHRWStatsCollector & s) { return s.getResult(); }
89  static inline ResultType stealResult(MHRWStatsCollector & s) { return s.stealResult(); }
90 };
91 
92 template<typename ResultType, typename... MHRWStatsCollectors>
93 struct multistatscoll_result_type_helper2 {
94  typedef std::tuple<MHRWStatsCollectors&...> TupleRefType;
95  typedef std::tuple<MHRWStatsCollectors...> TupleType;
96  template<typename T, int... Is>
97  static inline ResultType getResult(const TupleRefType & statscollectors, Tools::Sequence<T, Is...> )
98  {
99  return std::make_tuple(
100  multistatscoll_result_type_helper<typename std::tuple_element<Is, TupleType>::type>::getResult(
101  std::get<Is>(statscollectors)
102  ) ...
103  ) ;
104  }
105  template<typename T, int... Is>
106  static inline ResultType stealResult(TupleRefType & statscollectors, Tools::Sequence<T, Is...> )
107  {
108  return std::make_tuple(
109  std::move(
110  multistatscoll_result_type_helper<typename std::tuple_element<Is, TupleType>::type>::stealResult(
111  std::get<Is>(statscollectors)
112  )
113  ) ...
114  ) ;
115  }
116 };
117 
118 } // namespace tomo_internal
119 
120 
121 
156 template<typename... MHRWStatsCollectors>
157 class TOMOGRAPHER_EXPORT MultipleMHRWStatsCollectors
158 {
159 public:
160  typedef std::tuple<MHRWStatsCollectors&...> MHRWStatsCollectorsRefTupleType;
161  typedef std::tuple<MHRWStatsCollectors...> MHRWStatsCollectorsTupleType;
162 
164  static constexpr int NumStatColl = sizeof...(MHRWStatsCollectors);
165 
166 private:
167  MHRWStatsCollectorsRefTupleType statscollectors;
168 
169 public:
170 
171  MultipleMHRWStatsCollectors(MHRWStatsCollectors&... statscollectors_)
172  : statscollectors(statscollectors_...)
173  {
174  }
175 
178 
179  // method to get a particular stats collector
180  template<int I>
181  inline const typename std::tuple_element<I, MHRWStatsCollectorsTupleType>::type & getStatsCollector() const
182  {
183  return std::get<I>(statscollectors);
184  }
185 
187  ResultType;
188 
189  ResultType getResult() const
190  {
191  return tomo_internal::multistatscoll_result_type_helper2<ResultType, MHRWStatsCollectors...>::getResult(
192  statscollectors,
194  );
195  }
196  ResultType stealResult()
197  {
198  return tomo_internal::multistatscoll_result_type_helper2<ResultType, MHRWStatsCollectors...>::stealResult(
199  statscollectors,
201  );
202  }
203 
204 
205  // init() callback
206 
207  template<int I = 0>
208  inline typename std::enable_if<I < NumStatColl, void>::type init()
209  {
210  std::get<I>(statscollectors).init();
211  init<I+1>();
212  }
213  template<int I = 0>
214  inline typename std::enable_if<I == NumStatColl, void>::type init()
215  {
216  }
217 
218  // thermalizingDone() callback
219 
220  template<int I = 0>
221  inline typename std::enable_if<I < NumStatColl, void>::type thermalizingDone()
222  {
223  std::get<I>(statscollectors).thermalizingDone();
224  thermalizingDone<I+1>();
225  }
226  template<int I = 0>
227  inline typename std::enable_if<I == NumStatColl, void>::type thermalizingDone()
228  {
229  }
230 
231  // done() callback
232 
233  template<int I = 0>
234  inline typename std::enable_if<I < NumStatColl, void>::type done()
235  {
236  std::get<I>(statscollectors).done();
237  done<I+1>();
238  }
239  template<int I = 0>
240  inline typename std::enable_if<I == NumStatColl, void>::type done()
241  {
242  }
243 
244 
245  // rawMove() callback
246 
247  template<typename CountIntType, typename PointType, typename FnValueType, typename MHRandomWalk, int I = 0>
248  inline typename std::enable_if<I < NumStatColl, void>::type rawMove(
249  CountIntType k, bool is_thermalizing, bool is_live_iter, bool accepted,
250  double a, const PointType & newpt, FnValueType newptval,
251  const PointType & curpt, FnValueType curptval,
252  MHRandomWalk & rw
253  )
254  {
255  std::get<I>(statscollectors).rawMove(
256  k, is_thermalizing, is_live_iter, accepted, a,
257  newpt, newptval, curpt, curptval, rw
258  );
259  rawMove<CountIntType, PointType, FnValueType, MHRandomWalk, I+1>(
260  k, is_thermalizing, is_live_iter, accepted, a,
261  newpt, newptval, curpt, curptval, rw
262  );
263  }
264  template<typename CountIntType, typename PointType, typename FnValueType, typename MHRandomWalk, int I = 0>
265  inline typename std::enable_if<I == NumStatColl, void>::type rawMove(
266  CountIntType, bool, bool, bool, double, const PointType &, FnValueType,
267  const PointType &, FnValueType, MHRandomWalk &
268  )
269  {
270  }
271 
272 
273  // processSample() callback
274 
275  template<typename CountIntType, typename PointType, typename FnValueType, typename MHRandomWalk, int I = 0>
276  inline typename std::enable_if<I < NumStatColl, void>::type processSample(
277  CountIntType k, CountIntType n, const PointType & curpt, FnValueType curptval, MHRandomWalk & rw
278  )
279  {
280  std::get<I>(statscollectors).processSample(k, n, curpt, curptval, rw);
281  processSample<CountIntType, PointType, FnValueType, MHRandomWalk, I+1>(k, n, curpt, curptval, rw);
282  }
283 
284  template<typename CountIntType, typename PointType, typename FnValueType, typename MHRandomWalk, int I = 0>
285  inline typename std::enable_if<I == NumStatColl, void>::type processSample(
286  CountIntType, CountIntType, const PointType &, FnValueType, MHRandomWalk &
287  )
288  {
289  }
290 
291 };
292 
300 
301 
302 
308 template<typename... MHRWStatsCollectors>
309 inline MultipleMHRWStatsCollectors<MHRWStatsCollectors...>
310 mkMultipleMHRWStatsCollectors(MHRWStatsCollectors& ... mhrwstatscollectors)
311 {
312  return MultipleMHRWStatsCollectors<MHRWStatsCollectors...>(mhrwstatscollectors...) ;
313 }
314 
315 
316 
317 
318 
319 
320 // -----------------
321 
326 template<typename IterCountIntType_ = int>
328 {
329 public:
330  typedef IterCountIntType_ IterCountIntType;
331 
332 private:
333  Eigen::ArrayXi accept_buffer;
334  IterCountIntType pos;
335 
336 public:
337 
338  inline MHRWMovingAverageAcceptanceRatioStatsCollector(Eigen::Index num_samples_ = 2048)
339  : accept_buffer(Eigen::ArrayXi::Zero(num_samples_)), pos(0)
340  {
341  }
342 
343  inline Eigen::Index bufferSize() const {
344  return accept_buffer.size();
345  }
346 
348  inline double movingAverageAcceptanceRatio() const {
349  return (double)accept_buffer.count() / accept_buffer.size();
350  }
351 
353  inline bool hasMovingAverageAcceptanceRatio() const {
354  return ( pos >= accept_buffer.size() );
355  }
356 
357 
358  // init() callback
359 
360  inline void init()
361  {
362  }
363 
364  // thermalizingDone() callback
365  inline void thermalizingDone()
366  {
367  }
368 
369  // done() callback
370  inline void done()
371  {
372  }
373 
374 
375  // rawMove() callback
376 
377  template<typename CountIntType, typename PointType, typename FnValueType, typename PointType2, typename MHRandomWalk>
378  inline void rawMove(
379  CountIntType /*k*/, bool /*is_thermalizing*/, bool /*is_live_iter*/, bool accepted,
380  double /*a*/, PointType && /*newpt*/, FnValueType /*newptval*/,
381  PointType2 && /*curpt*/, FnValueType /*curptval*/,
382  MHRandomWalk && /* rw */
383  )
384  {
385  // Strategy: update the item in the array at position pos%num_samples, and increment
386  // pos. This way we remove the oldest samples and replace them by the new ones.
387 
388  accept_buffer[ pos % accept_buffer.size() ] = (int)accepted;
389  ++pos;
390  }
391 
392 
393  // processSample() callback
394 
395  template<typename CountIntType, typename PointType, typename FnValueType, typename MHRandomWalk>
396  inline void processSample(
397  CountIntType /*k*/, CountIntType /*n*/, PointType && /*curpt*/, FnValueType /*curptval*/, MHRandomWalk && /*rw*/
398  )
399  {
400  }
401 
402 };
403 
404 
405 
406 
407 // -----------------
408 
409 
410 
425 template<typename ValueCalculator_,
426  typename LoggerType = Logger::VacuumLogger,
427  typename HistogramType_ = Histogram<typename ValueCalculator_::ValueType>
428  >
429 class TOMOGRAPHER_EXPORT ValueHistogramMHRWStatsCollector
430  : public virtual Tools::NeedOwnOperatorNew<ValueCalculator_, HistogramType_>::ProviderType
431 {
432 public:
436  typedef ValueCalculator_ ValueCalculator;
437 
439  typedef typename ValueCalculator::ValueType ValueType;
440 
442  typedef HistogramType_ HistogramType;
443 
445  typedef HistogramType_ ResultType;
446 
448  typedef typename HistogramType::Params HistogramParams;
449 
450 private:
451 
453  HistogramType _histogram;
454 
459  ValueCalculator _vcalc;
460 
461  LoggerType & _logger;
462 
463 public:
465  ValueHistogramMHRWStatsCollector(HistogramParams histogram_params,
466  const ValueCalculator & vcalc,
467  LoggerType & logger)
468  : _histogram(histogram_params),
469  _vcalc(vcalc),
470  _logger(logger)
471  {
472  }
473 
475  inline const HistogramType & histogram() const
476  {
477  return _histogram;
478  }
479 
489  inline const ResultType & getResult() const
490  {
491  return _histogram;
492  }
493 
501  inline ResultType stealResult()
502  {
503  return std::move(_histogram);
504  }
505 
506  // stats collector part
507 
509  inline void init()
510  {
511  // reset our array
512  _histogram.reset();
513  }
515  inline void thermalizingDone()
516  {
517  }
525  template<bool PrintHistogram = true>
526  inline void done()
527  {
528  if (PrintHistogram) {
529  if (_logger.enabledFor(Logger::LONGDEBUG)) {
530  // _logger.longdebug("ValueHistogramMHRWStatsCollector", "done()");
531  _logger.longdebug("ValueHistogramMHRWStatsCollector",
532  "Done walking & collecting stats. Here's the histogram:\n"
533  + _histogram.prettyPrint());
534  }
535  }
536  }
537 
539  template<typename CountIntType, typename PointType, typename LLHValueType, typename MHRandomWalk>
540  void rawMove(CountIntType k, bool /*is_thermalizing*/, bool /*is_live_iter*/, bool /*accepted*/,
541  double /*a*/, const PointType & /*newpt*/, LLHValueType /*newptval*/,
542  const PointType & /*curpt*/, LLHValueType /*curptval*/, MHRandomWalk & /*mh*/)
543  {
544  _logger.longdebug("ValueHistogramMHRWStatsCollector", [&](std::ostream & stream) {
545  stream << "rawMove(): k=" << k;
546  });
547  }
548 
550  template<typename CountIntType, typename PointType, typename LLHValueType, typename MHRandomWalk>
551  Eigen::Index processSample(CountIntType k, CountIntType n, const PointType & curpt,
552  LLHValueType /*curptval*/, MHRandomWalk & /*mh*/)
553  {
554  ValueType val = _vcalc.getValue(curpt);
555 
556  _logger.longdebug("ValueHistogramMHRWStatsCollector", [&](std::ostream & stream) {
557  stream << "in processSample(): "
558  << "k=" << k << ", n=" << n << ", val=" << val
559  << " [with ValueType=" << typeid(ValueType).name() << "]" ;
560  });
561 
562  return _histogram.record(val);
563 
564  //_logger.longdebug("ValueHistogramMHRWStatsCollector", "processSample() finished");
565  }
566 
567 
568 };
569 
570 
571 
572 
578 template<typename HistogramType_, typename BinningAnalysisParamsType_>
580  : public virtual Tools::NeedOwnOperatorNew<
581  HistogramType_,
582  typename BinningAnalysisParamsType_::BinSumSqArray
583  >::ProviderType
584 {
585  typedef HistogramType_ HistogramType;
586  typedef typename HistogramType::Params HistogramParams;
587  typedef BinningAnalysisParamsType_ BinningAnalysisParamsType;
588 
591  : histogram(), error_levels(), converged_status()
592  {
593  }
594 
595  // can be moved
597  = default;
598 
599  // can be copied
602  )
603  : histogram(HistogramType::copy(copy.histogram)),
604  error_levels(copy.error_levels),
605  converged_status(copy.converged_status)
606  {
607  }
608 
610  template<typename EigenDerived1, typename EigenDerived2>
611  ValueHistogramWithBinningMHRWStatsCollectorResult(const HistogramType & histogram_,
612  const Eigen::DenseBase<EigenDerived1> & error_levels_,
613  const Eigen::DenseBase<EigenDerived2> & converged_status_)
614  : histogram(HistogramType::copy(histogram_)),
615  error_levels(error_levels_),
616  converged_status(converged_status_)
617  {
618  }
619 
621  template<typename BinningAnalysisType>
622  ValueHistogramWithBinningMHRWStatsCollectorResult(HistogramParams p, const BinningAnalysisType & b)
623  : histogram(p),
624  error_levels(b.numTrackValues(), b.numLevels()+1),
625  converged_status(Eigen::ArrayXi::Constant(b.numTrackValues(), BinningAnalysisType::UNKNOWN_CONVERGENCE))
626  {
627  tomographer_assert(converged_status.rows() == b.numTrackValues() && converged_status.cols() == 1);
628  }
629 
639  HistogramType histogram;
640 
643  typename BinningAnalysisParamsType::BinSumSqArray error_levels;
644 
648  Eigen::ArrayXi converged_status;
649 
652  {
654  }
655 
656 
658  inline void dumpConvergenceAnalysis(std::ostream & stream) const
659  {
660  for (int k = 0; k < converged_status.size(); ++k) {
661  stream << "\tval[" << std::setw(3) << k << "] = "
662  << std::setw(12) << histogram.bins(k)
663  << " +- " << std::setw(12) << histogram.delta(k);
664  if (converged_status(k) == BINNING_CONVERGED) {
665  stream << " [CONVERGED]";
666  } else if (converged_status(k) == BINNING_NOT_CONVERGED) {
667  stream << " [NOT CONVERGED]";
668  } else if (converged_status(k) == BINNING_UNKNOWN_CONVERGENCE) {
669  stream << " [UNKNOWN]";
670  } else {
671  stream << " [INVALID CONVERGENCE STATUS: " << converged_status(k) << "]";
672  }
673  stream << "\n";
674  }
675  }
676 
679  {
681  dumpConvergenceAnalysis(ss);
682  return ss.str();
683  }
684 
685 };
686 
687 
688 
689 
697 template<typename ValueCalculator_,
698  typename CountIntType_ = int,
699  typename CountRealAvgType_ = double,
700  int NumTrackValues_ = Eigen::Dynamic,
701  int NumLevels_ = Eigen::Dynamic
702  >
704 {
707  typedef ValueCalculator_ ValueCalculator;
709  typedef CountIntType_ CountIntType;
711  typedef CountRealAvgType_ CountRealAvgType;
712 
714  static constexpr int NumTrackValues = NumTrackValues_;
716  static constexpr int NumLevels = NumLevels_;
717 
719  typedef typename ValueCalculator::ValueType ValueType;
720 
722  typedef BinningAnalysisParams<ValueType,NumTrackValues,NumLevels,false/*StoreBinSums*/,CountIntType>
724 
738 
742 
743 };
744 
752 template<typename Params,
753  typename LoggerType_ = Logger::VacuumLogger
754  >
756  : public virtual Tools::NeedOwnOperatorNew<ValueHistogramMHRWStatsCollector<
757  typename Params::ValueCalculator,
758  LoggerType_,
759  typename Params::BaseHistogramType
760  >,
761  BinningAnalysis<typename Params::BinningAnalysisParamsType, LoggerType_>,
762  typename Params::Result
763  >::ProviderType
764 {
765 public:
766 
768  typedef typename Params::ValueCalculator ValueCalculator;
770  typedef typename Params::CountIntType CountIntType;
772  typedef typename Params::CountRealAvgType CountRealAvgType;
773 
775  typedef LoggerType_ LoggerType;
776 
778  typedef typename Params::BaseHistogramType BaseHistogramType;
780  typedef typename Params::HistogramParams HistogramParams;
781 
783  typedef typename Params::ValueType ValueType;
784 
786  typedef typename Params::BinningAnalysisParamsType BinningAnalysisParamsType;
789 
791  static constexpr int NumTrackValuesCTime = Params::NumTrackValues;
793  static constexpr int NumLevelsCTime = Params::NumLevels;
794 
796  typedef typename Params::Result ResultType;
797 
802  ValueCalculator,
803  LoggerType,
804  BaseHistogramType
806 
807 private:
808 
809  ValueHistogramMHRWStatsCollectorType value_histogram;
810 
811  BinningAnalysisType binning_analysis;
812 
813  LoggerType & logger;
814 
815  ResultType result;
816 
817 public:
818 
819  ValueHistogramWithBinningMHRWStatsCollector(HistogramParams histogram_params,
820  const ValueCalculator & vcalc,
821  int num_levels,
822  LoggerType & logger_)
823  : value_histogram(histogram_params, vcalc, logger_),
824  binning_analysis((int)histogram_params.num_bins, num_levels, logger_),
825  logger(logger_),
826  result(histogram_params, binning_analysis)
827  {
828  logger.longdebug("ValueHistogramWithBinningMHRWStatsCollector", "constructor()");
829  }
830 
832  inline const BaseHistogramType & histogram() const
833  {
834  return value_histogram.histogram();
835  }
836 
837  inline const BinningAnalysisType & getBinningAnalysis() const
838  {
839  return binning_analysis;
840  }
841 
848  inline const ResultType & getResult() const
849  {
850  return result;
851  }
852 
857  {
858  const BaseHistogramType & hist = histogram();
859  return hist.bins.template cast<CountRealAvgType>() /
860  (CountRealAvgType)(hist.bins.sum() + hist.off_chart);
861  }
862 
873  inline ResultType stealResult()
874  {
875  return std::move(result);
876  }
877 
878  // stats collector part
879 
881  inline void init()
882  {
883  value_histogram.init();
884  }
886  inline void thermalizingDone()
887  {
888  value_histogram.thermalizingDone();
889  }
891  inline void done()
892  {
893  logger.longdebug("ValueHistogramWithBinningMHRWStatsCollector::done()", "finishing up ...");
894 
895  value_histogram.template done<false>();
896 
897  //
898  // Determine the error bars from the binning analysis. Remember, the binning analysis was
899  // applied to each of the indicator functions "chi(value) = (value in bin # i) ? 1 : 0"
900  //
901  // The total number of samples is simply h.bins.sum()+h.off_chart; this is the relevant
902  // coefficient to calculate the bin means needed by binning_analysis.calcErrorLevels(). Indeed,
903  // in this way we really get the averaged observed value of each indicator function for each
904  // value interval.
905  //
906  const BaseHistogramType & h = value_histogram.histogram();
907  result.histogram.params = h.params;
908  CountRealAvgType numsamples = h.bins.sum() + h.off_chart;
909  result.histogram.bins = h.bins.template cast<CountRealAvgType>() / numsamples;
910  result.error_levels = binning_analysis.calcErrorLevels(result.histogram.bins);
911  result.histogram.delta = result.error_levels.col(binning_analysis.numLevels()).template cast<CountRealAvgType>();
912  result.histogram.off_chart = h.off_chart / numsamples;
913 
914  result.converged_status = binning_analysis.determineErrorConvergence(result.error_levels);
915 
916  logger.debug("ValueHistogramWithBinningMHRWStatsCollector", [&,this](std::ostream & str) {
917  str << "Binning analysis: bin sqmeans at different binning levels are:\n"
918  << binning_analysis.getBinSqmeans() << "\n"
919  << "\t-> so the error bars at different binning levels are:\n"
920  << result.error_levels << "\n"
921  << "\t-> convergence analysis: \n";
922  result.dumpConvergenceAnalysis(str);
923  str << "\t... and just for you, here is the final histogram:\n" << result.histogram.prettyPrint() << "\n";
924  });
925  }
926 
928  template<typename CountIntType2, typename PointType, typename LLHValueType, typename MHRandomWalk>
929  inline void rawMove(CountIntType2 k, bool is_thermalizing, bool is_live_iter, bool accepted,
930  double a, const PointType & newpt, LLHValueType newptval,
931  const PointType & curpt, LLHValueType curptval, MHRandomWalk & mh)
932  {
933  value_histogram.rawMove(k, is_thermalizing, is_live_iter, accepted, a, newpt, newptval, curpt, curptval, mh);
934  }
935 
937  template<typename CountIntType2, typename PointType, typename LLHValueType, typename MHRandomWalk>
938  inline void processSample(CountIntType2 k, CountIntType2 n, const PointType & curpt,
939  LLHValueType curptval, MHRandomWalk & mh)
940  {
941  Eigen::Index histindex = value_histogram.processSample(k, n, curpt, curptval, mh);
942  binning_analysis.processNewValues(
944  histindex,
945  value_histogram.histogram().numBins()
946  )
947  );
948  }
949 
950 };
951 
952 
956 template<typename ValueCalculator_, typename LoggerType = Logger::VacuumLogger,
957  typename HistogramType_ = Histogram<typename ValueCalculator_::ValueType> >
958 inline
961  typename HistogramType_::Params hist_params,
962  ValueCalculator_ valcalc,
963  LoggerType & logger
964  )
965 {
967  std::move(hist_params),
968  std::move(valcalc),
969  logger
970  ) ;
971 }
972 
973 
977 template<typename ValueCalculator_, typename CountIntType_ = int,
978  typename CountRealAvgType_ = double, int NumTrackValues_ = Eigen::Dynamic,
979  int NumLevels_ = Eigen::Dynamic,
980  typename LoggerType = Tomographer::Logger::VacuumLogger>
981 inline
983  ValueHistogramWithBinningMHRWStatsCollectorParams<ValueCalculator_, CountIntType_,
984  CountRealAvgType_, NumTrackValues_,
985  NumLevels_>,
986  LoggerType
987  >
990  ValueCalculator_ valcalc,
991  int num_binning_levels,
992  LoggerType & logger
993  )
994 {
995  return
997  ValueHistogramWithBinningMHRWStatsCollectorParams<ValueCalculator_, CountIntType_,
998  CountRealAvgType_, NumTrackValues_,
999  NumLevels_>,
1000  LoggerType
1001  >(std::move(hist_params), std::move(valcalc), num_binning_levels, logger) ;
1002 }
1003 
1004 
1005 
1009 template<typename MHRWParamsType_>
1010 class TOMOGRAPHER_EXPORT PredStatusReportMHRWStatsCollector
1011 {
1012 public:
1013  typedef MHRWParamsType_ MHRWParamsType;
1015 
1016 private:
1017  std::function<bool()> pred_fn;
1019 
1020 public:
1021  template<typename PredicateFn, typename SendStatusFn>
1022  PredStatusReportMHRWStatsCollector(PredicateFn && pred_fn_, SendStatusFn && send_status_fn_)
1023  : pred_fn(pred_fn_), send_status_fn(send_status_fn_)
1024  { }
1025 
1026  inline void init() { }
1027  inline void thermalizingDone() { }
1028  inline void done() { }
1029 
1030  template<typename IterCountIntType, typename PointType, typename FnValueType, typename MHRandomWalk>
1031  inline void rawMove(
1032  IterCountIntType k, bool is_thermalizing, bool, bool, double, const PointType &, FnValueType,
1033  const PointType &, FnValueType, MHRandomWalk & rw
1034  )
1035  {
1036  // see if we should provide a status report
1037  // fprintf(stderr, "StatusReportCheck::rawMove(): testing for status report requested!\n");
1038  // only check once per sweep, to speed up things
1039  if ((k % rw.nSweep() == 0) && pred_fn()) {
1040  send_status_fn(
1041  MHRWStatusReportType::createFromRandWalkStatInfo(k, is_thermalizing, rw,
1042  rw.statsCollector(),
1043  rw.mhrwController())
1044  );
1045  }
1046  // fprintf(stderr, "StatusReportCheck::rawMove(): done\n");
1047  }
1048 
1049  template<typename IterCountIntType, typename PointType, typename FnValueType, typename MHRandomWalk>
1050  inline void processSample(IterCountIntType, IterCountIntType, PointType&&, FnValueType, MHRandomWalk &)
1051  {
1052  }
1053 };
1054 
1055 
1059 template<typename MHRWParamsType_, typename ClockType_ =
1060  // exception for gcc/g++ 4.6, which doesn't have steady_clock but has monotonic_clock instead
1061 #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && !defined(__clang__)
1062  std::chrono::monotonic_clock
1063 #else
1065 #endif
1066  >
1068 {
1069 public:
1070  typedef MHRWParamsType_ MHRWParamsType;
1072 
1073  typedef ClockType_ ClockType;
1074  typedef typename ClockType::time_point TimePoint;
1075  typedef typename ClockType::duration DurationType;
1076 
1077 private:
1078  TimePoint last_status_report;
1079  DurationType interval;
1081 
1082 public:
1083  template<typename DurationInit, typename SendStatusFn>
1084  PeriodicStatusReportMHRWStatsCollector(DurationInit && interval_, SendStatusFn && send_status_fn_)
1085  : interval(interval_), send_status_fn(send_status_fn_)
1086  { }
1087 
1088  inline void init() { }
1089  inline void thermalizingDone() { }
1090  inline void done() { }
1091 
1092  template<typename IterCountIntType, typename PointType, typename FnValueType, typename MHRandomWalk>
1093  inline void rawMove(
1094  IterCountIntType k, bool is_thermalizing, bool, bool, double, const PointType &, FnValueType,
1095  const PointType &, FnValueType, MHRandomWalk & rw
1096  )
1097  {
1098  // only check once per sweep, to speed up things
1099  if ((k % rw.nSweep() == 0)) {
1100 
1101  auto now = ClockType::now();
1102 
1103  if ( interval.count() > 0 && (now - (last_status_report + interval)).count() > 0 ) {
1104  // send in a status report
1105  send_status_fn(
1106  MHRWStatusReportType::createFromRandWalkStatInfo(k, is_thermalizing, rw,
1107  rw.statsCollector(),
1108  rw.mhrwController())
1109  );
1110  last_status_report = now;
1111  }
1112 
1113  }
1114  // fprintf(stderr, "StatusReportCheck::rawMove(): done\n");
1115  }
1116 
1117  template<typename IterCountIntType, typename PointType, typename FnValueType, typename MHRandomWalk>
1118  inline void processSample(IterCountIntType, IterCountIntType, PointType&&, FnValueType, MHRandomWalk &)
1119  {
1120  }
1121 };
1122 
1123 
1124 
1125 
1126 
1127 
1128 
1129 
1130 
1131 //
1132 // Specialize Tomographer::Tools::StatusProvider for our stats collector classes
1133 //
1134 
1135 
1136 namespace Tools {
1137 
1141 template<typename... Args>
1142 struct TOMOGRAPHER_EXPORT StatusProvider<MultipleMHRWStatsCollectors<Args... > >
1143 {
1146 
1147  static constexpr int NumStatColl = MHRWStatsCollector::NumStatColl;
1148 
1149  static constexpr bool CanProvideStatusLine = true;
1150 
1151  template<int I = 0, typename std::enable_if<(I < NumStatColl), bool>::type dummy = true>
1152  static inline std::string getStatusLine(const MHRWStatsCollector * stats)
1153  {
1154  typedef typename std::tuple_element<I, typename MHRWStatsCollector::MHRWStatsCollectorsTupleType>::type
1155  ThisStatsCollector;
1156  return
1158  ? StatusQuery<ThisStatsCollector>::getStatusLine(& stats->template getStatsCollector<I>())
1159  : std::string()),
1160  getStatusLine<I+1>(stats) );
1161  };
1162 
1163  template<int I = 0, typename std::enable_if<(I == NumStatColl), bool>::type dummy = true>
1164  static inline std::string getStatusLine(const MHRWStatsCollector * stats)
1165  {
1166  (void)stats;
1167  return std::string();
1168  }
1169 
1170 private:
1171  static inline std::string _joinnl(std::string a, std::string b) {
1172  if (a.size() && b.size()) {
1173  return std::move(a) + "\n" + std::move(b);
1174  }
1175  return std::move(a) + std::move(b); // one of these guys is empty
1176  }
1177 };
1178 // static members:
1179 template<typename... Args>
1180 constexpr int StatusProvider<MultipleMHRWStatsCollectors<Args... > >::NumStatColl;
1181 template<typename... Args>
1182 constexpr bool StatusProvider<MultipleMHRWStatsCollectors<Args... > >::CanProvideStatusLine;
1183 
1184 
1185 
1189 template<typename ValueCalculator_,
1190  typename LoggerType_,
1191  typename HistogramType_
1192  >
1193 struct TOMOGRAPHER_EXPORT StatusProvider<ValueHistogramMHRWStatsCollector<ValueCalculator_, LoggerType_, HistogramType_> >
1194 {
1196 
1197  static constexpr bool CanProvideStatusLine = true;
1198 
1199  static inline std::string getStatusLine(const MHRWStatsCollector * stats)
1200  {
1201  const int maxbarwidth = 50;
1202 
1203  typedef typename MHRWStatsCollector::HistogramType HistogramType;
1204 
1205  return "Histogram: " + histogramShortBar<HistogramType>(stats->histogram(), true, maxbarwidth);
1206  }
1207 };
1208 // static members:
1209 template<typename ValueCalculator_,
1210  typename LoggerType_,
1211  typename HistogramType_
1212  >
1213 constexpr bool
1215 
1216 
1220 template<typename Params_,
1221  typename LoggerType_
1222  >
1223 struct TOMOGRAPHER_EXPORT StatusProvider<ValueHistogramWithBinningMHRWStatsCollector<Params_, LoggerType_> >
1224 {
1226 
1227  static constexpr bool CanProvideStatusLine = true;
1228 
1229  static inline std::string getStatusLine(const MHRWStatsCollector * stats)
1230  {
1231  const int maxbarwidth = 50;
1232 
1233  typedef typename MHRWStatsCollector::BaseHistogramType BaseHistogramType;
1234  const BaseHistogramType & histogram = stats->histogram();
1235 
1236  // calculate the error bars at different levels, to determine convergence status.
1237  //typedef typename MHRWStatsCollector::BinningAnalysisType BinningAnalysisType;
1238  //typedef typename MHRWStatsCollector::CountRealAvgType CountRealAvgType;
1239  //typedef typename BinningAnalysisType::ValueType ValueType;
1240  const auto& binning_analysis = stats->getBinningAnalysis();
1241  const auto binmeans = stats->binMeans();
1242 
1243  auto error_levels = binning_analysis.calcErrorLevels(binmeans);
1244  auto conv_status = binning_analysis.determineErrorConvergence(error_levels);
1245 
1246  auto conv_summary = BinningErrorBarConvergenceSummary::fromConvergedStatus(conv_status);
1247 
1248  return histogramShortBar<BaseHistogramType>(histogram, true, maxbarwidth)
1249  + Tools::fmts(" err(cnvg/?/x): %d/%d/%d",
1250  (int)conv_summary.n_converged, (int)conv_summary.n_unknown,
1251  (int)conv_summary.n_not_converged);
1252  }
1253 };
1254 // static members:
1255 template<typename Params_,
1256  typename LoggerType_
1257  >
1258 constexpr bool
1260 
1261 
1265 template<typename CountIntType_>
1266 struct TOMOGRAPHER_EXPORT StatusProvider<MHRWMovingAverageAcceptanceRatioStatsCollector<CountIntType_> >
1267 {
1268  static constexpr bool CanProvideStatusLine = true;
1269 
1270  static inline std::string getStatusLine(const MHRWMovingAverageAcceptanceRatioStatsCollector<CountIntType_> * obj)
1271  {
1272  if (obj->hasMovingAverageAcceptanceRatio()) {
1273  return Tools::fmts("acceptance ratio = %.2g (over last %d iter)",
1274  (double)obj->movingAverageAcceptanceRatio(),
1275  (int)obj->bufferSize());
1276  }
1277  return std::string();
1278  }
1279 };
1280 
1281 
1282 
1283 } // namespace Tools
1284 
1285 } // namespace Tomographer
1286 
1287 
1288 
1289 #endif
A StatsCollector which builds a histogram of values calculated with a ValueCalculator for each data s...
A Metropolis-Hastings Random Walk.
Definition: mhrw.h:602
HistogramType histogram
Histogram, already with error bars.
It is unknown whether the error bar has converged or not.
Definition: mhrw_bin_err.h:79
auto canonicalBasisVec(IndexType k, IndexType size) -> const Eigen::CwiseNullaryOp< tomo_internal::can_basis_vec_generator< typename Eigen::internal::traits< Der >::Scalar, IndexType >, Der >
Expression for the k-th canonical basis vector of given dimension.
Definition: eigenutil.h:213
Eigen::Array< CountRealAvgType, Eigen::Dynamic, 1 > binMeans() const
Get the current bin means collected so far.
static BinningErrorBarConvergenceSummary fromConvergedStatus(const Eigen::Ref< const Eigen::ArrayXi > &converged_status)
Construct a summary object from a list of converged status obtained from BinningAnalysis::determineEr...
Definition: mhrw_bin_err.h:131
Params::BaseHistogramType BaseHistogramType
See ValueHistogramWithBinningMHRWStatsCollectorParams::BaseHistogramType .
const MHRWStatsCollector & statsCollector() const
Access the stats collector.
Definition: mhrw.h:725
void done()
Finalize the data collection. Part of the MHRWStatsCollector Interface.
BinningAnalysis< BinningAnalysisParamsType, LoggerType > BinningAnalysisType
The corresponding BinningAnalysis type for this value histogram stats collector.
auto getBinSqmeans() const
Get the raw average of the squared values observed, for each binning level.
Definition: mhrw_bin_err.h:685
The parameters of a Histogram.
Definition: histogram.h:67
void done()
Part of the MHRWStatsCollector Interface.
Base namespace for the Tomographer project.
Definition: densellh.h:45
CountRealAvgType_ CountRealAvgType
Type used to store the averages of the histogram bins.
ValueHistogramMHRWStatsCollector(HistogramParams histogram_params, const ValueCalculator &vcalc, LoggerType &logger)
Simple constructor, initializes with the given values.
const BaseHistogramType & histogram() const
Get the histogram data collected so far. See BaseHistogramType .
MultipleMHRWStatsCollectors< MHRWStatsCollectors... > mkMultipleMHRWStatsCollectors(MHRWStatsCollectors &... mhrwstatscollectors)
Convenience function to create a MultipleMHRWStatsCollector (using template argument deduction) ...
ValueCalculator::ValueType ValueType
The type to use to represent a calculated distance.
HistogramWithErrorBars< typename ValueCalculator::ValueType, CountRealAvgType > HistogramType
The Final Histogram Type (with error bars).
The error bar appears to have converged.
Definition: mhrw_bin_err.h:81
ValueHistogramMHRWStatsCollector< ValueCalculator_, LoggerType, HistogramType_ > mkValueHistogramMHRWStatsCollector(typename HistogramType_::Params hist_params, ValueCalculator_ valcalc, LoggerType &logger)
Helper to easily instantiate a ValueHistogramMHRWStatsCollector.
Eigen::ArrayXi converged_status
Information of convergence status of the error bars (see e.g. BINNING_CONVERGED)
Group template parameters for BinningAnalysis.
Definition: mhrw_bin_err.h:212
Eigen::ArrayXi determineErrorConvergence(const Eigen::Ref< const BinSumSqArray > &error_levels) const
Attempt to determine if the error bars have converged.
Definition: mhrw_bin_err.h:836
Result type of a ValueHistogramWithBinningMHRWStatsCollector.
HistogramType::Params HistogramParams
The corresponding histogram params type.
ValueHistogramWithBinningMHRWStatsCollectorResult(HistogramParams p, const BinningAnalysisType &b)
Constructor which initializes the fields from the histogram and binning analysis type.
Stores a histogram along with error bars.
Definition: histogram.h:537
Params::HistogramParams HistogramParams
See ValueHistogramWithBinningMHRWStatsCollectorParams::HistogramParams .
void processNewValues(const Eigen::DenseBase< Derived > &vals)
Process new raw samples.
Definition: mhrw_bin_err.h:562
Provide appropriate operator new() definitions for a structure which has a member of the given stored...
ValueHistogramWithBinningMHRWStatsCollectorResult(const HistogramType &histogram_, const Eigen::DenseBase< EigenDerived1 > &error_levels_, const Eigen::DenseBase< EigenDerived2 > &converged_status_)
Simple constructor with direct initialization of fields.
ValueCalculator_ ValueCalculator
The type which calculates the interesting value. Should be of type interface ValueCalculator Interfac...
const Tools::StaticOrDynamic< int,(NumLevelsCTime==Eigen::Dynamic), NumLevelsCTime > numLevels
The number of levels in the binning analysis.
Definition: mhrw_bin_err.h:428
void thermalizingDone()
Part of the MHRWStatsCollector Interface. No-op.
Logger that discards all messages.
Definition: loggers.h:1149
T make_tuple(T... args)
bool hasMovingAverageAcceptanceRatio() const
Returns true after enough samples have been collected to fill the internal buffer.
BinningErrorBarConvergenceSummary errorBarConvergenceSummary() const
A summary of the convergence status of the binning error bars.
void rawMove(CountIntType2 k, bool is_thermalizing, bool is_live_iter, bool accepted, double a, const PointType &newpt, LLHValueType newptval, const PointType &curpt, LLHValueType curptval, MHRandomWalk &mh)
Part of the MHRWStatsCollector Interface. No-op.
A "stats collector" which produces status reports whenever a predicate evaluates to true...
HistogramType::Params HistogramParams
Structure which holds the parameters of the histogram we&#39;re recording.
const MHRWController & mhrwController() const
Access the random walk controller.
Definition: mhrw.h:728
T setw(T... args)
Query status from different objects.
STL class.
HistogramType_ ResultType
Required for compliance with Resultable Interface type.
const ResultType & getResult() const
Get the histogram data collected. This method is needed for Resultable Interface compliance.
Traits-like class for ValueHistogramWithBinningMHRWStatsCollector.
double movingAverageAcceptanceRatio() const
Returns the average acceptance ratio as stored in the buffer.
An empty struct used as a ResultType in MultipleMHRWStatsCollector for stats collectors which don&#39;t r...
Collect a histogram of values from a MH random walk, with binning analysis.
BinSumSqArray calcErrorLevels(const Eigen::ArrayBase< Derived > &means) const
Calculate the error bars of samples at different binning levels.
Definition: mhrw_bin_err.h:735
const HistogramType & histogram() const
Get the histogram data collected so far. See HistogramType.
Params::ValueType ValueType
See ValueHistogramWithBinningMHRWStatsCollectorParams::ValueType .
Params::BinningAnalysisParamsType BinningAnalysisParamsType
See ValueHistogramWithBinningMHRWStatsCollectorParams::BinningAnalysisParamsType .
Params::ValueCalculator ValueCalculator
See ValueHistogramWithBinningMHRWStatsCollectorParams::ValueCalculator .
void thermalizingDone()
Part of the MHRWStatsCollector Interface. No-op.
Stores a histogram.
Definition: histogram.h:213
void rawMove(CountIntType k, bool, bool, bool, double, const PointType &, LLHValueType, const PointType &, LLHValueType, MHRandomWalk &)
Part of the MHRWStatsCollector Interface. No-op.
ResultType stealResult()
Retrieve the collected histogram data, in compliance with Resultable Interface compliance.
ValueHistogramWithBinningMHRWStatsCollectorResult< HistogramType, BinningAnalysisParamsType > Result
Result type of the corresponding ValueHistogramWithBinningMHRWStatsCollector.
T str(T... args)
Params::CountRealAvgType CountRealAvgType
See ValueHistogramWithBinningMHRWStatsCollectorParams::CountRealAvgType .
A "stats collector" which produces status reports periodically.
Some C++ utilities, with a tad of C++11 tricks.
T move(T... args)
void dumpConvergenceAnalysis(std::ostream &stream) const
Dump values, error bars and convergence status in verbose, debug-human-readable form into ostream...
HistogramType_ HistogramType
The type of the histogram. Usually a Histogram with ValueType range type.
CountIntType nSweep() const
Number of iterations in a sweep.
Definition: mhrw.h:738
The error bar appears NOT to have converged.
Definition: mhrw_bin_err.h:83
T size(T... args)
Status Report structure representing the status of a MHRandomWalk.
Definition: mhrw.h:1099
void init()
Part of the MHRWStatsCollector Interface. Initializes the histogram to zeros.
std::string fmts(const char *fmt,...)
printf- format to a std::string
Definition: fmt.h:128
Template, specializable class to provide status reports for different objects.
std::string dumpConvergenceAnalysis() const
Dump values, error bars and convergence status in verbose, debug-human-readable form as string...
Params::CountIntType CountIntType
See ValueHistogramWithBinningMHRWStatsCollectorParams::CountIntType .
BinningAnalysisParams< ValueType, NumTrackValues, NumLevels, false, CountIntType > BinningAnalysisParamsType
The relevant BinningAnalysis parameters for us.
Brief summary of convergence of error bars from a binning analysis.
Definition: mhrw_bin_err.h:107
ValueCalculator_ ValueCalculator
The type of the ValueCalculator Interface which calculates the value of which we&#39;re collecting a hist...
ResultType stealResult()
Retrieve the final histogram data, in compliance with Resultable Interface compliance.
void processSample(CountIntType2 k, CountIntType2 n, const PointType &curpt, LLHValueType curptval, MHRandomWalk &mh)
Part of the MHRWStatsCollector Interface. Records the sample in the histogram.
LoggerType_ LoggerType
Somewhere where this object may log what it&#39;s doing.
ValueHistogramWithBinningMHRWStatsCollectorResult()
Simple default constructor (e.g. to use as std::vector<Result>).
ValueHistogramWithBinningMHRWStatsCollector< ValueHistogramWithBinningMHRWStatsCollectorParams< ValueCalculator_, CountIntType_, CountRealAvgType_, NumTrackValues_, NumLevels_ >, LoggerType > mkValueHistogramWithBinningMHRWStatsCollector(HistogramParams< typename ValueCalculator_::ValueType > hist_params, ValueCalculator_ valcalc, int num_binning_levels, LoggerType &logger)
Helper to easily instantiate a ValueHistogramWithBinningMHRWStatsCollector.
Definitions for Histogram Types.
Long Debug logging level.
Definition: loggers.h:122
Histogram< typename ValueCalculator::ValueType, CountIntType > BaseHistogramType
The Base Histogram Type.
Params::Result ResultType
See ValueHistogramWithBinningMHRWStatsCollectorParams::Result .
Routines for performing a Metropolis-Hastings random walk.
Binning Analysis in a Metropolis-Hastings random walk.
STL class.
void init()
Part of the MHRWStatsCollector Interface. Initializes the histogram to zeros.
const ResultType & getResult() const
Get the final histogram data. This method is needed for Resultable Interface compliance.
#define tomographer_assert(...)
Assertion test macro.
Definition: cxxdefs.h:84
BinningAnalysisParamsType::BinSumSqArray error_levels
Detailed error bars for all binning levels.
ValueHistogramMHRWStatsCollector< ValueCalculator, LoggerType, BaseHistogramType > ValueHistogramMHRWStatsCollectorType
This is the natural ValueHistogramMHRWStatsCollector type on which we&#39;re adding error bars...
Utilities for logging messages.
ValueCalculator::ValueType ValueType
The type of a value calculated by the ValueCalculator Interface.
A simple MHRWStatsCollector interface which combines several stats collectors.
Eigen::Index processSample(CountIntType k, CountIntType n, const PointType &curpt, LLHValueType, MHRandomWalk &)
Part of the MHRWStatsCollector Interface. Records the sample in the histogram.
MultipleMHRWStatsCollectors TrivialMHRWStatsCollector
Trivial, NO-OP stats collector.
CountIntType_ CountIntType
Type used to count the number of hits in each bin.