diff --git a/src/Gauss.cpp b/src/Gauss.cpp index 60513ee..6234e10 100644 --- a/src/Gauss.cpp +++ b/src/Gauss.cpp @@ -4,72 +4,66 @@ namespace Gauss { -static void GaussNonJordan(Matrix& mat, bool reduite) { - int r = -1; - for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { - std::size_t indice_ligne_maximum = r + 1; - - // Recherche maximum - for (std::size_t i = r + 1; i < mat.GetRawCount(); i++) { - if (std::abs(mat.at(i, j)) > std::abs(mat.at(indice_ligne_maximum, j))) - indice_ligne_maximum = i; - } - - // Si A[k,j]≠0 alors (A[k,j] désigne la valeur de la ligne k et de la colonne j) - if (!IsEqualZero(mat.at(indice_ligne_maximum, j))) { - r++; - - // Si k≠r alors - if (indice_ligne_maximum != r) { - // Échanger les lignes k et r (On place la ligne du pivot en position r) - for (std::size_t k = 0; k < mat.GetColumnCount(); k++) { - std::swap(mat.at(indice_ligne_maximum, k), mat.at(r, k)); - } - } - - // Pour i de 1 jusqu'à n (On simplifie les autres lignes) - for (std::size_t i = (reduite ? 0 : j); i < mat.GetRawCount(); i++) { - // Si i≠r alors - if (i != r) { - // Soustraire à la ligne i la ligne r multipliée par A[i,j] (de façon à - // annuler A[i,j]) - for (int k = mat.GetColumnCount() - 1; k >= 0; k--) { - long double pivot = mat.at(r, j); - long double anul = mat.at(i, j); - mat.at(i, k) = mat.at(i, k) * pivot - mat.at(r, k) * anul; - } - } - } - } +static void SwapLines(Matrix& mat, std::size_t line1, std::size_t line2) { + for (std::size_t k = 0; k < mat.GetColumnCount(); k++) { + std::swap(mat.at(line1, k), mat.at(line2, k)); } } -static void GaussJordan(Matrix& mat, bool reduite) { - GaussNonJordan(mat, reduite); - for (std::size_t i = 0; i < mat.GetRawCount(); i++) { - int k = -1; - for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { - if (!IsEqualZero(mat.at(i, j))) { - k = j; - break; - } - } - // ligne de 0 - if (k == -1) - break; - // on divise la ligne par (i, k) - long double annul = mat.at(i, k); - for (int j = 0; j < mat.GetColumnCount(); j++) { - mat.at(i, j) /= annul; +static void DivideLine(Matrix& mat, std::size_t line, Matrix::Element number) { + for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { + mat.at(line, j) /= number; + } +} + +static int FirstNotNullElementIndexOnColumn(Matrix& mat, std::size_t column, std::size_t startLine = 0) { + for (std::size_t i = startLine; i < mat.GetRawCount(); i++) { + if (!IsEqualZero(mat.at(i, column))) { + return i; } } + return -1; +} + +static void SimplifyLine(Matrix& mat, std::size_t line, std::size_t pivot_line, std::size_t pivot_column) { + const Matrix::Element pivot = mat.at(pivot_line, pivot_column); + const Matrix::Element anul = mat.at(line, pivot_column); + + for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { + mat.at(line, j) = mat.at(line, j) * pivot - mat.at(pivot_line, j) * anul; + } } void GaussJordan(Matrix& mat, bool reduite, bool normalise) { - if (normalise) - GaussJordan(mat, reduite); - else - GaussNonJordan(mat, reduite); + int indice_ligne_pivot = -1; + + for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { + + int indice_ligne_pivot_trouve = FirstNotNullElementIndexOnColumn(mat, j, indice_ligne_pivot + 1); + + if (indice_ligne_pivot_trouve < 0) // colonne de 0 + continue; // on regarde la prochaine colonne + + indice_ligne_pivot++; + + if (indice_ligne_pivot_trouve != indice_ligne_pivot) { + SwapLines(mat, indice_ligne_pivot_trouve, indice_ligne_pivot); + } + + Matrix::Element pivot = mat.at(indice_ligne_pivot, j); + + if (normalise) { + DivideLine(mat, indice_ligne_pivot, pivot); + } + + // On simplifie les autres lignes + for (std::size_t i = (reduite ? 0 : j); i < mat.GetRawCount(); i++) { + // Pour les lignes autre que la ligne pivot + if (i != static_cast(indice_ligne_pivot)) { + SimplifyLine(mat, i, indice_ligne_pivot, j); + } + } + } } } // namespace Gauss \ No newline at end of file diff --git a/src/Gauss.h b/src/Gauss.h index 168919a..5116a27 100644 --- a/src/Gauss.h +++ b/src/Gauss.h @@ -4,6 +4,12 @@ class Matrix; namespace Gauss { +/** + * \brief Echelonne une matrice en utilisant l'algorithme de Gauss-Jordan + * \param mat La matrice à échelonner + * \param reduite Mets des 0 au dessus des pivots + * \param normalise Mets les pivots à 1 + */ void GaussJordan(Matrix& mat, bool reduite, bool normalise); } // namespace Gauss \ No newline at end of file diff --git a/src/IO.cpp b/src/IO.cpp new file mode 100644 index 0000000..800a3cd --- /dev/null +++ b/src/IO.cpp @@ -0,0 +1,101 @@ +#include "IO.h" + +#include "Vect.h" +#include +#include + +std::ostream& operator<<(std::ostream& stream, const Matrix& mat) { + stream << mat.GetRawCount() << " " << mat.GetColumnCount() << "\n"; + for (std::size_t i = 0; i < mat.GetRawCount(); i++) { + for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { + stream << mat.at(i, j) << " "; + } + stream << "\n"; + } + return stream; +} + +std::istream& operator>>(std::istream& stream, Matrix& mat) { + std::size_t raw, column; + stream >> raw >> column; + + Matrix result {raw, column}; + mat = result; + + for (std::size_t i = 0; i < mat.GetRawCount(); i++) { + for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { + stream >> mat.at(i, j); + } + } + + return stream; +} + +Matrix LoadMatrix(const std::string& fileName) { + std::ifstream in {fileName}; + if (!in) { + std::cerr << "Impossible de charger la matrice !\n"; + return {}; + } + Matrix result; + in >> result; + + return result; +} + +void SaveMatrix(const Matrix& mat, const std::string& fileName) { + std::ofstream out {fileName}; + if (!out) { + std::cerr << "Impossible de sauvegarder la matrice !\n"; + return; + } + out << mat; +} + +Matrix InsertMatrix() { + std::cout << "Quelle est le nombre de lignes de votre matrice ?" << std::endl; + std::size_t lignes; + std::cin >> lignes; + std::cout << "Quelle est le nombre de colonnes de votre matrice ?" << std::endl; + std::size_t colonnes; + std::cin >> colonnes; + std::cout << "Rentrez les coefficients de la matrice" << std::endl; + Matrix result(lignes, colonnes); + for (size_t i = 0; i < result.GetRawCount(); ++i) { + for (size_t j = 0; j < result.GetColumnCount(); ++j) { + std::cin >> result.at(i, j); + } + std::cout << std::endl; + } + + return result; +} + +void Print(const Matrix& mat) { + for (size_t i = 0; i < mat.GetRawCount(); ++i) { + std::cout << "[ "; + for (size_t j = 0; j < mat.GetColumnCount(); ++j) { + std::cout << mat.at(i, j) << " "; + } + std::cout << "]"; + std::cout << std::endl; + } +} + +void Print(const Vect& vect) { + std::cout << "Espace vectoriel de dimension " << vect.GetCardinal() << " de base :\n\n"; + for (std::size_t i = 0; i < vect.GetDimension(); i++) { + for (std::size_t j = 0; j < vect.GetCardinal(); j++) { + Matrix vector = vect.GetVector(j); + std::cout << "[ " << vector.at(i, 0) << " ]\t"; + } + std::cout << "\n"; + } +} + +void Print(const VectAffine& vect) { + std::cout << "\tEspace Affine :\n\n"; + Print(vect.GetBase()); + std::cout << "\nOrigine :\n\n"; + Print(vect.GetOrigin()); +} \ No newline at end of file diff --git a/src/IO.h b/src/IO.h new file mode 100644 index 0000000..54732c6 --- /dev/null +++ b/src/IO.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Matrix; +class Vect; +class VectAffine; + +std::ostream& operator<<(std::ostream& stream, const Matrix& mat); +std::istream& operator>>(std::istream& stream, Matrix& mat); + +Matrix LoadMatrix(const std::string& fileName); +void SaveMatrix(const Matrix& mat, const std::string& fileName); + +Matrix InsertMatrix(); + +void Print(const Matrix& mat); +void Print(const Vect& vect); +void Print(const VectAffine& vect); \ No newline at end of file diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 244b36c..5f36544 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -1,20 +1,17 @@ #include "Matrix.h" +#include "IO.h" #include #include #include #include #include -Matrix::Matrix(const std::string& fileNameInput) { - Load(fileNameInput); -} - Matrix::Matrix(std::size_t lignes, std::size_t colonnes) : m_Raws(lignes), m_Columns(colonnes) { m_Data.resize(m_Raws * m_Columns); } -Matrix::Matrix(std::size_t lignes, std::size_t colonnes, std::initializer_list&& initList) : +Matrix::Matrix(std::size_t lignes, std::size_t colonnes, std::initializer_list&& initList) : m_Raws(lignes), m_Columns(colonnes) { m_Data = initList; m_Data.resize(m_Raws * m_Columns); @@ -25,14 +22,14 @@ Matrix::~Matrix() {} Matrix Matrix::operator*(const Matrix& other) const { if (m_Columns != other.m_Raws) { std::cerr << "Mutiplication impossible car la dimensions des matrices est incompatible" << std::endl; - return {1, 1, {0}}; + return {}; } Matrix result(m_Raws, other.m_Columns); for (std::size_t i = 0; i < m_Raws; ++i) { for (std::size_t j = 0; j < other.m_Columns; ++j) { - long double sum = 0; + Element sum = 0; for (std::size_t k = 0; k < m_Columns; k++) { sum += at(i, k) * other.at(k, j); } @@ -42,44 +39,6 @@ Matrix Matrix::operator*(const Matrix& other) const { return result; } -void Matrix::Print() const { - for (size_t i = 0; i < m_Raws; ++i) { - std::cout << "[ "; - for (size_t j = 0; j < m_Columns; ++j) { - std::cout << at(i, j) << " "; - } - std::cout << "]"; - std::cout << std::endl; - } -} - -void Matrix::Insert() { - for (size_t i = 0; i < m_Raws; ++i) { - for (size_t j = 0; j < m_Columns; ++j) { - std::cin >> at(i, j); - } - std::cout << std::endl; - } -} - -void Matrix::Save(const std::string& fileName) { - std::ofstream out {fileName}; - if (!out) { - std::cerr << "Impossible de sauvegarder la matrice !\n"; - return; - } - out << *this; -} - -void Matrix::Load(const std::string& filename) { - std::ifstream in {filename}; - if (!in) { - std::cerr << "Impossible de charger la matrice !\n"; - return; - } - in >> *this; -} - void Matrix::Transpose() { Matrix result {m_Columns, m_Raws}; for (std::size_t i = 0; i < m_Raws; i++) { @@ -133,15 +92,15 @@ bool Matrix::operator==(const Matrix& other) const { return true; } -long double& Matrix::operator[](std::size_t indice) { +Matrix::Element& Matrix::operator[](std::size_t indice) { return m_Data[indice]; } -long double& Matrix::at(std::size_t ligne, std::size_t colonne) { +Matrix::Element& Matrix::at(std::size_t ligne, std::size_t colonne) { return m_Data[ligne * m_Columns + colonne]; } -long double Matrix::at(std::size_t ligne, std::size_t colonne) const { +Matrix::Element Matrix::at(std::size_t ligne, std::size_t colonne) const { return m_Data[ligne * m_Columns + colonne]; } @@ -165,25 +124,3 @@ Matrix Matrix::SubMatrix(std::size_t origine_ligne, std::size_t origine_colonne, return result; } - -std::ostream& operator<<(std::ostream& stream, const Matrix& mat) { - stream << mat.m_Raws << " " << mat.m_Columns << "\n"; - for (std::size_t i = 0; i < mat.m_Raws; i++) { - for (std::size_t j = 0; j < mat.m_Columns; j++) { - stream << mat.at(i, j) << " "; - } - stream << "\n"; - } - return stream; -} - -std::istream& operator>>(std::istream& stream, Matrix& mat) { - stream >> mat.m_Raws >> mat.m_Columns; - mat.m_Data.resize(mat.m_Raws * mat.m_Columns); - for (std::size_t i = 0; i < mat.m_Raws; i++) { - for (std::size_t j = 0; j < mat.m_Columns; j++) { - stream >> mat.at(i, j); - } - } - return stream; -} diff --git a/src/Matrix.h b/src/Matrix.h index 2d34ded..a0ee3fb 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -6,26 +6,23 @@ #include class Matrix { + public: + typedef long double Element; + private: std::size_t m_Raws; std::size_t m_Columns; - std::vector m_Data; + std::vector m_Data; public: - Matrix(const std::string& fileNameInput); + Matrix() : m_Raws(0), m_Columns(0) {} Matrix(std::size_t raws, std::size_t columns); - Matrix(std::size_t raws, std::size_t columns, std::initializer_list&& initList); + Matrix(std::size_t raws, std::size_t columns, std::initializer_list&& initList); ~Matrix(); std::size_t GetRawCount() const; std::size_t GetColumnCount() const; - void Insert(); - void Print() const; - - void Save(const std::string& fileName); - void Load(const std::string& filename); - void Transpose(); static Matrix Identity(std::size_t size); @@ -36,13 +33,10 @@ class Matrix { bool operator==(const Matrix& other) const; Matrix operator*(const Matrix& other) const; - long double& operator[](std::size_t index); + Element& operator[](std::size_t index); - long double& at(std::size_t raw, std::size_t column); - long double at(std::size_t raw, std::size_t column) const; - - friend std::ostream& operator<<(std::ostream& stream, const Matrix& mat); - friend std::istream& operator>>(std::istream& stream, Matrix& mat); + Element& at(std::size_t raw, std::size_t column); + Element at(std::size_t raw, std::size_t column) const; }; template diff --git a/src/Vect.cpp b/src/Vect.cpp index 3b3e7a7..58990cc 100644 --- a/src/Vect.cpp +++ b/src/Vect.cpp @@ -5,6 +5,15 @@ #include #include +static bool IsColumnNull(Matrix& mat, std::size_t column) { + for (std::size_t i = 0; i < mat.GetRawCount(); i++) { + if (!IsEqualZero(mat.at(i, column))) { + return false; + } + } + return true; +} + Vect::Vect(const Matrix& mat) : m_Data(mat) { Simplify(); } @@ -12,12 +21,7 @@ Vect::Vect(const Matrix& mat) : m_Data(mat) { void Vect::Simplify() { Matrix mat = m_Data; for (std::size_t j = 0; j < mat.GetColumnCount(); j++) { - std::size_t i; - for (i = 0; i < mat.GetRawCount(); i++) { - if (!IsEqualZero(mat.at(i, j))) - break; - } - if (i == mat.GetRawCount()) { + if (IsColumnNull(mat, j)) { m_Data = mat.SubMatrix(0, 0, mat.GetRawCount(), j); return; } @@ -25,6 +29,10 @@ void Vect::Simplify() { m_Data = mat; } +Matrix Vect::GetVector(std::size_t index) const { + return m_Data.SubMatrix(0, index, m_Data.GetRawCount(), 1); +} + std::size_t Vect::GetCardinal() const { return m_Data.GetColumnCount(); } @@ -65,26 +73,9 @@ Matrix Vect::GetLinearSystem() const { return vect; } -void Vect::Print() const { - std::cout << "Espace vectoriel de dimension " << GetCardinal() << " de base :\n\n"; - for (std::size_t i = 0; i < m_Data.GetRawCount(); i++) { - for (std::size_t j = 0; j < m_Data.GetColumnCount(); j++) { - std::cout << "[ " << m_Data.at(i, j) << " ]\t"; - } - std::cout << "\n"; - } -} - std::size_t Vect::GetDimension() const { return m_Data.GetRawCount(); } VectAffine::VectAffine(const Vect& base, const Matrix& origine) : - m_Base(base), m_Origin(origine.SubMatrix(0, 0, m_Base.GetDimension(), 1)) {} - -void VectAffine::Print() const { - std::cout << "\tEspace Affine :\n\n"; - m_Base.Print(); - std::cout << "\nOrigine :\n\n"; - m_Origin.Print(); -} + m_Base(base), m_Origin(origine.SubMatrix(0, 0, m_Base.GetDimension(), 1)) {} \ No newline at end of file diff --git a/src/Vect.h b/src/Vect.h index 64b587e..d540a44 100644 --- a/src/Vect.h +++ b/src/Vect.h @@ -15,10 +15,7 @@ class Vect { */ Vect(const Matrix& mat); - /** - * \brief Affiche la base de l'espace vectoriel dans la console - */ - void Print() const; + Matrix GetVector(std::size_t index) const; std::size_t GetDimension() const; std::size_t GetCardinal() const; @@ -46,8 +43,6 @@ class VectAffine { public: VectAffine(const Vect& base, const Matrix& origin); - void Print() const; - const Vect& GetBase() const { return m_Base; } diff --git a/src/main.cpp b/src/main.cpp index 114bb8e..169b909 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ +#include "Gauss.h" +#include "IO.h" #include "Matrix.h" #include "NR.h" -#include "Gauss.h" #include "Solver.h" #include @@ -19,8 +20,8 @@ void test() { mat.Print(); // mat.Save("matrice4x4echelonne.mat"); */ - Matrix mat2 {"matrice4x4.mat"}; - mat2.Print(); + Matrix mat2 = LoadMatrix("matrice4x4.mat"); + Print(mat2); Solver solver {mat2}; @@ -28,35 +29,27 @@ void test() { Vect noyau = solver.Kernel(); std::cout << "\tImage :\n"; - image.Print(); + Print(image); std::cout << "Système :\n"; - image.GetLinearSystem().Print(); + Print(image.GetLinearSystem()); std::cout << "\tNoyau :\n"; - noyau.Print(); + Print(noyau); std::cout << "Système :\n"; - noyau.GetLinearSystem().Print(); + Print(noyau.GetLinearSystem()); std::cout << "\n\n"; - solver.TriangularSystem().Print(); + Print(solver.TriangularSystem()); } void prompt() { - std::cout << "Quelle est le nombre de lignes de votre matrice ?" << std::endl; - std::size_t lignes; - std::cin >> lignes; - std::cout << "Quelle est le nombre de colonnes de votre matrice ?" << std::endl; - std::size_t colonnes; - std::cin >> colonnes; - std::cout << "Rentrez les coefficients de la matrice" << std::endl; - Matrix mat(lignes, colonnes); - mat.Insert(); + Matrix mat = InsertMatrix(); - mat.Print(); + Print(mat); Gauss::GaussJordan(mat, true, true); - mat.Print(); + Print(mat); } int main(int argc, char** argv) { diff --git a/test/test_solver.cpp b/test/test_solver.cpp index cfe6e7e..51a5fd9 100644 --- a/test/test_solver.cpp +++ b/test/test_solver.cpp @@ -3,6 +3,7 @@ #include #include +#include "IO.h" #include "Solver.h" namespace fs = std::filesystem; @@ -16,7 +17,7 @@ int main() { std::ifstream in {fileName}; - Matrix mat {1, 1}, imageMat {1, 1}, noyauMat {1, 1}; + Matrix mat, imageMat, noyauMat; in >> mat >> imageMat >> noyauMat; Vect image {imageMat};