CASM  1.1.0
A Clusters Approach to Statistical Mechanics
MCData.cc
Go to the documentation of this file.
2 
3 #include <boost/math/special_functions/erf.hpp>
4 
5 namespace CASM {
6 namespace Monte {
7 
40  double prec) {
41  size_type start1, start2, N;
42  double sum1, sum2;
43  double eps =
44  (observations(0) == 0.0) ? 1e-8 : std::abs(observations(0)) * 1e-8;
45 
46  N = observations.size();
47  bool is_even = ((N % 2) == 0);
48 
49  // -------------------------------------------------
50  // if the values are all the same to observations(0)*1e-8, set
51  // m_is_equilibrated = true; m_equil_samples = 0;
52  bool all_same = true;
53  for (size_type i = 0; i < N; i++)
54  if (std::abs(observations(i) - observations(0)) > eps) {
55  all_same = false;
56  break;
57  }
58  if (all_same) {
59  m_is_equilibrated = true;
60  m_equil_samples = 0;
61  return;
62  }
63 
64  // find partitions
65  start1 = 0;
66  start2 = (is_even) ? N / 2 : (N / 2) + 1;
67 
68  // find sums for each partition
69  sum1 = observations.head(start2).sum();
70  // mean1 = sum1 / (start2 - start1)
71  sum2 = observations.segment(start2, N - start2).sum();
72  // mean2 = sum2 / (N - start2)
73 
74  // std::cout << observations << std::endl;
75 
76  // increment start1 (and update start2, sum1, and sum2) until abs(mean1 -
77  // mean2) < prec
78  while (std::abs((sum1 / (start2 - start1)) - (sum2 / (N - start2))) > prec &&
79  start1 < N - 2) {
80  /*std::cout << " start1: " << start1 << " start2: " << start2 << " N: "
81  << N
82  << " mean1: " << (sum1 / (start2 - start1)) << " mean2: " <<
83  (sum2 / (N - start2))
84  << " diff: " << std::abs((sum1 / (start2 - start1)) - (sum2 / (N
85  - start2)))
86  << " prec: " << prec << std::endl;*/
87  if (is_even) {
88  sum1 -= observations(start1);
89  sum1 += observations(start2);
90  sum2 -= observations(start2);
91  start2++;
92  } else {
93  sum1 -= observations(start1);
94  }
95 
96  start1++;
97  is_even = !is_even;
98  }
99 
100  // ensure that there are values on either side of the total mean
101  double mean_tot = (sum1 + sum2) / (N - start1);
102 
103  if (observations(start1) < mean_tot) {
104  while (observations(start1) < mean_tot && start1 < N - 1) start1++;
105  } else {
106  while (observations(start1) > mean_tot && start1 < N - 1) start1++;
107  }
108 
109  m_is_equilibrated = (start1 < N - 1);
110  m_equil_samples = start1;
111 }
112 
133  double conf)
134  : m_is_converged(false),
135  m_mean(observations.mean()),
136  m_squared_norm(observations.squaredNorm()) {
137  // will check if Var <= criteria
138  double z_alpha = sqrt(2.0) * boost::math::erf_inv(conf);
139 
140  bool found_rho;
141  double rho;
142  double CoVar0;
143  size_type N = observations.size();
144 
145  // try to calculate variance taking into account correlations
146  std::tie(found_rho, rho, CoVar0) = _calc_rho(observations);
147 
148  if (!found_rho) {
149  m_is_converged = false;
150  m_calculated_prec = 1.0 / 0.0;
151  return;
152  }
153 
154  double var_of_mean = (CoVar0 / N) * (1.0 + rho) / (1.0 - rho);
155 
156  m_calculated_prec = z_alpha * sqrt(var_of_mean);
157 }
158 
159 double covariance(const Eigen::VectorXd &X, const Eigen::VectorXd &Y,
160  double mean) {
161  Eigen::VectorXd vmean = Eigen::VectorXd::Ones(X.size()) * mean;
162  return (X - vmean).dot(Y - vmean) / X.size();
163 }
164 
170 std::tuple<bool, double, double> MCDataConvergence::_calc_rho(
171  const Eigen::VectorXd &observations) {
172  size_type N = observations.size();
173  double CoVar0 = m_squared_norm / N - m_mean * m_mean;
174 
175  // if there is essentially no variation, return rho(l==1)
176  if (std::abs(CoVar0 / m_mean) < 1e-8 || CoVar0 == 0.0) {
177  CoVar0 = 0.0;
178  return std::make_tuple(true, pow(2.0, -1.0 / 1), CoVar0);
179  }
180 
181  // simple incremental search for now, could try bracketing / bisection
182  for (size_type i = 1; i < N; ++i) {
183  size_type range_size = N - i;
184 
185  double cov = covariance(observations.segment(0, range_size),
186  observations.segment(i, range_size), m_mean);
187 
188  if (std::abs(cov / CoVar0) <= 0.5) {
189  return std::make_tuple(true, pow(2.0, (-1.0 / i)), CoVar0);
190  }
191  }
192 
193  // if could not find:
194  return std::make_tuple(false, 0.0, CoVar0);
195 }
196 
197 } // namespace Monte
198 } // namespace CASM
std::tuple< bool, double, double > _calc_rho(const Eigen::VectorXd &observations)
Try to find rho = pow(2.0, -1.0/i), using min i such that CoVar[i]/CoVar[0] <= 0.5.
Definition: MCData.cc:170
MCData::size_type size_type
Definition: MCData.hh:81
MCDataConvergence()
Default constructor.
Definition: MCData.hh:84
MCDataEquilibration()
Default constructor.
Definition: MCData.hh:63
MCData::size_type size_type
Definition: MCData.hh:60
double covariance(const Eigen::VectorXd &X, const Eigen::VectorXd &Y, double mean)
Definition: MCData.cc:159
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::VectorXd VectorXd