Hamiltonian Monte Carlo

linearalgebra.cpp
Go to the documentation of this file.
1 //
2 // Created by Lars Gebraad on 7/10/17.
3 // Simple Linear Algebra stuff.
4 //
5 
6 #include <vector>
7 #include <iostream>
8 #include <cmath>
9 
10 // Linear algebra functions
11 std::vector<double> VectorDifference(std::vector<double> A, std::vector<double> B) {
12 
13  std::vector<double> C;
14 
15  if (A.size() != B.size()) {
16  // Get some Exception class to THROW.
17  std::cout << "Vectors are not the same dimension! The code DIDN'T run successfully." << std::endl;
18  throw std::exception();
19  }
20 
21  std::vector<double> q_difference;
22  for (int i = 0; i < A.size(); i++) {
23  // Prior misfit
24  C.push_back(A[i] - B[i]);
25  }
26  return C;
27 }
28 
29 std::vector<double> VectorScalarProduct(std::vector<double> A, double b) {
30  for (double &i : A) {
31  i = i * b;
32  }
33  return A;
34 }
35 
36 std::vector<double> VectorSum(std::vector<double> A, std::vector<double> B) {
37 
38  std::vector<double> C;
39 
40  if (A.size() != B.size()) {
41  // Get some Exception class to THROW.
42  std::cout << "Vectors are not the same dimension! The code DIDN'T run successfully." << std::endl;
43  throw std::exception();
44  }
45 
46  std::vector<double> q_difference;
47  for (int i = 0; i < A.size(); i++) {
48  // Prior misfit
49  C.push_back(A[i] + B[i]);
50  }
51  return C;
52 }
53 
54 std::vector<double> MatrixVectorProduct(std::vector<std::vector<double> > M, std::vector<double> A) {
55  std::vector<double> C;
56 
57  // Using std::vector<>.size() requires casting for clean compilation (seems unnecessary.. But oh well)
58  // So watch out if you're working on 2^63 order problems.. ;) (Maximum <int>, not maximum <unsigned int>)
59  int rowsM = static_cast<int>(M.size());
60  int columnsM = static_cast<int>(M[0].size());
61  int rowsA = static_cast<int>(A.size());
62 
63  if (columnsM != rowsA) {
64  // Get some Exception class to THROW.
65  std::cout << "Vector and matrix are not compatible in dimension! The code DIDN'T run successfully." << std::endl;
66  throw std::exception();
67  }
68 
69  for (int i = 0; i < rowsM; i++) {
70  C.push_back(0);
71  for (int j = 0; j < columnsM; j++) {
72  C[i] += M[i][j] * A[j];
73  }
74  }
75  return C;
76 }
77 
78 double VectorVectorProduct(std::vector<double> A, std::vector<double> B) {
79  double C;
80 
81  if (A.size() != B.size()) {
82  // Get some Exception class to THROW.
83  std::cout << "Vectors are not compatible in dimension! The code DIDN'T run successfully." << std::endl;
84  throw std::exception();
85  }
86  C = 0;
87  for (int i = 0; i < A.size(); i++) {
88  C += (A[i] * B[i]);
89  }
90  return C;
91 }
92 
93 std::vector<double> GetMatrixColumn(std::vector<std::vector<double>> M, int column) {
94  std::vector<double> A;
95  unsigned long rows = M.size();
96 
97  if (column > M[0].size()) {
98  // Get some Exception class to THROW.
99  std::cout << "Matrix index out of range. The code DIDN'T run successfully." << std::endl;
100  throw std::exception();
101  }
102 
103  A.clear();
104  for (unsigned long row = 0; row < rows; row++) {
105  A.push_back(M[row][column]);
106  }
107  return A;
108 }
109 
110 std::vector<double> GetMatrixRow(std::vector<std::vector<double>> M, int row) {
111  std::vector<double> A;
112  unsigned long columns = M[0].size();
113 
114  if (row > M.size()) {
115  // Get some Exception class to THROW.
116  std::cout << "Matrix index out of range. The code DIDN'T run successfully." << std::endl;
117  throw std::exception();
118  }
119 
120  A.clear();
121  for (unsigned long column = 0; column < columns; column++) {
122  A.push_back(M[row][column]);
123  }
124  return A;
125 }
126 
127 std::vector<std::vector<double>> TransposeMatrix(std::vector<std::vector<double> > M) {
128  unsigned long rows = M.size();
129  unsigned long columns = M[0].size();
130  std::vector<std::vector<double>> N;
131 
132  N.clear();
133  std::vector<double> zeroRow(rows, 0);
134  N.insert(N.end(), columns, zeroRow);
135 
136  for (int row = 0; row < rows; row++) {
137  for (int column = 0; column < columns; column++) {
138  N[column][row] = M[row][column];
139  }
140  }
141  return N;
142 }
143 
144 std::vector<double> MatrixTrace(std::vector<std::vector<double>> M) {
145  if (M.size() != M[0].size()) {
146  // Get some Exception class to THROW.
147  std::cout << "Matrix is not square, and trace doesn't exist. The code DIDN'T run successfully." << std::endl;
148  throw std::exception();
149  }
150  std::vector<double> trace;
151  trace.clear();
152  for (int i = 0; i < M.size(); i++) {
153  trace.push_back(M[i][i]);
154  }
155  return trace;
156 }
157 
158 std::vector<std::vector<double>> InvertMatrixElements(std::vector<std::vector<double>> M) {
159  for (std::vector<double> &row : M) {
160  for (double &rowElement : row) {
161  if (rowElement != 0) {
162  rowElement = 1.0 / rowElement;
163  }
164  }
165  }
166  return M;
167 }
168 
169 std::vector<std::vector<double>> VectorToDiagonal(std::vector<double> A) {
170  std::vector<std::vector<double>> M;
171 
172  M.clear();
173  std::vector<double> zeroRow(A.size(), 0);
174  M.insert(M.end(), A.size(), zeroRow);
175 
176  for (int i = 0; i < A.size(); i++) {
177  M[i][i] = A[i];
178  }
179 
180  return M;
181 }
182 
183 std::vector<std::vector<double>>
184 MatrixMatrixProduct(std::vector<std::vector<double>> M, std::vector<std::vector<double>> N) {
185  std::vector<std::vector<double>> P;
186  unsigned long columnsM = M[0].size();
187  unsigned long rowsM = M.size();
188  unsigned long columnsN = N[0].size();
189  unsigned long rowsN = N.size();
190 
191  if (columnsM != rowsN) {
192  // Get some Exception class to THROW.
193  std::cout << "Matrices are not compatible in dimension. The code DIDN'T run successfully." << std::endl;
194  throw std::exception();
195  }
196 
197  P.clear();
198  std::vector<double> zeroRow(columnsN, 0);
199  P.insert(P.end(), rowsM, zeroRow);
200 
201  for (int rowM = 0; rowM < rowsM; rowM++) {
202  for (int columnN = 0; columnN < columnsN; columnN++) {
203  double sum = 0;
204  for (int innerDim = 0; innerDim < rowsN; innerDim++) {
205  sum += M[rowM][innerDim] * N[innerDim][columnN];
206  }
207  P[rowM][columnN] = sum;
208  }
209  }
210  return P;
211 }
212 
213 std::vector<std::vector<double>> MatrixMatrixSum(std::vector<std::vector<double>> M, std::vector<std::vector<double>> N) {
214  std::vector<std::vector<double>> S;
215 
216  unsigned long columnsM = M[0].size();
217  unsigned long rowsM = M.size();
218  unsigned long columnsN = N[0].size();
219  unsigned long rowsN = N.size();
220 
221  if (columnsM != columnsN || rowsM != rowsN) {
222  // Get some Exception class to THROW.
223  std::cout << "Matrices are not compatible in dimension. The code DIDN'T run successfully." << std::endl;
224  throw std::exception();
225  }
226 
227  S.clear();
228  std::vector<double> zeroRow(columnsN, 0);
229  S.insert(S.end(), rowsN, zeroRow);
230 
231  for (int rowM = 0; rowM < rowsM; rowM++) {
232  for (int columnM = 0; columnM < columnsM; columnM++) {
233  S[rowM][columnM] = M[rowM][columnM] + N[rowM][columnM];
234  }
235  }
236 
237  return S;
238 }
239 
240 std::vector<std::vector<double>> operator+(std::vector<std::vector<double>> M, std::vector<std::vector<double>> N) {
241  // Just a simple wrapper. Doesn't need much memory because of std::move
242  return MatrixMatrixSum(std::move(M), std::move(N));
243 }
244 
245 std::vector<std::vector<double>> operator*(std::vector<std::vector<double>> M, std::vector<std::vector<double>> N) {
246  // Just a simple wrapper. Doesn't need much memory because of std::move
247  return MatrixMatrixProduct(std::move(M), std::move(N));
248 }
249 
250 double operator*(std::vector<double> A, std::vector<double> B) {
251  return VectorVectorProduct(std::move(A), std::move(B));
252 }
253 
254 std::vector<double> operator*(std::vector<std::vector<double>> M, std::vector<double> A) {
255  // Just a simple wrapper. Doesn't need much memory because of std::move
256  return MatrixVectorProduct(std::move(M), std::move(A));
257 }
258 
259 std::vector<double> operator+(std::vector<double> A, std::vector<double> B) {
260  return VectorSum(std::move(A), std::move(B));
261 }
262 
263 std::vector<double> operator-(std::vector<double> A, std::vector<double> B) {
264  return VectorDifference(std::move(A), std::move(B));
265 }
266 
267 std::vector<double> operator*(double b, std::vector<double> A) {
268  return VectorScalarProduct(std::move(A), b);
269 }
270 
271 std::vector<double> operator*(std::vector<double> A, double b) {
272  return VectorScalarProduct(std::move(A), b);
273 }
274 
275 std::vector<std::vector<double>> CholeskyDecompose(std::vector<std::vector<double>> A) {
276  std::vector<std::vector<double>> L;
277  unsigned long rowsA = A.size();
278  L.clear();
279  std::vector<double> zeroRow(rowsA, 0);
280  L.insert(L.end(), rowsA, zeroRow);
281 
282  L[0][0] = sqrt(A[0][0]);
283 
284  for (int row = 1; row < rowsA; ++row) {
285  for (int column = 0; column <= row; ++column) {
286 
287  double sum = 0;
288  for (int k = 0; k < column; k++) {
289  sum += L[row][k] * L[column][k];
290  }
291 
292  if (column == row) {
293  L[row][column] = sqrt(A[row][column] - sum);
294  } else {
295  L[row][column] = (1 / L[column][column]) * (A[row][column] - sum);
296  }
297  }
298  }
299 
300  return L;
301 }
302 
303 std::vector<double> SolveLowerTriangular(std::vector<std::vector<double>> L, std::vector<double> x) {
304  if (L.size() != L[0].size()) {
305  std::cout << "Lower triangular matrix is not square, and solving the triangular system can't be done. The "
306  << "code DIDN'T run successfully." << std::endl;
307  throw std::exception();
308  }
309  std::vector<double> y(L.size(), 0.0);
310 
311  y[0] = x[0] / L[0][0];
312  for (int i = 1; i < y.size(); ++i) {
313  double sum = 0.0;
314 
315  for (int j = 0; j < i; ++j) {
316  sum += L[i][j] * y[j];
317  }
318 
319  y[i] = (x[i] - sum) / L[i][i];
320  }
321 
322  return y;
323 }
324 
325 std::vector<std::vector<double>> InvertLowerTriangular(std::vector<std::vector<double>> L) {
326  if (L.size() != L[0].size()) {
327  std::cout << "Lower triangular matrix is not square, and inverse doesn't exist. The code DIDN'T run successfully." <<
328  std::endl;
329  throw std::exception();
330  }
331 
332  std::vector<std::vector<double>> iL;
333  for (int i = 0; i < L.size(); ++i) {
334  std::vector<double> RHS(L.size(), 0.0);
335  RHS[i] = 1.0;
336  iL.push_back(SolveLowerTriangular(L, RHS));
337  }
338  return TransposeMatrix(iL);
339 }
340 
341 std::vector<double> operator/(std::vector<double> A, double b) {
342  return VectorScalarProduct(std::move(A), 1.0 / b);
343 }
344 
345 std::vector<double> NormalizeVector(std::vector<double> A) {
346  return A / (sqrt(A * A));
347 }
std::vector< std::vector< double > > InvertLowerTriangular(std::vector< std::vector< double >> L)
Invert a lower triangular matrix by use of solving the system per column of using SolveLowerTriang...
std::vector< std::vector< double > > MatrixMatrixSum(std::vector< std::vector< double >> M, std::vector< std::vector< double >> N)
A function to calculate the sum of the entries of two matrices.
std::vector< double > MatrixTrace(std::vector< std::vector< double >> M)
Function to the trace of a square matrix .
std::vector< double > VectorSum(std::vector< double > A, std::vector< double > B)
Vector sum between two vectors.
std::vector< double > operator/(std::vector< double > A, double b)
Operator form of vector by scalar division. Uses VectorScalarProduct() with std library forwarding...
std::vector< std::vector< double > > VectorToDiagonal(std::vector< double > A)
Function which takes a std::vector of double to make a diagonal matrix of it, such that ...
std::vector< double > VectorDifference(std::vector< double > A, std::vector< double > B)
Vector difference between two vectors.
double VectorVectorProduct(std::vector< double > A, std::vector< double > B)
Dot product of vectors.
std::vector< std::vector< double > > TransposeMatrix(std::vector< std::vector< double > > M)
std::vector< double > VectorScalarProduct(std::vector< double > A, double b)
Vector scalar prodcut of vector and scalar.
std::vector< double > GetMatrixColumn(std::vector< std::vector< double >> M, int column)
Function to get a column from a matrix.
std::vector< double > GetMatrixRow(std::vector< std::vector< double >> M, int row)
Function to get a row from a matrix.
std::vector< std::vector< double > > MatrixMatrixProduct(std::vector< std::vector< double >> M, std::vector< std::vector< double >> N)
Function incorporating the standard matrix-matrix product, producing a new matrix. Matrix M should have as many columns as N has rows, otherwise an exception is thrown.
std::vector< std::vector< double > > InvertMatrixElements(std::vector< std::vector< double >> M)
Function to take the inverse of the individual matrix elements.
std::vector< double > SolveLowerTriangular(std::vector< std::vector< double >> L, std::vector< double > x)
Solve linear equation where is a lower triangular matrix and and are dimensional vectors...
std::vector< double > operator-(std::vector< double > A, std::vector< double > B)
Operator form of VectorDifference(), using std library forwarding.
std::vector< std::vector< double > > operator*(std::vector< std::vector< double >> M, std::vector< std::vector< double >> N)
Operator form of MatrixMatrixProduct(), using std library forwarding.
std::vector< double > NormalizeVector(std::vector< double > A)
Normalizes a vector to unit length.
std::vector< double > MatrixVectorProduct(std::vector< std::vector< double > > M, std::vector< double > A)
std::vector< std::vector< double > > operator+(std::vector< std::vector< double >> M, std::vector< std::vector< double >> N)
Operator form of MatrixMatrixSum(), using std library forwarding.
std::vector< std::vector< double > > CholeskyDecompose(std::vector< std::vector< double >> A)
Cholesky-decomposition of a positive definite Hermitian matrix .