Advertisement
egraPA

Untitled

Apr 30th, 2024
872
1
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.56 KB | None | 1 0
  1. #include <iostream>
  2. #include <vector>
  3. // #include <cstdio>
  4. // #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <sstream>
  8. #include <iomanip>
  9.  
  10. using namespace std;
  11. FILE* pipe;
  12. class Matrix {
  13.     protected:
  14.         vector<vector<double>> data;
  15.         int n;
  16.         int m;
  17.     public:
  18.         Matrix() {
  19.             n = 0;
  20.             m = 0;
  21.         }
  22.         Matrix (int x, int y) {
  23.             n = x;
  24.             m = y;
  25.             data.assign(n, vector<double>(m));
  26.         }
  27.         Matrix& operator+ (const Matrix& matrix) {
  28.             if (matrix.m != m || matrix.n != n) {
  29.                 throw runtime_error("Error: the dimensional problem occurred");
  30.             }
  31.             Matrix *ans = new Matrix(n, m);
  32.             for (int i = 0; i < n; i++) {
  33.                 for (int j = 0; j < m; j++) {
  34.                     ans->data[i][j] = data[i][j] + matrix.data[i][j];
  35.                 }
  36.             }
  37.             return *ans;
  38.         }
  39.         Matrix& operator- (const Matrix& matrix) {
  40.             if (matrix.m != m || matrix.n != n) {
  41.                 throw runtime_error("Error: the dimensional problem occurred");
  42.             }
  43.             Matrix *ans = new Matrix(n, m);
  44.             for (int i = 0; i < n; i++) {
  45.                 for (int j = 0; j < m; j++) {
  46.                     ans->data[i][j] = data[i][j] - matrix.data[i][j];
  47.                 }
  48.             }
  49.             return *ans;
  50.         }
  51.         Matrix& operator* (const Matrix& matrix) {
  52.             if (matrix.n != m) {
  53.                 throw runtime_error("Error: the dimensional problem occurred");
  54.             }
  55.             Matrix *ans = new Matrix(n, matrix.m);
  56.             for (int i = 0; i < n; i++) {
  57.                 for (int j = 0; j < matrix.m; j++) {
  58.                     for (int k = 0; k < m; k++) {
  59.                         ans->data[i][j] += data[i][k]*matrix.data[k][j];
  60.                     }
  61.                 }
  62.             }
  63.             return *ans;
  64.         }
  65.         Matrix& transpose() {
  66.             Matrix *ans = new Matrix(m, n);
  67.             for (int i = 0; i < n; i++) {
  68.                 for (int j = 0; j < m; j++) {
  69.                     ans->data[j][i] = data[i][j];
  70.                 }
  71.             }
  72.             return *ans;
  73.         }
  74.         Matrix& operator| (const Matrix& matrix) {
  75.             if (matrix.n != n) {
  76.                 throw runtime_error("Error: the dimensional problem occurred");
  77.             }
  78.             Matrix *ans = new Matrix(n, matrix.m + m);
  79.             for (int i = 0; i < n; i++) {
  80.                 for (int j = 0; j < m; j++) {
  81.                     ans->data[i][j] = data[i][j];
  82.                 }
  83.                 for (int j = m; j < matrix.m + m; j++) {
  84.                     ans->data[i][j] = matrix.data[i][j-m];
  85.                 }
  86.             }
  87.             return *ans;
  88.         }
  89.         vector<double>& operator[] (int x) {
  90.             if (x >= n) {
  91.                 throw runtime_error("Error: index out of range");
  92.             }
  93.             return data[x];
  94.         }
  95.         friend istream& operator>> (istream &is, Matrix &matrix);
  96.         friend ostream& operator<< (ostream &os, Matrix &matrix);
  97.         double get(int i, int j) {
  98.             if (i >= n || j >= m) {
  99.                 throw out_of_range("Out of bound for get");
  100.             }
  101.             return data[i][j];
  102.         }
  103.         bool is_square() {
  104.             return n == m;
  105.         }
  106.         int get_n() {
  107.             return n;
  108.         }
  109.         int get_m() {
  110.             return m;
  111.         }
  112.         void normalize_diagonally() {
  113.             for (int i = 0; i < n; i++) {
  114.                 if (data[i][i] != 0) {
  115.                     for (int j = i + 1; j < m; j++) {
  116.                         data[i][j] /= data[i][i];
  117.                     }
  118.                     data[i][i] = 1;
  119.                 }
  120.             }
  121.         }
  122.         void separate() {
  123.             // for (int i = 0; i < n; i++) {
  124.             //     for (int j = 0; j < m - 1; j++) {
  125.             //         // if (abs(data[i][j]) < 0.005) {
  126.             //         //     // // cout << fixed << abs(data[i][j]) << ' ';
  127.             //         // } else
  128.             //         // // // cout << fixed << data[i][j] << ' ';
  129.             //     }
  130.             //     // cout << '\n';
  131.             // }
  132.             // for (int j = 0; j < n; j++) {
  133.             //     if (abs(data[j][m - 1]) < 0.005) {
  134.             //         // cout << fixed << abs(data[j][m - 1]) << ' ';
  135.             //     } else
  136.             //     // cout << fixed << data[j][m - 1] << ' ';
  137.             // }
  138.             // // cout << '\n';
  139.         }
  140.         void last() {
  141.             // for (int j = 0; j < n; j++) {
  142.             //     if (abs(data[j][m - 1]) < 0.005) {
  143.             //         // cout << fixed << abs(data[j][m - 1]) << ' ';
  144.             //     } else
  145.             //     // cout << fixed << data[j][m - 1] << ' ';
  146.             // }
  147.             // // cout << '\n';
  148.         }
  149.         Matrix& inverse();
  150. };
  151.  
  152. class Vector : public Matrix {
  153. public:
  154.     Vector(vector<double> input) : Matrix(input.size(), 1) {
  155.         for (int i = 0 ; i < input.size(); i++) {
  156.             data[i][0] = input[i];
  157.         }
  158.     }
  159. };
  160.  
  161. class LeastSquareAproxMatrix : public Matrix {
  162. public:
  163.     LeastSquareAproxMatrix(int m, vector<double> input) : Matrix(input.size(), m + 1) {
  164.         for (int i = 0; i < input.size(); i++) {
  165.             double pow = 1;
  166.             for (int j = 0; j <= m; j++) {
  167.                 data[i][j] = pow;
  168.                 pow *= input[i];
  169.             }
  170.         }
  171.     }
  172.  
  173. };
  174.  
  175. class SquareMatrix : public Matrix {
  176. public:
  177.     SquareMatrix() {
  178.         n = 0;
  179.         m = 0;
  180.     }
  181.     SquareMatrix(int x) : Matrix(x, x) {};
  182.     friend istream& operator>> (istream &is, SquareMatrix &matrix);
  183. };
  184.  
  185. class IdentityMatrix : public SquareMatrix {
  186. public:
  187.     IdentityMatrix() {
  188.         n = 0;
  189.         m = 0;
  190.     }
  191.     IdentityMatrix(int x) : SquareMatrix(x) {
  192.         for (int i = 0; i < x; i++) {
  193.             data[i][i] = 1;
  194.         }
  195.     }
  196. };
  197. class EliminationMatrix : public IdentityMatrix {
  198. public:
  199.     EliminationMatrix(Matrix& matrix, int j, int i) : IdentityMatrix(matrix.get_n()) {
  200.         data[j - 1][i - 1] = -matrix.get(j - 1, i - 1) / matrix.get(i - 1, i - 1);
  201.     }
  202. };
  203.  
  204. class PermutationMatrix : public IdentityMatrix {
  205. public:
  206.     PermutationMatrix(int x, int i, int j) : IdentityMatrix(x) {
  207.         data[j - 1][j - 1] = 0;
  208.         data[i - 1][i - 1] = 0;
  209.         data[i - 1][j - 1] = 1;
  210.         data[j - 1][i - 1] = 1;
  211.     }
  212. };
  213.  
  214. istream& operator>> (istream &is, SquareMatrix& matrix) {
  215.     is >> matrix.n;
  216.     matrix.m = matrix.n;
  217.     matrix.data.assign(matrix.n, vector<double>(matrix.m));
  218.     for (int i = 0; i < matrix.n; i++) {
  219.         for (int j = 0; j < matrix.m; j++) {
  220.             is >> matrix.data[i][j];
  221.         }
  222.     }
  223.     return is;
  224. }
  225.  
  226. istream& operator>> (istream &is, Matrix& matrix) {
  227.     is >> matrix.n >> matrix.m;
  228.     matrix.data.assign(matrix.n, vector<double>(matrix.m));
  229.     for (int i = 0; i < matrix.n; i++) {
  230.         for (int j = 0; j < matrix.m; j++) {
  231.             is >> matrix.data[i][j];
  232.         }
  233.     }
  234.     return is;
  235. }
  236. ostream& operator<< (ostream &os, Matrix& matrix) {
  237.     for (int i = 0; i < matrix.n; i++) {
  238.         for (int j = 0; j < matrix.m; j++) {
  239.             if (abs(matrix.data[i][j]) < 0.005) {
  240.                 os << fixed << abs(matrix.data[i][j]) << ' ';
  241.             } else
  242.             os << fixed << matrix.data[i][j] << ' ';
  243.         }
  244.         os << '\n';
  245.     }
  246.     return os;
  247. }
  248.  
  249.  
  250. bool gaus_elimination(Matrix& a, int &step) {
  251.     bool sign = 1;
  252.     for (int i = 0; i < a.get_n(); i++) {
  253.         double m = 0;
  254.         int m_i = 0;
  255.         for (int j = i; j < a.get_n(); j++) {
  256.             if (abs(a.get(j, i)) > abs(m))  {
  257.                 m = a.get(j, i);
  258.                 m_i = j;
  259.             }
  260.         }
  261.         if (m_i != i) {
  262.             // // cout << fixed  << "step #" << step << ": permutation" << '\n';
  263.             PermutationMatrix p(a.get_n(), m_i + 1, i + 1);
  264.             a = p * a;
  265.             // a.separate();
  266.             sign = !sign;
  267.             step++;
  268.         }
  269.         for (int j = i + 1; j < a.get_n(); j++) {
  270.             if (a.get(j, i) != 0) {
  271.                 // // cout << fixed  << "step #" << step << ": elimination" << '\n';
  272.                 step++;
  273.                 EliminationMatrix e(a, j + 1, i + 1);
  274.                 a = e * a;
  275.                 // a.separate();
  276.             }  
  277.         }
  278.     }
  279.     return sign;
  280. }
  281.  
  282. void gaus_back_elimination(Matrix& a, int &step) {
  283.     for (int i = a.get_n() - 1; i >= 0; i--) {
  284.         if (a.get(i, i) != 0) {
  285.             for (int j = i - 1 ; j >= 0; j--) {
  286.                 if (a.get(j, i) != 0) {
  287.                     step++;
  288.                     EliminationMatrix e(a, j + 1, i + 1);
  289.                     a = e * a;
  290.                     a.separate();
  291.                 }
  292.             }
  293.         }
  294.     }
  295. }
  296.  
  297. Matrix& Matrix::inverse() {
  298.     Matrix* ans = new Matrix(n, m);
  299.     IdentityMatrix I(n);
  300.     Matrix aug = *this | I;
  301.     int step = 1;
  302.     gaus_elimination(aug, step);
  303.     gaus_back_elimination(aug, step);
  304.     aug.normalize_diagonally();
  305.     for (int j = 0; j < aug.get_n(); j++) {
  306.         for (int i = aug.get_n(); i < aug.get_m(); i++) {
  307.             (*ans)[j][i - aug.get_n()] = aug.get(j, i);
  308.         }
  309.     }
  310.  
  311.     return *ans;
  312. }
  313.  
  314. class ColumnVector : public Matrix {
  315. public:
  316.     ColumnVector() {
  317.         n = 0;
  318.         m = 0;
  319.     }
  320.     ColumnVector(int x) {
  321.         n = x;
  322.         m = 1;
  323.         data.resize(n, vector<double>(1));
  324.     }
  325.     friend istream& operator>> (istream &is, ColumnVector &matrix);
  326.     friend ostream& operator<< (ostream &os, ColumnVector &matrix);
  327. };
  328.  
  329. istream& operator>> (istream &is, ColumnVector& matrix) {
  330.     is >> matrix.n;
  331.     matrix.m = 1;
  332.     matrix.data.resize(matrix.n,vector<double>(1));
  333.     for (int i = 0; i < matrix.n; i++) {
  334.         is >> matrix.data[i][0];
  335.     }
  336.     return is;
  337. }
  338. ostream& operator<< (ostream &os, ColumnVector& matrix) {
  339.     for (int i = 0; i < matrix.n; i++) {
  340.         os << matrix.data[i][0] << ' ';
  341.     }
  342.     os << '\n';
  343.     return os;
  344. }
  345.  
  346. bool is_singular( Matrix a) {
  347.     for (int i = 0; i < a.get_n(); i++) {
  348.         double m = 0;
  349.         int m_i = 0;
  350.         for (int j = i; j < a.get_n(); j++) {
  351.             if (abs(a.get(j, i)) > abs(m))  {
  352.                 m = a.get(j, i);
  353.                 m_i = j;
  354.             }
  355.         }
  356.         if (m_i != i) {
  357.             PermutationMatrix p(a.get_n(), m_i + 1, i + 1);
  358.             a = p * a;
  359.         }
  360.         for (int j = i + 1; j < a.get_n(); j++) {
  361.             if (a.get(j, i) != 0) {
  362.                 EliminationMatrix e(a, j + 1, i + 1);
  363.                 a = e * a;
  364.             }  
  365.         }
  366.     }
  367.     for (int i = 0; i < a.get_n(); i++) {
  368.         if (a.get(i, i) == 0) {
  369.             return 0;
  370.         }
  371.     }
  372.     return 1;
  373. }
  374. inline string to_s(double val) {
  375.     stringstream ss;
  376.     ss << fixed << setprecision(4) << val;
  377.     return ss.str();
  378. }
  379. int main() {
  380.     pipe = popen("/usr/bin/gnuplot -persist", "w");
  381.     double min_x = 1000000;
  382.     double max_x = -1000000;
  383.     double min_y = 100000000;
  384.     double max_y = -1000000;
  385.  
  386.     if (pipe == NULL) {
  387.        return 0;
  388.     }
  389.     int m;
  390.     cin >> m;
  391.     vector<double> data_a, data_b;
  392.     for (int i = 0; i < m; i++) {
  393.         double a, b;
  394.         cin >> a >> b;
  395.         data_a.push_back(a);
  396.         data_b.push_back(b);
  397.         min_x = min(min_x, a);
  398.         min_y = min(min_y, b);
  399.         max_x= max(max_x, a);
  400.         max_y = max(max_y, b);
  401.     }
  402.     int n;
  403.     cin >> n;
  404.     LeastSquareAproxMatrix A(n, data_a);
  405.     cout << A;
  406.     Vector b(data_b);
  407.     cout << b;
  408.     cout.precision(4);
  409.     Matrix c = (A.transpose() * A).inverse() * A.transpose() * b;
  410.     string s = "f(x)=" +to_s(c.get(c.get_n() - 1, 0)) + "*x**" + to_string(c.get_n() - 1);
  411.     for(int i = c.get_n() - 2; i > 0; i--) {
  412.         s += "+(" + to_s(c.get(i, 0)) + "*x**" + to_string(i) + ")";
  413.     }
  414.     s += "+(" + to_s(c.get(0, 0)) + ")";
  415.     fputs(s.c_str(), pipe);
  416.     fprintf(pipe, "\n");
  417.     fputs(("plot ["+ to_string(int(min_x - 1)) + ":" + to_string(int(max_x+ 1)) + "]["+ to_string(int (min_y - 1)) + ":" + to_string(int (max_y + 1)) + "] '-' using 1:2 title 'points' with points pointtype 5, f(x) title 'approximation' with lines").c_str(), pipe);
  418.     fprintf(pipe, "\n");
  419.     for (int i = 0; i < m; i++) {
  420.         fprintf(pipe, "%f\t%f\n", data_a[i], data_b[i]);
  421.     }
  422.     fprintf(pipe, "%s\n", "e");
  423.     cout << s << '\n';
  424.     cout << c;
  425.     pclose(pipe);
  426. }
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement