diff --git a/11_12_2019/solve/solve.cpp b/11_12_2019/solve/solve.cpp index 42f750e..3b3891e 100644 --- a/11_12_2019/solve/solve.cpp +++ b/11_12_2019/solve/solve.cpp @@ -1,7 +1,8 @@ #include "Matrix.hpp" #include "MatrixUtils.hpp" - +#include<iostream> #include <cassert> +#include<typeinfo> void testSolve( ); @@ -14,7 +15,17 @@ int main( ) void testSolve( ) { Matrix A( 3, 3 ); + //A( 0, 0 ) = 1.0; + //A( 0, 1 ) = 2.0; + //A( 0, 2 ) = -1.0; + + //A( 1, 0 ) = 4.0; + //A( 1, 1 ) = 3.0; + //A( 1, 2 ) = 1.0; + //A( 2, 0 ) = 2.0; + //A( 2, 1 ) = 2.0; + //A( 2, 2 ) = 3.0; A( 0, 0 ) = 3.0; A( 0, 1 ) = 2.0; A( 0, 2 ) = -4.0; @@ -27,12 +38,22 @@ void testSolve( ) A( 2, 1 ) = -3.0; A( 2, 2 ) = 1.0; - std::vector<double> rhs = {3., 15., 14.}; + std::cout << A; + std::vector<double> rhs = {3.0, 15.0, 14.0}; std::vector<double> answer = matrixUtilities::solveByGaussElimination( A, rhs ); - - assert( answer.size() == 3 ); - assert( std::abs( answer[0] - 3.0 ) < std::numeric_limits<double>::epsilon( ) ); - assert( std::abs( answer[1] - 1.0 ) < std::numeric_limits<double>::epsilon( ) ); - assert( std::abs( answer[2] - 2.0 ) < std::numeric_limits<double>::epsilon( ) ); + //L and U matrix generator + Matrix L(A.numberOfRows(), A.numberOfCols()), U(A.numberOfRows(), A.numberOfCols()); + matrixUtilities::lu_generator(A, L, U); + matrixUtilities::gauss_lu_solver(L, U, rhs); + for (auto a : answer) + std::cout << a << " "; + for (auto b : rhs) + std::cout << b << " "; + // assert( answer.size() == 3 ); + //double eps = 1e-10; + ////the numeric limits are of order 1e-16 so the assert will not work. + // assert( std::abs( answer[0] - 3.0 ) < eps ); + // assert( std::abs( answer[1] - 1.0 ) < eps ); + // assert( std::abs( answer[2] - 2.0 ) < eps ); } diff --git a/Matrix/inc/MatrixUtils.hpp b/Matrix/inc/MatrixUtils.hpp index d46f4bd..30e8279 100644 --- a/Matrix/inc/MatrixUtils.hpp +++ b/Matrix/inc/MatrixUtils.hpp @@ -18,6 +18,8 @@ namespace matrixUtilities void pad(Matrix & m,int step=1, double value=0.0); void productThread(const Matrix & m1, const Matrix & m2, int begin, int end, int other_dim, Matrix & m3); void sumThread(const Matrix & m1, const Matrix & m2, int begin, int end, int other_dim, Matrix & m3); + void lu_generator(const Matrix&, Matrix&, Matrix&); + void gauss_lu_solver(const Matrix&, const Matrix&, std::vector<double>&); std::vector<double> solveByGaussElimination( const Matrix& matrix, const std::vector<double>& rhs); //additional functions diff --git a/Matrix/src/MatrixUtils.cpp b/Matrix/src/MatrixUtils.cpp index bd60a80..ce80a6e 100644 --- a/Matrix/src/MatrixUtils.cpp +++ b/Matrix/src/MatrixUtils.cpp @@ -21,7 +21,57 @@ namespace matrixUtilities std::vector<double> solveByGaussElimination( const Matrix& matrix, const std::vector<double>& rhs) { // Fill Gauss Elimination - return std::vector<double>(); + std::vector<double> b = rhs; + std::vector<double> result; + result.reserve(rhs.size()); + //Assign input matrix + Matrix A = matrix; + + int n = A.numberOfRows(); + for(int i=0; i<n; i++) + for(int j=i+1; j<n;j++) + if (abs(A(i, i) < abs(A(j, i)))) + { + for (int k = 0; k < n; k++) + { + A(i, k) = A(i, k) + A(j, k); + A(j, k) = A(i, k) - A(j, k); + A(i, k) = A(i, k) - A(j, k); + + } + + b[i] = b[i] + b[j]; + b[j] = b[i] - b[j]; + b[i] = b[i] - b[j]; + } + + std::cout << A; + + //performing Gaussian elimination + for(int i=0; i<n;i++) + for (int j = i + 1; j < n; j++) + { + double f = A(j, i) / A(i, i); + for (int k = 0; k < n; k++) + { + A(j, k) = A(j, k) - f * A(i, k); + } + b[j] = b[j] - f * b[i]; + + } + //backward substitution + for (int i = n - 1; i >= 0; i--) + { + for (int j = i + 1; j < n; ++j) + { + b[i] -= (A(i, j)*b[j]); + } + + b[i] = b[i] / A(i, i); + } + + + return b; } Matrix matrixSum(const Matrix &m1, const Matrix &m2) { @@ -143,6 +193,86 @@ void sumThread(const Matrix &m1, const Matrix &m2, int begin, int end, int other for (size_t i = begin; i < end; i++) for (size_t j = 0; j < other_dim; j++) m3(i, j) = m1(i, j) + m2(i, j); +} +void lu_generator(const Matrix &matrix, Matrix &L, Matrix &U) +{ + + const int rows = L.numberOfRows(); + const int cols = L.numberOfCols(); + Matrix A = matrix; + + for (int i = 0; i < rows; i++) + { + //Upper triangular matrix + for (int k = i; k < rows; k++) + { + double sum = 0.0; + for (int j = 0; j < i; j++) + { + sum += L(i, j)*U(j, k); + } + + U(i, k) = A(i, k) - sum; + } + + //Lower triangular matrix + for (int k = i; k < rows; k++) + { + if (i == k) + L(i, i) = 1.0; + else + { + double sum = 0.0; + for (int j = 0; j < i; j++) + sum += L(k, j)*U(j, i); + + //Evaluating for L + L(k, i) = (A(k, i) - sum) / U(i, i); + + } + + } + + + + } + + +} +void gauss_lu_solver(const Matrix &L, const Matrix &U, std::vector<double>&b) +{ + std::vector<double> z; + z.resize(b.size()); + b[0] = b[0] / L(0, 0); + //solve for Ly=z by forward substitution + for (int i = 1; i < L.numberOfRows(); i++) + { + double sum = 0.0; + for (int j = 0; j < i; j++) + { + sum += L(i, j)*b[j]; + } + + + b[i] = (b[i] - sum); + + } + + + //Solving for Ux=z by backward substitution + + + for (int i = L.numberOfRows() - 1; i >= 0; i--) + { + for (int j = i+1; j < L.numberOfRows(); ++j) + { + b[i] -= (U(i, j)*b[j]); + } + + b[i] = b[i] / U(i, i); + } + + } void pad(Matrix &m, int step, double value) {