hops
IsConstantChain.hpp
Go to the documentation of this file.
1 #ifndef ISCONSTANTCHAIN_HPP
2 #define ISCONSTANTCHAIN_HPP
3 
4 #include <stdexcept>
5 #include <vector>
6 #include <cmath>
7 #include <cassert>
8 #include <memory>
9 #include <limits>
10 
11 namespace hops {
12  // taken from https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
13  template<class T>
14  typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
15  almost_equal(T x, T y, int ulp = 2)
16  {
17  // the machine epsilon has to be scaled to the magnitude of the values used
18  // and multiplied by the desired precision in ULPs (units in the last place)
19  return std::fabs(x-y) <= std::numeric_limits<T>::epsilon() * std::fabs(x+y) * ulp
20  // unless the result is subnormal
21  || std::fabs(x-y) < std::numeric_limits<T>::min();
22  }
23 
24  template<typename StateType>
25  bool isConstantChain (const std::vector<const std::vector<StateType>*>& chains, long dimension) {
26  using Scalar = typename StateType::Scalar;
27 
28  long d = dimension;
29  unsigned long numberOfChains = chains.size();
30  unsigned long numberOfDraws = chains[0]->size();
31 
32  std::vector<Scalar> initDraw(numberOfChains, 0);
33 
34  bool chainsAllConst = true;
35  for (unsigned long m = 0; m < numberOfChains; ++m) {
36  initDraw[m] = (*chains[m])[0](d);
37 
38  if (!std::isfinite(initDraw[m])) {
39  return std::numeric_limits<double>::quiet_NaN();
40  }
41 
42  // check if all draws are (almost) equal to the first value.
43  // if one is different, break.
44  bool drawsAllConst = true;
45  for (unsigned long n = 1; n < numberOfDraws; ++n) {
46  if (!std::isfinite((*chains[m])[n](d))) {
47  return true;
48  }
49 
50  if (!almost_equal(initDraw[m], (*chains[m])[n](d))) {
51  drawsAllConst = false;
52  break;
53  }
54  }
55 
56  // record if any of the chains has draws which are not all const
57  if (!drawsAllConst) {
58  chainsAllConst = false;
59  break;
60  }
61  }
62 
63  if (chainsAllConst) {
64  bool chainsAllSameConst = true;
65  // If all chains are constant then return NaN
66  // if they all equal the same constant value
67  for (unsigned long m = 1; m < numberOfChains; ++m) {
68  if (!almost_equal(initDraw[0], initDraw[m])) {
69  chainsAllSameConst = false;
70  break;
71  }
72  }
73 
74  if (chainsAllSameConst) {
75  return true;
76  }
77  }
78 
79  return false;
80  }
81 
82  template<typename StateType>
83  bool isConstantChain (const std::vector<std::vector<StateType>>& chains, long dimension) {
84  std::vector<const std::vector<StateType>*> chainsPtrArray;
85  for (auto& chain : chains) {
86  chainsPtrArray.push_back(&chain);
87  }
88  return isConstantChain(chainsPtrArray, dimension);
89  }
90 
91  template<typename StateType>
92  bool isConstantChain (const std::vector<const std::vector<StateType>*>& chains) {
93  for (long dimension = 0; dimension < (*chains[0])[0].size(); ++dimension) {
94  if (!isConstantChain(chains, dimension)) {
95  return false;
96  }
97  }
98 
99  return true;
100  }
101 
102  template<typename StateType>
103  bool isConstantChain (const std::vector<std::vector<StateType>>& chains) {
104  std::vector<const std::vector<StateType>*> chainsPtrArray;
105  for (auto& chain : chains) {
106  chainsPtrArray.push_back(&chain);
107  }
108  return isConstantChain(chainsPtrArray);
109  }
110 }
111 
112 #endif // ISCONSTANTCHAIN_HPP
hops::almost_equal
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type almost_equal(T x, T y, int ulp=2)
Definition: IsConstantChain.hpp:15
hops
Definition: CsvReader.hpp:8
hops::isConstantChain
bool isConstantChain(const std::vector< const std::vector< StateType > * > &chains, long dimension)
Definition: IsConstantChain.hpp:25