You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

167 lines
4.8 KiB

  1. #include <fstream>
  2. #include <iostream>
  3. #include <stdexcept>
  4. #include <vector>
  5. class Matrix {
  6. std::vector<std::vector<double>> m_data;
  7. public:
  8. Matrix() {}
  9. // Copy constructor combined with transpose
  10. Matrix(const Matrix& m, bool transpose = 0) {
  11. const std::vector<std::vector<double>>& data = m.GetData();
  12. if (transpose) {
  13. if (data.size()) {
  14. int rows = data[0].size(), cols = data.size();
  15. m_data.resize(rows);
  16. for (auto& i : m_data) i.resize(cols, 0);
  17. for (int i = 0; i < rows; ++i)
  18. for (int j = 0; j < cols; ++j) m_data[i][j] = data[j][i];
  19. }
  20. } else {
  21. m_data = data;
  22. }
  23. }
  24. // Move constructor
  25. Matrix(Matrix&& m) { m_data = std::move(m.GetData()); }
  26. // Constructor with size
  27. Matrix(size_t rows, size_t cols) {
  28. m_data.resize(rows);
  29. for (auto& i : m_data) i.resize(cols, 0);
  30. }
  31. // reference-Getter of m_data
  32. std::vector<std::vector<double>>& GetData() { return m_data; }
  33. // Getter of m_data
  34. const std::vector<std::vector<double>>& GetData() const { return m_data; }
  35. size_t GetRows() const { return m_data.size(); }
  36. size_t GetCols() const {
  37. if (m_data.size() == 0) return 0;
  38. return m_data[0].size();
  39. }
  40. // Matrix multiplication operator
  41. friend Matrix operator*(const Matrix& m1, const Matrix& m2);
  42. // Inverse matrix using Gaussian elimination
  43. static Matrix Inverse(const Matrix& m) {
  44. int rows = m.GetRows(), cols = m.GetCols();
  45. if (rows != cols)
  46. throw std::invalid_argument("Inverse is only for square matrices!");
  47. Matrix from(m), res(rows, rows);
  48. std::vector<std::vector<double>>&datares = res.GetData(),
  49. data = from.GetData();
  50. for (int i = 0; i < rows; ++i) datares[i][i] = 1;
  51. for (int i = 0; i < rows; ++i) {
  52. if (data[i][i] == 0.0)
  53. throw std::invalid_argument("No inverse for this matrix!");
  54. for (int j = 0; j < rows; ++j) {
  55. if (i != j) {
  56. double ratio = data[j][i] / data[i][i];
  57. for (int k = 0; k < rows; ++k)
  58. data[j][k] -= ratio * data[i][k];
  59. for (int k = 0; k < rows; ++k)
  60. datares[j][k] -= ratio * datares[i][k];
  61. }
  62. }
  63. }
  64. for (int i = 0; i < rows; ++i)
  65. for (int j = 0; j < rows; ++j) datares[i][j] /= data[i][i];
  66. return res;
  67. }
  68. void print(std::ostream& out) const {
  69. for (const auto& i : m_data) {
  70. for (const auto& j : i) out << j << ' ';
  71. out << '\n';
  72. }
  73. }
  74. };
  75. Matrix operator*(const Matrix& m1, const Matrix& m2) {
  76. size_t rows = m1.GetRows(), cols = m2.GetCols(), mid = m1.GetCols();
  77. if (mid != m2.GetRows()) throw std::invalid_argument("Couldn't multiply!");
  78. Matrix res(rows, cols);
  79. const std::vector<std::vector<double>>&data1 = m1.GetData(),
  80. &data2 = m2.GetData();
  81. std::vector<std::vector<double>>& datares = res.GetData();
  82. for (size_t i = 0; i < rows; ++i) {
  83. for (size_t j = 0; j < cols; ++j) {
  84. datares[i][j] = 0;
  85. for (size_t k = 0; k < mid; ++k) {
  86. datares[i][j] += data1[i][k] * data2[k][j];
  87. }
  88. }
  89. }
  90. return res;
  91. }
  92. inline std::ostream& operator<<(std::ostream& out, const Matrix& m) {
  93. m.print(out);
  94. return out;
  95. }
  96. int main() {
  97. std::ifstream inputtxt("input.txt");
  98. std::ofstream outputtxt("output.txt");
  99. #ifdef DEBUG
  100. std::istream& in = inputtxt;
  101. std::ostream& out = std::cout;
  102. #else
  103. std::istream& in = inputtxt;
  104. std::ostream& out = outputtxt;
  105. #endif
  106. out.precision(2);
  107. int n, m;
  108. in >> n >> m;
  109. Matrix A(m, n + 1), Y(m, 1);
  110. // input
  111. std::vector<std::vector<double>>&a = A.GetData(), &y = Y.GetData();
  112. for (int i = 0; i < m; ++i) {
  113. for (int j = 0; j < n + 1; ++j) {
  114. if (j == 0) a[i][j] = 1;
  115. if (j < n)
  116. in >> a[i][j + 1];
  117. else
  118. in >> y[i][0];
  119. }
  120. }
  121. out << "A:\n" << std::fixed << A << '\n';
  122. out << "b:\n" << std::fixed << Y << '\n';
  123. Matrix A_T(A, true), // A transpose
  124. A_TA(std::move(A_T * A)), // A transpose multiplied by A
  125. A_TA_inv(
  126. std::move(Matrix::Inverse(A_TA))), // inverse of the previous one
  127. A_TA_invA_T(std::move(A_TA_inv * A_T)), // multiplied by A transpose
  128. ans(std::move(A_TA_invA_T * Y)); // answer x
  129. out << "A_T*A:\n" << std::fixed << A_TA << '\n';
  130. out << "(A_T*A)_-1:\n" << std::fixed << A_TA_inv << '\n';
  131. out << "(A_T*A)_-1*A_T:\n" << std::fixed << A_TA_invA_T << '\n';
  132. out << "x:\n" << std::fixed << ans << '\n';
  133. }