Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
SparseMatrix.h
Go to the documentation of this file.
1#ifndef SPARSEMATRIX_H
2#define SPARSEMATRIX_H
3
4#include <iostream>
5#include <map>
6#include <string>
7#include <vector>
8#include <stdexcept>
9
15template<typename T>
16using SparseMatrix = std::map<std::pair<T, T>, double>;
17
25template<typename T>
26std::vector<T> getDiagonalElements(const SparseMatrix<T>& matrix) {
27 std::vector<T> diagonalElements;
28 for (const auto& element : matrix) {
29 if (element.first.first == element.first.second) {
30 diagonalElements.push_back(element.first.first);
31 }
32 }
33 return diagonalElements;
34}
35
43template<typename T>
44SparseMatrix<T> createIdentityMatrix(const std::vector<T>& indices) {
45 SparseMatrix<T> identity;
46 for (const T& index : indices) {
47 identity[{index, index}] = 1.0;
48 }
49 return identity;
50}
51
61template<typename T>
62double getElement(const SparseMatrix<T>& matrix, const T& row, const T& col) {
63 auto it = matrix.find({row, col});
64 if (it != matrix.end()) {
65 return it->second;
66 }
67 return 0.0;
68}
69
79template<typename T>
80void setElement(SparseMatrix<T>& matrix, const T& row, const T& col, double value) {
81 if (value != 0.0) {
82 matrix[{row, col}] = value;
83 } else {
84 matrix.erase({row, col});
85 }
86}
87
97template<typename T>
98SparseMatrix<T> invertMatrix(const SparseMatrix<T>& matrix, const std::vector<T>& indices) {
99 SparseMatrix<T> augmentedMatrix = matrix;
100 SparseMatrix<T> inverse = createIdentityMatrix(indices);
101
102 for (size_t i = 0; i < indices.size(); ++i) {
103 T pivot = indices[i];
104
105 double pivotValue = getElement(augmentedMatrix, pivot, pivot);
106 if (pivotValue == 0.0) {
107 throw std::runtime_error("Matrix is singular and cannot be inverted.");
108 }
109
110 for (size_t k = 0; k < indices.size(); ++k) {
111 T col = indices[k];
112 setElement(augmentedMatrix, pivot, col, getElement(augmentedMatrix, pivot, col) / pivotValue);
113 setElement(inverse, pivot, col, getElement(inverse, pivot, col) / pivotValue);
114 }
115
116 for (size_t j = 0; j < indices.size(); ++j) {
117 if (i == j) continue;
118 T row = indices[j];
119 double factor = getElement(augmentedMatrix, row, pivot);
120 for (size_t k = 0; k < indices.size(); ++k) {
121 T col = indices[k];
122 setElement(augmentedMatrix, row, col, getElement(augmentedMatrix, row, col) - factor * getElement(augmentedMatrix, pivot, col));
123 setElement(inverse, row, col, getElement(inverse, row, col) - factor * getElement(inverse, pivot, col));
124 }
125 }
126 }
127
128 return inverse;
129}
130
141template<typename T>
142std::pair<SparseMatrix<T>, std::vector<T>> removeEmptyRowsAndCols(const SparseMatrix<T>& matrix, const std::vector<T>& indices) {
143 std::map<T, int> rowCount;
144 std::map<T, int> colCount;
145
146 // Count non-zero elements per row and column
147 for (const auto& [coord, value] : matrix) {
148 if (value != 0.0) { // <-- Ignore zero entries explicitly present
149 T row = coord.first;
150 T col = coord.second;
151 rowCount[row]++;
152 colCount[col]++;
153 }
154 }
155
156 // Keep only indices where row and column are not empty
157 std::vector<T> cleanedIndices;
158 for (const T& idx : indices) {
159 if (rowCount[idx] > 0 || colCount[idx] > 0) {
160 cleanedIndices.push_back(idx);
161 }
162 }
163
164 // Filter matrix to keep only relevant rows/cols
165 SparseMatrix<T> cleanedMatrix;
166 for (const auto& [coord, value] : matrix) {
167 if (value != 0.0) {
168 T row = coord.first;
169 T col = coord.second;
170 if (std::find(cleanedIndices.begin(), cleanedIndices.end(), row) != cleanedIndices.end() &&
171 std::find(cleanedIndices.begin(), cleanedIndices.end(), col) != cleanedIndices.end()) {
172 cleanedMatrix[coord] = value;
173 }
174 }
175 }
176
177 return {cleanedMatrix, cleanedIndices};
178}
179
180
188template<typename T>
189void printMatrix(const SparseMatrix<T>& matrix, const std::vector<T>& indices) {
190 for (const auto& i : indices) {
191 for (const auto& j : indices) {
192 std::cout << getElement(matrix, i, j) << " ";
193 }
194 std::cout << std::endl;
195 }
196}
197
205template<typename T>
206void customPrintMatrix(const SparseMatrix<T>& matrix, const std::vector<T>& indices) {
207 // Determine maximum width for any label or value
208 size_t maxLabelWidth = 0;
209 size_t maxValueWidth = 0;
210
211 std::ostringstream oss;
212 for (const T& index : indices) {
213 oss.str("");
214 oss.clear();
215 oss << index;
216 maxLabelWidth = std::max(maxLabelWidth, oss.str().length());
217 }
218
219 for (const auto& [coord, value] : matrix) {
220 oss.str("");
221 oss.clear();
222 oss << value;
223 maxValueWidth = std::max(maxValueWidth, oss.str().length());
224 }
225
226 size_t cellWidth = std::max(maxLabelWidth, maxValueWidth) + 2;
227
228 // Print top-left empty cell
229 std::cout << std::setw(cellWidth) << " ";
230
231 // Print column headers
232 for (const auto& col : indices) {
233 std::cout << std::setw(cellWidth) << col;
234 }
235 std::cout << "\n";
236
237 // Print separator line
238 std::cout << std::setw(cellWidth) << " ";
239 for (size_t i = 0; i < indices.size(); ++i) {
240 std::cout << std::setw(cellWidth) << std::string(cellWidth - 1, '-');
241 }
242 std::cout << "\n";
243
244 // Print rows
245 for (const auto& row : indices) {
246 std::cout << std::setw(cellWidth) << row;
247 for (const auto& col : indices) {
248 double val = getElement(matrix, row, col);
249 std::cout << std::setw(cellWidth) << val;
250 }
251 std::cout << "\n";
252 }
253}
254
255template<typename T>
257public:
259
261
262 double getElement(T row, T col) const {
263 return ::getElement(matrix, row, col);
264 }
265
266 void setElement(T row, T col, double value) {
267 ::setElement(matrix, row, col, value);
268 }
269
270 std::vector<T> getDiagonalElements() const {
271 return ::getDiagonalElements(matrix);
272 }
273
274 void print(const std::vector<T>& indices) const {
275 ::printMatrix(matrix, indices);
276 }
277
278 SparseMatrixWrapper<T> invert(const std::vector<T>& indices) const {
280 result.matrix = ::invertMatrix(matrix, indices);
281 return result;
282 }
283};
284
285
286#endif // __SPARSEMATRIX_H__
void customPrintMatrix(const SparseMatrix< T > &matrix, const std::vector< T > &indices)
Prints the matrix in a formatted grid with row and column headers.
void setElement(SparseMatrix< T > &matrix, const T &row, const T &col, double value)
Sets or updates an element in the sparse matrix.
std::map< std::pair< T, T >, double > SparseMatrix
Alias for a sparse matrix using a map of coordinate pairs.
void printMatrix(const SparseMatrix< T > &matrix, const std::vector< T > &indices)
Prints the matrix in dense form using a list of indices.
std::pair< SparseMatrix< T >, std::vector< T > > removeEmptyRowsAndCols(const SparseMatrix< T > &matrix, const std::vector< T > &indices)
Removes rows and columns that are entirely zero (i.e., not present in the sparse matrix).
SparseMatrix< T > invertMatrix(const SparseMatrix< T > &matrix, const std::vector< T > &indices)
Inverts a square sparse matrix using Gauss-Jordan elimination.
double getElement(const SparseMatrix< T > &matrix, const T &row, const T &col)
Retrieves an element from the sparse matrix.
std::vector< T > getDiagonalElements(const SparseMatrix< T > &matrix)
Extracts the diagonal elements from a sparse matrix.
SparseMatrix< T > createIdentityMatrix(const std::vector< T > &indices)
Creates an identity matrix from a list of indices.
double getElement(T row, T col) const
std::vector< T > getDiagonalElements() const
void print(const std::vector< T > &indices) const
void setElement(T row, T col, double value)
SparseMatrixWrapper< T > invert(const std::vector< T > &indices) const
SparseMatrix< T > matrix
SparseMatrixWrapper()=default
double T(double x)
Wilson coefficient T(x).