Quantum++  v1.0.0-beta2
C++11 quantum computing library
statistics.h
Go to the documentation of this file.
1 /*
2  * Quantum++
3  *
4  * Copyright (c) 2013 - 2017 Vlad Gheorghiu (vgheorgh@gmail.com)
5  *
6  * This file is part of Quantum++.
7  *
8  * Quantum++ is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Quantum++ is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Quantum++. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
27 #ifndef STATISTICS_H_
28 #define STATISTICS_H_
29 
30 // Collection of statistics-related functions
31 
32 namespace qpp
33 {
34 
41 inline std::vector<double> uniform(idx N)
42 {
43  // EXCEPTION CHECKS
44 
45  if (N == 0)
46  throw Exception("qpp::uniform", Exception::Type::ZERO_SIZE);
47  // END EXCEPTION CHECKS
48 
49  return std::vector<double>(N, 1. / N);
50 }
51 
60 inline std::vector<double> marginalX(const dmat& probXY)
61 {
62  // EXCEPTION CHECKS
63 
64  if (!internal::check_nonzero_size(probXY))
65  throw Exception("qpp::marginalX", Exception::Type::ZERO_SIZE);
66  // END EXCEPTION CHECKS
67 
68  std::vector<double> result(probXY.rows(), 0);
69  for (idx i = 0; i < static_cast<idx>(probXY.rows()); ++i)
70  {
71  for (idx j = 0; j < static_cast<idx>(probXY.cols()); ++j)
72  {
73  result[i] += probXY(i, j);
74  }
75  }
76 
77  return result;
78 }
79 
88 inline std::vector<double> marginalY(const dmat& probXY)
89 {
90  // EXCEPTION CHECKS
91 
92  if (!internal::check_nonzero_size(probXY))
93  throw Exception("qpp::marginalY", Exception::Type::ZERO_SIZE);
94  // END EXCEPTION CHECKS
95 
96  return marginalX(probXY.transpose());
97 }
98 
108 template<typename Container>
109 double avg(const std::vector<double>& prob, const Container& X,
110  typename std::enable_if<is_iterable<Container>::value>::type*
111  = nullptr)
112 {
113  // EXCEPTION CHECKS
114 
115  if (!internal::check_nonzero_size(prob))
116  throw Exception("qpp:avg", Exception::Type::ZERO_SIZE);
117  if (!internal::check_matching_sizes(prob, X))
118  throw Exception("qpp:avg", Exception::Type::SIZE_MISMATCH);
119  // END EXCEPTION CHECKS
120 
121  double result = 0;
122  for (idx i = 0; i < prob.size(); ++i)
123  result += prob[i] * X[i];
124 
125  return result;
126 }
127 
138 template<typename Container>
139 double cov(const dmat& probXY,
140  const Container& X,
141  const Container& Y,
142  typename std::enable_if<is_iterable<Container>::value>::type*
143  = nullptr)
144 {
145  // EXCEPTION CHECKS
146 
148  throw Exception("qpp:cov", Exception::Type::ZERO_SIZE);
149  if (static_cast<idx>(probXY.rows()) != X.size() ||
150  static_cast<idx>(probXY.cols()) != Y.size())
151  throw Exception("qpp:cov", Exception::Type::SIZE_MISMATCH);
152  // END EXCEPTION CHECKS
153 
154  std::vector<double> probX = marginalX(probXY); // marginals
155  std::vector<double> probY = marginalY(probXY); // marginals
156 
157  double result = 0;
158  for (idx i = 0; i < X.size(); ++i)
159  {
160  for (idx j = 0; j < Y.size(); ++j)
161  {
162  result += probXY(i, j) * X[i] * Y[j];
163  }
164  }
165 
166  return result - avg(probX, X) * avg(probY, Y);
167 }
168 
177 template<typename Container>
178 double var(const std::vector<double>& prob, const Container& X,
179  typename std::enable_if<is_iterable<Container>::value>::type*
180  = nullptr)
181 {
182  // EXCEPTION CHECKS
183 
184  if (!internal::check_nonzero_size(prob))
185  throw Exception("qpp:var", Exception::Type::ZERO_SIZE);
186  if (!internal::check_matching_sizes(prob, X))
187  throw Exception("qpp:var", Exception::Type::SIZE_MISMATCH);
188  // END EXCEPTION CHECKS
189 
190  Eigen::VectorXd diag(prob.size());
191  for (idx i = 0; i < prob.size(); ++i)
192  diag(i) = prob[i];
193  dmat probXX = diag.asDiagonal();
194 
195  return cov(probXX, X, X);
196 }
197 
206 template<typename Container>
207 double sigma(const std::vector<double>& prob, const Container& X,
208  typename std::enable_if<is_iterable<Container>::value>::type*
209  = nullptr)
210 {
211  // EXCEPTION CHECKS
212 
213  if (!internal::check_nonzero_size(prob))
214  throw Exception("qpp:sigma", Exception::Type::ZERO_SIZE);
215  if (!internal::check_matching_sizes(prob, X))
216  throw Exception("qpp:sigma", Exception::Type::SIZE_MISMATCH);
217  // END EXCEPTION CHECKS
218 
219  return std::sqrt(var(prob, X));
220 }
221 
232 template<typename Container>
233 double cor(const dmat& probXY,
234  const Container& X,
235  const Container& Y,
236  typename std::enable_if<is_iterable<Container>::value>::type*
237  = nullptr)
238 {
239  // EXCEPTION CHECKS
240 
242  throw Exception("qpp:cor", Exception::Type::ZERO_SIZE);
243  if (static_cast<idx>(probXY.rows()) != X.size() ||
244  static_cast<idx>(probXY.cols()) != Y.size())
245  throw Exception("qpp:cor", Exception::Type::SIZE_MISMATCH);
246  // END EXCEPTION CHECKS
247 
248  return cov(probXY, X, Y) / (sigma(marginalX(probXY), X) *
249  sigma(marginalX(probXY), Y));
250 }
251 
252 } /* namespace qpp */
253 
254 #endif /* STATISTICS_H_ */
255 
bool check_nonzero_size(const T &x) noexcept
Definition: util.h:127
std::vector< double > uniform(idx N)
Uniform probability distribution vector.
Definition: statistics.h:41
std::vector< double > marginalX(const dmat &probXY)
Marginal distribution.
Definition: statistics.h:60
Eigen::MatrixXd dmat
Real (double precision) dynamic Eigen matrix.
Definition: types.h:66
Quantum++ main namespace.
Definition: codes.h:30
double sigma(const std::vector< double > &prob, const Container &X, typename std::enable_if< is_iterable< Container >::value >::type *=nullptr)
Standard deviation.
Definition: statistics.h:207
Checks whether T is compatible with an STL-like iterable container.
Definition: traits.h:52
bool check_matching_sizes(const T1 &lhs, const T2 &rhs) noexcept
Definition: util.h:134
double var(const std::vector< double > &prob, const Container &X, typename std::enable_if< is_iterable< Container >::value >::type *=nullptr)
Variance.
Definition: statistics.h:178
Generates custom exceptions, used when validating function parameters.
Definition: exception.h:39
std::vector< double > marginalY(const dmat &probXY)
Marginal distribution.
Definition: statistics.h:88
std::size_t idx
Non-negative integer index.
Definition: types.h:36
double cor(const dmat &probXY, const Container &X, const Container &Y, typename std::enable_if< is_iterable< Container >::value >::type *=nullptr)
Correlation.
Definition: statistics.h:233
double cov(const dmat &probXY, const Container &X, const Container &Y, typename std::enable_if< is_iterable< Container >::value >::type *=nullptr)
Covariance.
Definition: statistics.h:139
double avg(const std::vector< double > &prob, const Container &X, typename std::enable_if< is_iterable< Container >::value >::type *=nullptr)
Average.
Definition: statistics.h:109