TrdMCClusterR Fit Classifier
LinearAlgebra.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <limits>
4 #include <iostream>
5 #include <vector>
6 #include <cmath>
7 
8 #include <TMatrixD.h>
9 #include <TVectorD.h>
10 #include <TDecompSVD.h>
11 
12 
13 const double EPSILON = 1e-9;
14 
15 
16 namespace LA
17 {
18  //___________________________________________________________________________
19  std::vector<double> ROOTEquationSolver(const double& m1, const double& b1,
20  const double& m2, const double& b2,
21  const double& m3, const double& b3,
22  bool debugMode)
23  {
28  std::vector<std::vector<double>> mat = {
29  {-m1, 0, 1},
30  { 0, -m2, 1},
31  {-m3, 1, 0}
32  };
33 
34  // Construct a TMatrixD equivalent of the 2D std::vector
35  const int rows = mat.size();
36  const int cols = mat.empty() ? 0 : mat[0].size();
37  TMatrixD rootMatrix(rows, cols);
38  for (int i = 0; i < rows; ++i) {
39  for (int j = 0; j < cols; ++j) {
40  rootMatrix(i, j) = mat[i][j];
41  }
42  }
43 
44  TDecompSVD svd(rootMatrix);
45  TVectorD b(3); b(0) = b1; b(1) = b2; b(2) = b3;
46  Bool_t is_good_solution;
47 
49  TVectorD solution(b.GetNrows());
50 
52  solution = svd.Solve(b, is_good_solution);
53 
54  if (!is_good_solution)
55  {
56  if (debugMode)
57  std::cerr<<"\n\nWARNING: The system cannot be solved or is ill-conditioned.\n";
58  return {};
59  }
60 
62  std::vector<double> solutionVec = VectorUtilities::TVectorDToStdVector(solution);
63  return solutionVec;
64  }
65 
66 
67 
68  //___________________________________________________________________________
69  void GaussianElimination(std::vector<std::vector<double>>& mat, bool debugMode = false)
70  {
76  if (debugMode)
77  {
78  std::cout<<"\nBefore Gaussian elimination\n";
80  std::cout<<"\n";
81  }
82 
83  int n = mat.size();
84 
85  for (int i = 0; i < n; ++i)
86  {
88  int pivotRow = i;
89  for (int row = i + 1; row < n; ++row)
90  {
91  if (std::fabs(mat[row][i]) > std::fabs(mat[pivotRow][i]))
92  pivotRow = row;
93  }
94  std::swap(mat[pivotRow], mat[i]);
95 
97  if (std::fabs(mat[i][i]) < EPSILON) continue;
98 
100  for (int col = i + 1; col <= n; ++col)
101  {
102  mat[i][col] /= mat[i][i];
103  }
104  mat[i][i] = 1.0;
105 
107  for (int row = i + 1; row < n; ++row)
108  {
109  double factor = mat[row][i];
110  for (int col = i; col <= n; ++col) {
111  mat[row][col] -= factor * mat[i][col];
112  }
113  }
114  }
115 
116  if (debugMode)
117  {
118  std::cout<<"\nAfter Gaussian elimination\n";
120  std::cout<<"\n";
121  }
122  }
123 
124 
125  //___________________________________________________________________________
126  int GetMatrixRank(const std::vector<std::vector<double>>& mat)
127  {
129  int rank = 0;
130  for (const auto& row : mat) {
131  for (double val : row) {
132  if (std::fabs(val) > EPSILON) {
133  ++rank;
134  break;
135  }
136  }
137  }
138  return rank;
139  }
140 
141 
142  //___________________________________________________________________________
143  int CheckSolutions(const std::vector<std::vector<double>>& mat, std::vector<double>& solution)
144  {
146 
147  int n = mat.size();
148  int rankA = GetMatrixRank(mat);
149 
151  std::vector<std::vector<double>> augmentedMat(mat);
152  for (int i = 0; i < n; ++i) {
153  augmentedMat[i].pop_back();
154  }
155 
156  int rankAugmented = GetMatrixRank(augmentedMat);
157 
158  if (rankA < rankAugmented)
159  return -1;
160  else if (rankA < n)
161  return 0;
162 
164  solution.assign(n, 0);
165  for (int i = n - 1; i >= 0; --i) {
166  solution[i] = mat[i][n];
167 
168  for (int j = i + 1; j < n; ++j) {
169  solution[i] -= mat[i][j] * solution[j];
170  }
171 
172  if (std::fabs(mat[i][i]) > EPSILON) {
173  solution[i] /= mat[i][i];
174  }
175 
176  else if (std::fabs(solution[i]) > EPSILON) {
177  return -1;
178  }
179  }
180  return 1;
181  }
182 
183 
184  //___________________________________________________________________________
185  bool ValidateSolution(const std::vector<std::vector<double>>& origMat,
186  const std::vector<double>& solution,
187  bool debugMode)
188  {
190 
191  int n = origMat.size();
192  for (int i = 0; i < n; ++i)
193  {
194  double sum = 0.0;
195  for (int j = 0; j < n; ++j) {
196  sum += origMat[i][j] * solution[j];
197  }
198 
200  debugMode = false;
201 
202  if (debugMode)
203  std::cout<<"For equation "<<i<<", sum(0, n-1) = "<<sum<<", origMat[i][n] = "<<origMat[i][n]<<std::endl;
204  if (std::fabs(sum - origMat[i][n]) > EPSILON)
205  return false;
206  }
207  return true;
208  }
209 
210 
211  //___________________________________________________________________________
212  bool IsSlopeUndefined(double slope)
213  {
215  return std::abs(slope) > std::numeric_limits<double>::max();
216  }
217 
218 
219  //___________________________________________________________________________
220  std::vector<double> SolveSystemOfThreeEquations(const double& m1, const double& b1,
221  const double& m2, const double& b2,
222  const double& m3, const double& b3,
223  bool debugMode)
224  {
231  std::vector<std::vector<double>> mat = {
232  {-m1, 0, 1, b1},
233  { 0, -m2, 1, b2},
234  {-m3, 1, 0, b3}
235  };
236 
237  // Store the original matrix for validation
238  std::vector<std::vector<double>> origMat = mat;
239 
240  // Perform Gaussian elimination
241  GaussianElimination(mat);
242 
243  std::vector<double> solution;
244  int result = CheckSolutions(mat, solution);
245 
246  if (result == 1)
247  {
248  if (debugMode)
249  {
250  std::cout<<"\nThe system has a unique solution:"<<std::endl;
251  for (double s : solution) {
252  std::cout << s << " ";
253  }
254  std::cout<<std::endl;
255  }
256 
257  // Validate the solution
258  if (ValidateSolution(origMat, solution, debugMode))
259  {
260  if (debugMode)
261  std::cout<<"The solution is valid."<<std::endl;
262  return solution;
263  }
264 
265  else
266  {
267  if (debugMode)
268  std::cout<<"\n\nERROR: The solution is invalid.\nThis should never happen! Please check logic!\n\n"<<std::endl;
269  return {-9.0};
270  }
271  }
272 
273  else if (result == 0)
274  {
275  if (debugMode)
276  std::cout<<"\nThe system has infinite solutions."<<std::endl;
277  return {1.0};
278  }
279 
280  else
281  {
282  if (debugMode)
283  std::cout<<"\nThe system has no solution."<<std::endl;
284  return {0.0};
285  }
286  }
287 }
const double EPSILON
Definition: LinearAlgebra.h:13
Definition: LinearAlgebra.h:17
int CheckSolutions(const std::vector< std::vector< double >> &mat, std::vector< double > &solution)
Definition: LinearAlgebra.h:143
int GetMatrixRank(const std::vector< std::vector< double >> &mat)
Definition: LinearAlgebra.h:126
void GaussianElimination(std::vector< std::vector< double >> &mat, bool debugMode=false)
Definition: LinearAlgebra.h:69
std::vector< double > SolveSystemOfThreeEquations(const double &m1, const double &b1, const double &m2, const double &b2, const double &m3, const double &b3, bool debugMode)
Definition: LinearAlgebra.h:220
std::vector< double > ROOTEquationSolver(const double &m1, const double &b1, const double &m2, const double &b2, const double &m3, const double &b3, bool debugMode)
Definition: LinearAlgebra.h:19
bool ValidateSolution(const std::vector< std::vector< double >> &origMat, const std::vector< double > &solution, bool debugMode)
Definition: LinearAlgebra.h:185
bool IsSlopeUndefined(double slope)
Definition: LinearAlgebra.h:212
std::vector< double > TVectorDToStdVector(const TVectorD &vec)
Definition: Utilities.h:164
void printVectorOfVectors(std::vector< std::vector< double >> const &mat)
Definition: Utilities.h:67