Lesnic

Least square approximation my

Apr 17th, 2020
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.60 KB | None | 0 0
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <cstdio>
  4. #include <math.h>
  5.  
  6. #define GNUPLOT_NAME "C:\\gnuplot\\bin\\gnuplot.exe -persist"
  7.  
  8. using namespace std;
  9.  
  10. struct Point {
  11.     double x, y;
  12.     Point(int x, int y) : x(x), y(y) {}
  13. };
  14.  
  15. class Matrix {
  16. private:
  17.     int row, col;
  18.     double** matrix;
  19.  
  20. public:
  21.     Matrix(int n, int m) {
  22.         (*this).row = n;
  23.         (*this).col = m;
  24.         matrix = new double* [n];
  25.         for (int i = 0; i < n; i++) {
  26.             matrix[i] = new double[m];
  27.         }
  28.     }
  29.     void set(int i, int j, double res) {
  30.         matrix[i][j] = res;
  31.     }
  32.  
  33.     double getElement(int i, int j) {
  34.         return matrix[i][j];
  35.     }
  36.  
  37.     Matrix transpose() {
  38.         Matrix tr((*this).col, (*this).row);
  39.         for (int i = 0; i < (*this).col; i++)
  40.             for (int j = 0; j < (*this).row; j++)
  41.                 tr.matrix[i][j] = (*this).matrix[j][i];
  42.         return tr;
  43.     }
  44.  
  45.     Matrix inverse() {
  46.         Matrix now(this->row, this->col), res(this->row, this->col);
  47.         for (int i = 0; i < row; i++) {
  48.             for (int j = 0; j < col; j++) {
  49.                 now.matrix[i][j] = matrix[i][j];
  50.                 res.matrix[i][j] = i == j;
  51.             }
  52.         }
  53.  
  54.         for (int line = 0; line < row; line++) {
  55.             int maxLine = line;
  56.             for (int i = line + 1; i < now.row; i++) {
  57.                 if (abs(now.matrix[i][line]) > abs(now.matrix[maxLine][line]))
  58.                     maxLine = i;
  59.             }
  60.  
  61.             if (maxLine != line)
  62.                 now.permutation(line, maxLine, res);
  63.            
  64.             for (int i = line + 1; i < now.row; i++)
  65.                 now.elimination(line, i, res);
  66.         }
  67.  
  68.         for (int line = row - 1; line > 0; line--)
  69.             for (int i = line - 1; i >= 0; i--)
  70.                 now.elimination(line, i, res);
  71.         now.normalization(res);
  72.         return res;
  73.     }
  74.  
  75.     friend Matrix operator*(const Matrix& a, const Matrix& b) {
  76.         Matrix res(a.row, b.col);
  77.         for (int i = 0; i < res.row; i++) {
  78.             for (int j = 0; j < res.col; j++) {
  79.                 res.matrix[i][j] = 0;
  80.                 for (int k = 0; k < a.col; k++)
  81.                     res.matrix[i][j] += a.matrix[i][k] * b.matrix[k][j];
  82.             }
  83.         }
  84.         return res;
  85.     }
  86.  
  87.     friend ostream& operator<<(ostream& cout, const Matrix& base) {
  88.         for (int i = 0; i < base.row; i++) {
  89.             for (int j = 0; j < base.col; j++) {
  90.                 cout << fixed << setprecision(2) << base.matrix[i][j] + 1e-9;
  91.  
  92.                 if (j != base.col - 1)
  93.                     cout << " ";
  94.             }
  95.             cout << endl;
  96.         }
  97.         return cout;
  98.     }
  99.  
  100.     void permutation(int r1, int r2, Matrix& inverse) {
  101.         double* temp = *(matrix + r1);
  102.         *(matrix + r1) = *(matrix + r2);
  103.         *(matrix + r2) = temp;
  104.  
  105.         temp = *(inverse.matrix + r1);
  106.         *(inverse.matrix + r1) = *(inverse.matrix + r2);
  107.         *(inverse.matrix + r2) = temp;
  108.     }
  109.  
  110.     void elimination(int upperLine, int bottomLine, Matrix& inverse) {
  111.         double constant = matrix[bottomLine][upperLine] / matrix[upperLine][upperLine];
  112.  
  113.         if (matrix[bottomLine][upperLine] != 0) {
  114.  
  115.             for (int j = 0; j < col; j++) {
  116.                 matrix[bottomLine][j] -= matrix[upperLine][j] * constant;
  117.                 inverse.matrix[bottomLine][j] -= inverse.matrix[upperLine][j] * constant;
  118.             }
  119.         }
  120.     }
  121.  
  122.     void normalization(Matrix& inverse) {
  123.         for (int i = 0; i < row; i++) {
  124.             double constant = matrix[i][i];
  125.             for (int j = 0; j < col; j++) {
  126.                 matrix[i][j] /= constant;
  127.                 inverse.matrix[i][j] /= constant;
  128.             }
  129.         }
  130.     }
  131. };
  132.  
  133. double* approximation(Point* points) {
  134.     Matrix a(16, 3), b(16, 1);
  135.  
  136.     for (int i = 0; i < 16; i++) {
  137.         b.set(i, 0, points[i].y);
  138.  
  139.         for (int j = 0; j < 3; j++)
  140.             a.set(i, j, pow(points[i].x, j));
  141.     }
  142.    
  143.     Matrix at = a.transpose();
  144.     Matrix at_A = at * a;
  145.     Matrix at_A_inverse = at_A.inverse();
  146.     Matrix at_b = at * b;
  147.     Matrix res = at_A_inverse * at_b;
  148.     double* out = new double[3];
  149.     for (int i = 0; i < 3; i++)
  150.         out[2 - i] = res.getElement(i, 0);
  151.     return out;
  152. }
  153.  
  154. int main(){
  155.     FILE* pipe = _popen(GNUPLOT_NAME, "w");
  156.  
  157.     if (pipe != NULL) {
  158.         fprintf(pipe, "set xrange [-3:19]\nset yrange[4:15]\nset multiplot\n");
  159.        
  160.         Point points[16] = { {1, 6}, {2, 8}, {3, 11},
  161.         {5, 12}, {6, 11}, {7, 11},
  162.         {8, 12}, {9, 12}, {10, 11},
  163.         {11, 12}, {12, 12}, {12, 10},
  164.         {13, 9}, {14, 7}, {15, 10}, {16, 9}
  165.         };
  166.  
  167.         double* coef = approximation(points);
  168.  
  169.         fprintf(pipe, "plot '-' using 1:2 title ' %.2f * x^2 %s %.2f %s %.2f ' with lines linecolor 2\n", coef[0],
  170.             coef[1] > 0 ? "+" : "-", abs(coef[1]),
  171.             coef[1] > 0 ? "* x +" : "* x -", coef[2]);
  172.  
  173.         for (int i = 0; i < 2200 + 1; i++) {
  174.             double x = -3 + i / 100.0;
  175.             double y = coef[0] * pow(x, 2) + coef[1] * x + coef[2];
  176.             fprintf(pipe, "%f\t%f\n", x, y);
  177.         }
  178.         fprintf(pipe, "e\n");
  179.  
  180.         fprintf(pipe, "set nokey\nplot '-' using 1:2 title ' ' with points pointtype 5 pointsize 2\n");
  181.         for (int i = 0; i < 16; i++) {
  182.             fprintf(pipe, "%f\t%f\n", points[i].x, points[i].y);
  183.         }
  184.         fprintf(pipe, "e\n");
  185.  
  186.         fflush(pipe);
  187.  
  188.         _pclose(pipe);
  189.     }
  190. }
Add Comment
Please, Sign In to add comment