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