From 262894d00dc7a1ab63fe49e6bf76bc69da744c62 Mon Sep 17 00:00:00 2001 From: Ilya Grigorev Date: Mon, 7 Oct 2024 21:06:00 +0500 Subject: [PATCH] Revert "Deleted manual input function" This reverts commit fa123e0fb0cad1a209104dbf71069fbd3f51e92d. --- .gitignore | 34 ++++++ .vscode/settings.json | 9 ++ Makefile.txt | 35 ++++++ SimplexTASK | 1 - main.cpp | 72 +++++++++++ simplex.cpp | 229 ++++++++++++++++++++++++++++++++++ simplex.h | 20 +++ tools/elimination.cpp | 82 +++++++++++++ tools/elimination.h | 30 +++++ tools/math.cpp | 110 +++++++++++++++++ tools/math.h | 17 +++ tools/matrix.cpp | 277 ++++++++++++++++++++++++++++++++++++++++++ tools/matrix.h | 102 ++++++++++++++++ 13 files changed, 1017 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Makefile.txt delete mode 160000 SimplexTASK create mode 100644 main.cpp create mode 100644 simplex.cpp create mode 100644 simplex.h create mode 100644 tools/elimination.cpp create mode 100644 tools/elimination.h create mode 100644 tools/math.cpp create mode 100644 tools/math.h create mode 100644 tools/matrix.cpp create mode 100644 tools/matrix.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..95d0785 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +*.vscode +# Prerequisites +*.d +CMakeLists.txt +.idea +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..eeb0991 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "makefile.launchConfigurations": [ + { + "cwd": "/home/emil/Coding/Assignments/SimplexTASK", + "binaryPath": "/home/emil/Coding/Assignments/SimplexTASK/simplex.out", + "binaryArgs": [] + } + ] +} \ No newline at end of file diff --git a/Makefile.txt b/Makefile.txt new file mode 100644 index 0000000..e02affa --- /dev/null +++ b/Makefile.txt @@ -0,0 +1,35 @@ +GXX := g++ -std=c++20 +flags := -Wall -fsanitize=address +TOOLS := tools +BUILD := build + +build: + mkdir $(BUILD) + $(GXX) -c $(flags) $(TOOLS)/elimination.cpp -o $(BUILD)/elimination.obj + $(GXX) -c $(flags) $(TOOLS)/math.cpp -o $(BUILD)/math.obj + $(GXX) -c $(flags) $(TOOLS)/matrix.cpp -o $(BUILD)/matrix.obj + $(GXX) -c $(flags) simplex.cpp -o $(BUILD)/simplex.obj + $(GXX) -c $(flags) main.cpp -o $(BUILD)/main.obj + + $(GXX) $(BUILD)/*.obj $(flags) -o simplex.out + +$(BUILD)/elimination.obj: $(TOOLS)/elimination.cpp + $(GXX) -c $(flags) $(TOOLS)/elimination.cpp -o $(BUILD)/elimination.obj + +$(BUILD)/math.obj: $(TOOLS)/math.cpp + $(GXX) -c $(flags) $(TOOLS)/math.cpp -o $(BUILD)/math.obj + +$(BUILD)/matrix.obj: $(TOOLS)/matrix.cpp + $(GXX) -c $(flags) $(TOOLS)/matrix.cpp -o $(BUILD)/matrix.obj + +$(BUILD)/simplex.obj: simplex.cpp + $(GXX) -c $(flags) simplex.cpp -o $(BUILD)/simplex.obj + +$(BUILD)/main.obj: main.cpp + $(GXX) -c $(flags) main.cpp -o $(BUILD)/main.obj + +$(BUILD)/simplex.out: $(BUILD)/elimination.obj $(BUILD)/math.obj $(BUILD)/matrix.obj $(BUILD)/simplex.obj $(BUILD)/main.obj + $(GXX) $(BUILD)/*.obj $(flags) -o simplex.out + +clean: + rm -rf $(BUILD) diff --git a/SimplexTASK b/SimplexTASK deleted file mode 160000 index c7bc142..0000000 --- a/SimplexTASK +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c7bc14208163651cd65e39e00b37ae68b5909369 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..22a3ea5 --- /dev/null +++ b/main.cpp @@ -0,0 +1,72 @@ +#include +#include "tools/matrix.h" +#include "tools/math.h" +#include "simplex.h" + +void manualInput() { + int ZLength; + std::cout << "Write how many x's the objective function has:" << std::endl; + std::cin >> ZLength; + Vector Z = {}; +} +void printInitialInputs(Vector C, Matrix A, Vector b) { + +} +int main() { + // TODO: Initially should be positive + std::string doManual = ""; + std::cout << "Enable manual input? (y/n)" << std::endl; + std::cin >> doManual ; + if (doManual == "y" or doManual == "Y") { + manualInput(); + } else if (doManual == "n"){ + + } + + Vector C = {5, 4, 0, 0, 0, 0}; + + Matrix A = { + {6, 4, 1, 0, 0, 0}, + {1, 2, 0, 1, 0, 0}, + {-1, 1, 0, 0, 1, 0}, + {0, 1, 0, 0, 0, 1} + }; + + Vector b = {24, 6, 1, 2}; + + for (int i = 0; i < b.size(); i++) { + if (b[i] < 0) { + std::cout << "Error: method is not applicable" << std::endl; + return 1; + } + } + + //Matrix test = {{1, -1, -2}, {1, 1, -2}, {1, -1, 2}}; + + //showMatrix(test); + + + Result result = Simplex(C, A, b, 0.1, true); + + + + if(result.state == bounded) { + if(result.solution == nullptr) { + std::cout << "Error: no solution value is returned" << std::endl; + return 1; + } + std::cout << *result.solution << std::endl; + std::cout << result.objective_fucntion_value << std::endl; + + delete result.solution; + } + else { + std::cout << "Error: unbounded" << std::endl; + return 1; + } + //std::cout << "asdasd" << std::endl; + + return 0; +} + + diff --git a/simplex.cpp b/simplex.cpp new file mode 100644 index 0000000..d0dbf38 --- /dev/null +++ b/simplex.cpp @@ -0,0 +1,229 @@ +#include +#include +#include "tools/matrix.h" +#include "tools/math.h" +#include "tools/elimination.h" + +enum solver_state { + unbounded, + bounded +}; + +struct Result { + solver_state state; + Vector *solution; + double objective_function_value; +}; + + + +Result Simplex(Vector C, Matrix A, Vector b, double eps = 0.01, bool maximize=true) { + if (maximize == true) { + for (int i = 0; i < C.size(); i++) { + C[i] = -C[i]; + } + } + Result result{}; + Matrix generalMatrix = createGeneralMatrix(A, C, b); + std::cout << "Before:" << std::endl; + showMatrix(generalMatrix); + std::vector basicVars(generalMatrix.getRows()); + basicVars[0] = -1; + + for (size_t i = 1; i < basicVars.size(); i++) { + basicVars[i] = static_cast(basicVars.size()) + i; + } + int iterationCount = 0; + while (true) { + //3 + iterationCount++; + std::cout << "Iteration: "; + std::cout << iterationCount << std::endl; + int pivot_column_index = 0; + if (maximize) { + + pivot_column_index = min_index(generalMatrix[0]); + + if (generalMatrix[0][pivot_column_index] >= 0) { + DestroyMatrix destroyedGeneralMatrix = disassembleGeneralMatrix(generalMatrix); + Matrix _A = destroyedGeneralMatrix.A; + Vector _C = destroyedGeneralMatrix.C; + Vector _b = destroyedGeneralMatrix.b; + + result.state = bounded; + result.solution = new Vector(C.size()); + for (int i = 0; i < C.size(); i++) { + result.solution->operator[](i) = 0; + } + for (size_t i = 1; i < basicVars.size(); i++) { + if (basicVars[i] <= C.size()) { + result.solution->operator[](basicVars[i]) = _b[i]; + } + } + result.objective_function_value = _C[_C.size()]; + return result; + } + } + + if (maximize == false) { + pivot_column_index = max_index(generalMatrix[0]); + + if (generalMatrix[0][pivot_column_index] < 0) { + DestroyMatrix destroyedGeneralMatrix = disassembleGeneralMatrix(generalMatrix); + Matrix _A = destroyedGeneralMatrix.A; + Vector _C = destroyedGeneralMatrix.C; + Vector _b = destroyedGeneralMatrix.b; + + result.state = bounded; + result.solution = new Vector(C.size()); + for (int i = 0; i < C.size(); i++) { + result.solution->operator[](i) = 0; + } + for (size_t i = 1; i < basicVars.size(); i++) { + if (basicVars[i] <= C.size()) { + result.solution->operator[](basicVars[i]) = _b[i]; + } + } + result.objective_function_value = _C[_C.size()]; + return result; + } + } + + + //4 + Vector ratio_vector(generalMatrix.getRows()); + for (int i = 1; i < generalMatrix.getRows(); i++) { + if (generalMatrix[i][pivot_column_index] != 0) { + ratio_vector[i] = generalMatrix[i][generalMatrix.getColumns() - 1] / generalMatrix[i][pivot_column_index]; + } else { + ratio_vector[i] = 0; + } + } + ratio_vector[0] = 0; + + int pivot_row_index = min_index_positive(ratio_vector); + + basicVars[pivot_row_index] = pivot_column_index; + + //5 + elimination(generalMatrix, pivot_row_index, pivot_column_index); + std::cout << "After:" << std::endl; + showMatrix(generalMatrix); + + if (maximize) { + bool thereIsNegative = false; + for (int j = 0; j < generalMatrix.getColumns()-1; ++j) { + if (generalMatrix[0][j] < 0) { + thereIsNegative = true; + } + } + if (thereIsNegative) { + for (int j = 0; j < generalMatrix.getColumns()-1; ++j) { + if (generalMatrix[0][j] > 0) { + if (generalMatrix[0][j] < (eps * (-1))) { + showMatrix(generalMatrix); + std::cout << generalMatrix[0][j] << std::endl; + return result; + } + } + } + } + } + if (maximize == false) { + bool thereIsPositive = false; + for (int j = 0; j < generalMatrix.getColumns()-1; ++j) { + if (generalMatrix[0][j] > 0) { + thereIsPositive = true; + } + } + if (thereIsPositive) { + for (int j = 0; j < generalMatrix.getColumns()-1; ++j) { + if (generalMatrix[0][j] > 0) { + if (generalMatrix[0][j] < eps) { + showMatrix(generalMatrix); + std::cout << generalMatrix[0][j] << std::endl; + return result; + } + } + } + } + } + + + + } + + return result; + + /* + Result result; + std::vector basicVars(A.getColumns() - A.getRows()); + basicVars[0] = -1; + + for (int i = 1; i < basicVars.size(); i++) { + basicVars[i] = static_cast(basicVars.size()) + i; + } + + int kc = 0; + double temp = A[0][0]; + for (int j = 0; j< A.getColumns(); j++) { + if (A[0][j] < temp) { + temp = A[0][j]; + kc = j; + } + } + + if (A[0][kc] >= 0) { + result.state = unbounded; + result.solution = new Vector(C.getRows()); + for (int i = 0; i < C.getRows(); i++) { + result.solution->operator[](i) = 0; + } + for (int i = 1; i < basicVars.size(); i++) { + if (basicVars[i] <= C.getRows()) { + (*result.solution)[basicVars[i]] = b.getRows() - 1; + } + } + result.objective_fucntion_value = b[0]; + + } + */ +} + +/* +Function_name(C, A, b, eps = eps_default) + +Input: +- C: A vector of coefficients of the objective function +- A: A matrix of coefficients of the constraint functions +- b: A vector of right-hand side values +- eps: Approximation accuracy (optional, default = eps_default) + +Steps: +1. Print the optimization problem: + - max (or min) z = C[0] * x1 + C[1] * x2 + ... + C[n] * xn + - subject to the constraints: + - A[0] * x <= b[0] + - A[1] * x <= b[1] + - ... + - A[m] * x <= b[m] + +2. Initialize: + - Form the initial tableau by introducing slack variables to convert inequalities into equalities. + +3. Iteratively apply the Simplex method: + - Step 1: Identify the entering variable (most negative coefficient in the objective row). + - Step 2: Identify the leaving variable (smallest positive ratio of RHS to pivot column). + - Step 3: Perform pivot operations to update the tableau. + +4. Check for optimality or unboundedness: + - If all coefficients in the objective function row are non-negative, the solution is optimal. + - If no leaving variable exists, the problem is unbounded. + +5. Return: + - solver_state: {solved, unbounded} + - x*: Optimal vector of decision variables (if solved) + - z: Maximum (or minimum) value of the objective function (if solved) + +End Function +*/ diff --git a/simplex.h b/simplex.h new file mode 100644 index 0000000..bb35dc4 --- /dev/null +++ b/simplex.h @@ -0,0 +1,20 @@ +#ifndef SIMPLEX_H +#define SIMPLEX_H + +#include +#include "tools/matrix.h" + +enum solver_state { + unbounded, + bounded +}; + +struct Result { + solver_state state; + Vector *solution; + double objective_fucntion_value; +}; + +Result Simplex(Vector C, Matrix A, Vector b, double eps = 0.01, bool maximize = true); + +#endif // SIMPLEX_H \ No newline at end of file diff --git a/tools/elimination.cpp b/tools/elimination.cpp new file mode 100644 index 0000000..9b4ee4c --- /dev/null +++ b/tools/elimination.cpp @@ -0,0 +1,82 @@ +#include "elimination.h" +#include "math.h" + +FracturedMatrix::FracturedMatrix(const FracturedMatrix& other) : A(other.A), C(other.C), b(other.b), pivot_column_index(other.pivot_column_index), pivot_row_index(other.pivot_row_index) {} +FracturedMatrix::FracturedMatrix(Matrix A, Vector C, Vector b, int pivot_column_index, int pivot_row_index) : A(A), C(C), b(b), pivot_column_index(pivot_column_index), pivot_row_index(pivot_row_index) {} +FracturedMatrix& FracturedMatrix::operator=(const FracturedMatrix& other) { + A = other.A; + C = other.C; + b = other.b; + pivot_column_index = other.pivot_column_index; + pivot_row_index = other.pivot_row_index; + return *this; +} + +DestroyMatrix disassembleGeneralMatrix(Matrix& generalMatrix) { + int rows = generalMatrix.getRows(); + int cols = generalMatrix.getColumns(); + + Matrix A(rows - 1, cols - 1); + Vector C(cols - 1); + Vector b(rows - 1); + + for (int j = 0; j < cols - 1; ++j) { + C[j] = generalMatrix[0][j]; + } + + for (int i = 1; i < rows; ++i) { + b[i - 1] = generalMatrix[i - 1][cols - 1]; + } + + for (int i = 1; i < rows; ++i) { + for (int j = 0; j < cols - 1; ++j) { + A[i - 1][j] = generalMatrix[i][j]; + } + } + + return {A, C, b}; +} + +Matrix createGeneralMatrix(Matrix& A, Vector& C, Vector& b) { + Matrix generalMatrix(A.getRows() + 1, A.getColumns() + 1); + for (int i = 0; i < A.getColumns(); i++) { + generalMatrix[0][i] = C[i]; + } + + // For objective function (j=0) the value is set to zero automatically + for (int j = 1; j < A.getRows() + 1; j++) { + generalMatrix[j][A.getColumns()] = b[j-1]; + } + + for (int i = 0; i < A.getRows(); i++) { + for (int j = 0; j < A.getColumns(); j++) { + generalMatrix[i + 1][j] = A[i][j]; + } + } + + return generalMatrix; +} + +void elimination(Matrix& generalMatrix, int pivot_row_index, int pivot_column_index) { + + int rows = generalMatrix.getRows(); + int cols = generalMatrix.getColumns(); + + double pivotElement = generalMatrix[pivot_row_index][pivot_column_index]; + + for (int j = 0; j < cols; ++j) { + generalMatrix[pivot_row_index][j] /= pivotElement; + } + + for (int i = 0; i < rows; ++i) { + if (i == pivot_row_index) + continue; + + double pivotColumnCoefficient = generalMatrix[i][pivot_column_index]; + + for (int j = 0; j < cols; ++j) { + generalMatrix[i][j] -= pivotColumnCoefficient * generalMatrix[pivot_row_index][j]; + } + } +} + diff --git a/tools/elimination.h b/tools/elimination.h new file mode 100644 index 0000000..2c71100 --- /dev/null +++ b/tools/elimination.h @@ -0,0 +1,30 @@ +#ifndef ELIMINATION_H +#define ELIMINATION_H + +#include "matrix.h" + + +struct FracturedMatrix { + Matrix A; + Vector C; + Vector b; + int pivot_column_index; + int pivot_row_index; + FracturedMatrix() = default; + FracturedMatrix(const FracturedMatrix& other); + FracturedMatrix(Matrix A, Vector C, Vector b, int pivot_column_index, int pivot_row_index); + FracturedMatrix& operator=(const FracturedMatrix& other); +}; + +struct DestroyMatrix { + Matrix A; + Vector C; + Vector b; +}; + +DestroyMatrix disassembleGeneralMatrix(Matrix& generalMatrix); +void elimination(Matrix&, int pivot_row_index, int pivot_column_index); +Matrix createGeneralMatrix(Matrix& A, Vector& C, Vector& b); + + +#endif //ELIMINATION_H diff --git a/tools/math.cpp b/tools/math.cpp new file mode 100644 index 0000000..db43841 --- /dev/null +++ b/tools/math.cpp @@ -0,0 +1,110 @@ +#include "math.h" + +double min(Vector vector) { + double temp = vector[0]; + for (int j = 0; j < vector.size(); j++) { + if (vector[j] < temp) { + temp = vector[j]; + } + } + return temp; +} + +double max(Vector vector) { + double temp = vector[0]; + for (int j = 0; j < vector.size(); j++) { + if (vector[j] > temp) { + temp = vector[j]; + } + } + return temp; +} + +int min_index_positive(Vector vector) { + int i = 0; + while (i < vector.size() && vector[i] <= 0) { + ++i; + } + if (i >= vector.size()) { + throw std::runtime_error("No positive min found"); + } + int temp_index = i; + double temp = vector[i]; + + for (int j = i + 1; j < vector.size(); j++) { + if (vector[j] < temp && vector[j] > 0) { + temp_index = j; + temp = vector[j]; + } + } + return temp_index; +} + +int min_index(Vector vector) { + int temp_index = 0; + double temp = vector[0]; + for (int j = 0; j < vector.size(); j++) { + if (vector[j] < temp) { + temp_index = j; + temp = vector[j]; + } + } + return temp_index; +} + +int max_index(Vector vector) { + int temp_index = 0; + double temp = vector[0]; + for (int j = 0; j < vector.size(); j++) { + if (vector[j] > temp) { + temp_index = j; + temp = vector[j]; + } + } + return temp_index; +} + +double min(std::vector array) { + double temp = array[0]; + for (size_t i = 1; i < array.size(); i++) { + if (array[i] < temp) { + temp = array[i]; + } + } + return temp; +} + +double max(std::vector array) { + double temp = array[0]; + for (size_t i = 1; i < array.size(); i++) { + if (array[i] > temp) { + temp = array[i]; + } + } + return temp; +} + +int min_index(std::vector array) { + int temp_index = 0; + double temp = array[0]; + for (size_t i = 1; i < array.size(); i++) { + if (array[i] < temp) { + temp_index = i; + temp = array[i]; + } + } + return temp_index; +} + + +int max_index(std::vector array) { + int temp_index = 0; + double temp = array[0]; + for (size_t i = 1; i < array.size(); i++) { + if (array[i] > temp) { + temp_index = i; + temp = array[i]; + } + } + return temp_index; +} \ No newline at end of file diff --git a/tools/math.h b/tools/math.h new file mode 100644 index 0000000..ee5efee --- /dev/null +++ b/tools/math.h @@ -0,0 +1,17 @@ +#ifndef MATH_H +#define MATH_H + +#include +#include "matrix.h" + +double min(Vector vector); +double max(Vector vector); +int min_index(Vector vector); +int min_index_positive(Vector vector); +int max_index(Vector vector); +double min(std::vector array); +double max(std::vector array); +int min_index(std::vector array); +int max_index(std::vector array); + +#endif // MATH_H \ No newline at end of file diff --git a/tools/matrix.cpp b/tools/matrix.cpp new file mode 100644 index 0000000..cac1d78 --- /dev/null +++ b/tools/matrix.cpp @@ -0,0 +1,277 @@ +#include "matrix.h" + +void showMatrix(Matrix matrix) { + int maxNumberLength = 1; + for (size_t y = 0; y < matrix.getRows(); y++) { + for (size_t x = 0; x < matrix.getColumns(); x++) { + if (std::to_string(matrix[y][x]).length() > maxNumberLength) { + maxNumberLength = std::to_string(matrix[y][x]).length(); + } + } + } + //std::cout << maxNumberLength << std::endl; + std::cout << std::endl; + for (size_t y = 0; y < matrix.getRows(); y++) { + std::string row = ""; + for (size_t x = 0; x < matrix.getColumns(); x++) { + std::string strNumber = std::to_string(matrix[y][x]); + bool spaceRight = true; + while (strNumber.length() < maxNumberLength) { + if (spaceRight) { + strNumber += " "; + } + else { + strNumber = " " + strNumber; + } + spaceRight = !spaceRight; + strNumber = "" + strNumber; + + } + if (matrix[y][x] == 0) { + row += "[\033[0m" + strNumber + "\033[0m] "; + } + else if(matrix[y][x] > 0) { + row += "[\033[32m" + strNumber + "\033[0m] "; + }else { + row += "[\033[31m" + strNumber + "\033[0m] "; + } + + } + std::cout << row << std::endl; + } + std::cout << std::endl; +} + +Vector::Vector(int n) { + rows = n; + columns = 1; + vector.resize(n); +} + +Vector::Vector(const Vector& other) { + rows = other.rows; + columns = other.columns; + vector = other.vector; +} + +Vector::Vector(std::initializer_list init) { + rows = init.size(); + columns = 1; + vector = std::vector(rows); + + auto it = init.begin(); + + for (size_t i = 0; i < init.size(); ++i) { + vector[i] = *it++; + } +} + +int Vector::size() const { + return rows; +} + +double& Vector::operator[](int row) { + return vector[row]; +} + +Vector& Vector::operator=(const Vector& other) { + rows = other.rows; + columns = other.columns; + vector = other.vector; + return *this; +} + +Vector Vector::operator+(Vector& other) { + if (rows != other.rows) { + throw std::runtime_error("Error: the dimensional problem occurred"); + } + Vector result(rows); + for (int i = 0; i < rows; ++i) { + result[i] = vector[i] + other[i]; + } + + return result; +} + +Vector Vector::operator-(Vector& other) { + if (rows != other.rows) { + throw std::runtime_error("Error: the dimensional problem occurred"); + } + Vector result(rows); + for (int i = 0; i < rows; ++i) { + result[i] = vector[i] - other[i]; + } + + return result; +} + +std::istream& operator>>(std::istream& cin, Vector& vectorObj) { + for (int i = 0; i < vectorObj.rows; ++i) { + cin >> vectorObj[i]; + } + return cin; +} + +std::ostream& operator<<(std::ostream& cout, Vector& vectorObj) { + for (int i = 0; i < vectorObj.rows; ++i) { + if (i == vectorObj.rows - 1) { + cout << vectorObj[i] << std::endl; + } + else { + cout << vectorObj[i] << ' '; + } + } + return cout; +} + +Matrix::Matrix(int n, int m) { + rows = n; + columns = m; + matrix.resize(n, Vector(m)); + for (auto& row : matrix) { + row = Vector(m); + } +} + +Matrix::Matrix(const Matrix& other) { + rows = other.rows; + columns = other.columns; + matrix = other.matrix; +} + +Matrix::Matrix(std::initializer_list> init) { + rows = init.size(); + auto it = init.begin(); + columns = it->size(); + matrix = std::vector(rows, Vector(columns)); + + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < columns; ++j) { + matrix[i][j] = it->operator[](j); + } + ++it; + } +} + +int Matrix::getRows() const { + return rows; +} + +int Matrix::getColumns() const { + return columns; +} + +Vector& Matrix::operator[](int row) { + return matrix[row]; +} + +Matrix& Matrix::operator=(const Matrix& other) { + rows = other.rows; + columns = other.columns; + matrix = other.matrix; + return *this; +} + +Matrix Matrix::operator+(Matrix& other) const { + if (rows != other.rows || columns != other.columns) { + throw std::runtime_error("Error: the dimensional problem occurred"); + } + Matrix result(rows, columns); + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < columns; ++j) { + auto x = matrix[i]; + auto y = other[i]; + result[i][j] = x[j] + y[j]; + } + } + + return result; +} + +Matrix Matrix::operator-(Matrix& other) const { + if (rows != other.rows || columns != other.columns) { + throw std::runtime_error("Error: the dimensional problem occurred"); + } + Matrix result(rows, columns); + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < columns; ++j) { + auto x = matrix[i]; + auto y = other[i]; + result[i][j] = x[j] - y[j]; + } + } + + return result; +} + +Matrix Matrix::operator*(Matrix& other) const { + if (columns != other.rows) { + throw std::runtime_error("Error: the dimensional problem occurred"); + } + + Matrix result(rows, other.columns); + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < other.columns; ++j) { + result[i][j] = 0; + for (int k = 0; k < columns; ++k) { + auto x = matrix[i]; + auto y = other[k]; + result[i][j] += x[k] * y[j]; + } + } + } + + return result; +} + +Vector Matrix::operator*(Vector other) const { + if (columns != other.size()) { + throw std::runtime_error("Error: the dimensional problem occurred"); + } + + Vector result(rows); + for (int i = 0; i < rows; ++i) { + result[i] = 0; + for (int k = 0; k < columns; ++k) { + auto x = matrix[i]; + result[i] += x[k] * other[k]; + } + } + + return result; +} + +Matrix Matrix::transpose() const { + Matrix result(columns, rows); + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < columns; ++j) { + auto x = matrix[i]; + result[j][i] = x[j]; + } + } + + return result; +} + +std::istream& operator>>(std::istream& cin, Matrix& matrixObj) { + for (int i = 0; i < matrixObj.rows; ++i) { + for (int j = 0; j < matrixObj.columns; ++j) { + cin >> matrixObj[i][j]; + } + } + return cin; +} + +std::ostream& operator<<(std::ostream& cout, Matrix& matrixObj) { + for (int i = 0; i < matrixObj.rows; ++i) { + for (int j = 0; j < matrixObj.columns; ++j) { + if (j == matrixObj.columns - 1) { + cout << matrixObj[i][j] << std::endl; + } + else { + cout << matrixObj[i][j] << ' '; + } + } + } + return cout; +} diff --git a/tools/matrix.h b/tools/matrix.h new file mode 100644 index 0000000..af29d65 --- /dev/null +++ b/tools/matrix.h @@ -0,0 +1,102 @@ +#ifndef TOOLS_MATRIX_H +#define TOOLS_MATRIX_H + +// some functions for matrix interaction +#include +#include + +/** +* Vector is a class to represent +* a column vector with n rows. +*/ + + +class Vector { +protected: + // Number of rows in vector + int rows; + // Number of columns in vector + int columns; + // Matrix representation as vector of vectors of integers + std::vector vector; +public: + Vector(int n); + + Vector(const Vector& other); + + Vector(std::initializer_list); + + /* Getter for the number of rows */ + int size() const; + + double& operator[](int row); + + Vector& operator=(const Vector& other); + + Vector operator+(Vector& other); + + Vector operator-(Vector& other); + + /* Input operator reads element of vector */ + friend std::istream& operator>>(std::istream& cin, Vector& vectorObj); + + /* Output operator prints elements of the vector + * in a row separated with a space (no space at the end of the line) + */ + friend std::ostream& operator<<(std::ostream& cout, Vector& vectorObj); +}; + +/** +* Class Matrix represents +* a matrix of size n x m +* of type integer. +*/ +class Matrix { +protected: + // Number of rows in matrix + int rows; + // Number of columns in matrix + int columns; + // Matrix representation as vector of vectors of integers + std::vector matrix; +public: + Matrix(int n, int m); + + Matrix(const Matrix& other); + + Matrix(std::initializer_list>); + + /* Getter for the number of rows */ + int getRows() const; + + /* Getter for the number of columns */ + int getColumns() const; + + Vector& operator[](int row); + + Matrix& operator=(const Matrix& other); + + Matrix operator+(Matrix& other) const; + + Matrix operator-(Matrix& other) const; + + Matrix operator*(Matrix& other) const; + + /* Matrix-Vector multiplication */ + Vector operator*(Vector other) const; + + /* Produces transposed version of the matrix */ + Matrix transpose() const; + + /* Input operator reads element of matrix row by row */ + friend std::istream& operator>>(std::istream& cin, Matrix& matrixObj); + + /* Output operator prints elements of the matrix + * row by row separated with a space (no space at the end of each line) + */ + friend std::ostream& operator<<(std::ostream& cout, Matrix& matrixObj); +}; + +void showMatrix(Matrix); + +#endif // TOOLS_MATRIX_H