#include "Solver.h" #include "Gauss.h" static int FirstNotNullElementIndexOnLine(const Matrix& mat, std::size_t line) { for (std::size_t i = 0; i < mat.GetColumnCount(); i++) { if (!IsEqualZero(mat.at(line, i))) { return i; } } return -1; } Vect Solver::Image(Matrix&& a_Matrix) const { a_Matrix.Transpose(); Gauss::GaussJordan(a_Matrix, false, false); a_Matrix.Transpose(); return {std::move(a_Matrix)}; } // https://en.wikipedia.org/wiki/Kernel_(linear_algebra)#Computation_by_Gaussian_elimination Vect Solver::Kernel(Matrix&& a_Matrix) const { std::size_t matrixRawCount = a_Matrix.GetRawCount(); std::size_t matrixColumnCount = a_Matrix.GetColumnCount(); a_Matrix.Transpose(); a_Matrix.Augment(Matrix::Identity(a_Matrix.GetRawCount())); Gauss::GaussJordan(a_Matrix, false, true); a_Matrix.Transpose(); // nombre de colonnes non nulles std::size_t origine_colonne = Vect(a_Matrix.SubMatrix(0, 0, matrixRawCount, matrixColumnCount)).GetCardinal(); return {a_Matrix.SubMatrix( matrixRawCount, origine_colonne, a_Matrix.GetRawCount() - matrixRawCount, a_Matrix.GetColumnCount() - origine_colonne)}; } VectAffine Solver::RectangularSystem(Matrix&& a_MatrixA, const Matrix& a_VectorB) const { Matrix mat = a_MatrixA; mat.Augment(a_VectorB); Gauss::GaussJordan(mat, true, true); Solver solver; Vect noyau = solver.Kernel(std::move(a_MatrixA)); Matrix origin = mat.SubMatrix(0, mat.GetColumnCount() - 1, mat.GetRawCount(), 1); // on calcule le vecteur qui dirige l'espace affine Matrix fullOrigin {mat.GetColumnCount() - 1, 1}; for (std::size_t i = 0; i < mat.GetRawCount(); i++) { int pivot_index = FirstNotNullElementIndexOnLine(mat, i); if (static_cast(pivot_index) == mat.GetColumnCount() - 1) { // on a une ligne du type 0 = n. Aucune solution ! return {Matrix {}, Matrix::ColumnVector({0})}; } // ligne entière de 0 if (pivot_index < 0) continue; fullOrigin.at(pivot_index, 0) = origin.at(i, 0); } return {noyau, fullOrigin}; } std::size_t Solver::Rank(Matrix&& a_Matrix) const { return Image(std::move(a_Matrix)).GetCardinal(); }