vadimk772336

Untitled

Apr 25th, 2020
631
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.25 KB | None | 0 0
  1. #include <iostream>
  2. #include <math.h>
  3. #include <cmath>
  4. #include <stdlib.h>
  5. #include <fstream>
  6. using namespace std;
  7.  
  8. //Нормирует вектор y размерности N
  9. void normalize(double* y, int N)
  10. {
  11.     int i;
  12.     double norm, result = 0;
  13.     for (i = 0; i < N; i++)
  14.         result += y[i] * y[i];
  15.     norm = sqrt(result);
  16.  
  17.     for (i = 0; i < N; i++)
  18.         y[i] = y[i] / norm;
  19. }
  20.  
  21. //Записывает в res результат умножения матрицы А на столбец х
  22. void Multiply_Ax(double** A, double* x, double* res, int N)
  23. {
  24.     int i, j;
  25.  
  26.     for (i = 0; i < N; i++) {
  27.         res[i] = 0;
  28.         for (j = 0; j < N; j++) {
  29.             res[i] += A[i][j] * x[j];
  30.         }
  31.     }
  32. }
  33.  
  34. void Gauss_Seidel_method(double** A, double* B, double* x, int N, double deviation)
  35. {
  36.     int i, j, k = 0;
  37.     double tmp, sum;
  38.  
  39.     //Перестановка строк в случае, если есть нулевой диаг элемент
  40.     for (i = 0; i < N; i++) {
  41.         if (A[i][i] == 0) {
  42.             for (j = i + 1; j < N; j++) {
  43.                 if (A[j][i] != 0) {
  44.                     for (k = 0; k < N; k++) {
  45.                         tmp = A[j][k];
  46.                         A[j][k] = A[i][k];
  47.                         A[i][k] = tmp;
  48.                     }
  49.                     tmp = x[i];
  50.                     x[i] = x[j];
  51.                     x[j] = tmp;
  52.                     tmp = B[i];
  53.                     B[i] = B[j];
  54.                     B[j] = tmp;
  55.                 }
  56.             }
  57.         }
  58.     }
  59.  
  60.     //Реализация алгоритма
  61.     k = 0;
  62.     int flag = 1;
  63.     while (flag > 0 && k < 300) {
  64.         flag = 0;
  65.         for (i = 0; i < N; i++) {
  66.             for (j = 0; j < N; j++) {
  67.                 if (j != i)
  68.                     sum += A[i][j] * x[j];
  69.             }
  70.             tmp = B[i];
  71.             x[i] = (tmp - sum) / A[i][i];
  72.             sum = 0;
  73.         }
  74.         k++;
  75.  
  76.         //Проверка невязки (B - A*x')
  77.         for (i = 0; i < N; i++) {
  78.             tmp = B[i];
  79.             for (j = 0; j < N; j++)
  80.                 tmp -= A[i][j] * x[j];
  81.  
  82.             if (abs(tmp) > deviation) {
  83.                 flag = 1;
  84.             }
  85.         }
  86.     }
  87. }
  88.  
  89. void Gradient_descent_method(double** A, double* B, double* x, int N, double deviation)
  90. {
  91.     int i, j, k, flag = 1;
  92.     double tau = 0, sum = 0;
  93.     double denominator = 0, numerator = 0, tmp;
  94.     double* r = new double[N];
  95.     double* res = new double[N];
  96.  
  97.     k = 0;
  98.     while (flag > 0 && k < 300) {
  99.         flag = 0;
  100.  
  101.         for (i = 0; i < N; i++) {
  102.             sum = 0;
  103.             for (j = 0; j < N; j++)
  104.                 sum += A[i][j] * x[j];
  105.             //cout << "sum " << sum << " b[i] " << B[i] << endl;
  106.             r[i] = sum - B[i];
  107.             //cout << "r[" << i << "] = " << r[i] << endl;
  108.         }
  109.  
  110.         Multiply_Ax(A, r, res, N);
  111.         for (j = 0; j < N; j++) {
  112.             //cout << "res " << res[j] << endl;
  113.             denominator += res[j] * r[j];
  114.             numerator += r[j] * r[j];
  115.         }
  116.         //cout << "denominator = " << denominator << endl;
  117.         //cout << "numerator = " << numerator << endl;
  118.         tau = numerator / denominator;
  119.         denominator = 0;
  120.         numerator = 0;
  121.         //cout << "tau " << tau << endl;
  122.  
  123.         for (i = 0; i < N; i++) {
  124.             x[i] -= tau * r[i];
  125.             //cout << "x[" << i << "] = " << x[i] << endl;
  126.         }
  127.         //Проверка невязки (B - A*x' = 0)
  128.         for (i = 0; i < N; i++) {
  129.             tmp = B[i];
  130.             for (j = 0; j < N; j++)
  131.                 tmp -= A[i][j] * x[j];
  132.             // cout << "difference : " << tmp << endl;
  133.             if (abs(tmp) > deviation)
  134.                 flag = 1;
  135.             break;
  136.         }
  137.         k++;
  138.     }
  139. }
  140.  
  141. //Степенной метод нахождения макс собств числа
  142. double Power_iteration(double** A, int N, double deviation)
  143. {
  144.     int flag = 1, i;
  145.     double lambda;
  146.  
  147.     double* x = new double[N];
  148.     double* y = new double[N];
  149.     for (i = 0; i < N; i++)
  150.         x[i] = 1.0;
  151.  
  152.     while (flag > 0) {
  153.         flag = 0;
  154.  
  155.         Multiply_Ax(A, x, y, N);
  156.  
  157.         for (i = 0; i < N; i++)
  158.             if (abs(y[i] - lambda * x[i]) > deviation)
  159.                 flag = 1;
  160.  
  161.         lambda = 0;
  162.         for (i = 0; i < N; i++)
  163.             lambda += x[i] * y[i];
  164.  
  165.         normalize(y, N);
  166.         for (i = 0; i < N; i++)
  167.             x[i] = y[i];
  168.     }
  169.     return lambda;
  170. }
  171.  
  172. void Gaussian_elimination(double** A, double* B, double* x, int n)
  173. {
  174.  
  175.     double* tmp_mas;
  176.     tmp_mas = new double[n];
  177.  
  178.     int i, j, k, index;
  179.     double tmp, max, r;
  180.  
  181.     for (j = 0; j <= n - 2; j++) {
  182.  
  183.         max = abs(A[j][j]);
  184.         index = j;
  185.  
  186.         for (i = index + 1; i <= n - 1; i++) {
  187.             if (abs(A[i][index]) > max) {
  188.                 max = abs(A[i][index]);
  189.                 index = i;
  190.             }
  191.         }
  192.  
  193.         if (index != j) {
  194.             for (i = 0; i <= n - 1; i++) {
  195.                 tmp_mas[i] = A[j][i];
  196.                 A[j][i] = A[index][i];
  197.                 A[index][i] = tmp_mas[i];
  198.             }
  199.             tmp = B[j];
  200.             B[j] = B[index];
  201.             B[index] = tmp;
  202.         }
  203.  
  204.         for (i = j + 1; i <= n - 1; i++) {
  205.             r = -A[i][j] / A[j][j];
  206.  
  207.             for (k = j; k <= n - 1; k++) {
  208.                 A[i][k] = A[i][k] + r * A[j][k];
  209.             }
  210.             B[i] = B[i] + r * B[j];
  211.         }
  212.     }
  213.  
  214.     x[n - 1] = B[n - 1] / A[n - 1][n - 1];
  215.     for (i = n - 2; i >= 0; i--) {
  216.         tmp = 0.0;
  217.         for (int j = i + 1; j <= n - 1; j++)
  218.             tmp += A[i][j] * x[j];
  219.         x[i] = (B[i] - tmp) / A[i][i];
  220.     }
  221. }
  222.  
  223. double scalar(double* x, double* y, int N)
  224. {
  225.     double sum = 0;
  226.     for (int i = 0; i < N; i++)
  227.         sum += x[i] * y[i];
  228.     return sum;
  229. }
  230.  
  231. double Inverse_Power_iteration(double** A, int N, double deviation)
  232. {
  233.     int flag, i, j;
  234.     double lambda;
  235.  
  236.     double** A_copy;
  237.     A_copy = new double*[N];
  238.     for (i = 0; i < N; i++)
  239.         A_copy[i] = new double[N];
  240.     double* x_copy = new double[N];
  241.  
  242.     double* x = new double[N];
  243.     double* y = new double[N];
  244.     double* res = new double[N];
  245.  
  246.     for (i = 0; i < N; i++)
  247.         x[i] = 1.0;
  248.  
  249.     do {
  250.         flag = 0;
  251.  
  252.         for (i = 0; i < N; i++) {
  253.             x_copy[i] = x[i];
  254.             for (j = 0; j < N; j++)
  255.                 A_copy[i][j] = A[i][j];
  256.         }
  257.  
  258.         Gaussian_elimination(A_copy, x_copy, y, N); //Ay=x
  259.  
  260.         lambda = scalar(x, y, N) / scalar(y, y, N);
  261.  
  262.         Multiply_Ax(A, x, res, N);
  263.         for (i = 0; i < N; i++)
  264.             if (abs(res[i] - lambda * x[i]) > deviation)
  265.                 flag = 1;
  266.  
  267.         normalize(y, N);
  268.  
  269.         for (i = 0; i < N; i++)
  270.             x[i] = y[i];
  271.  
  272.     } while (flag > 0);
  273.  
  274.     return lambda;
  275. }
  276.  
  277. void Richardson_method(double** A, double* B, double* x, int N, double deviation)
  278. {
  279.     int i, j;
  280.     double max_lambda, min_lambda, tau;
  281.     double* res = new double[N];
  282.  
  283.     max_lambda = Power_iteration(A, N, deviation);
  284.     min_lambda = Inverse_Power_iteration(A, N, deviation);
  285.     tau = 2 / (max_lambda + min_lambda);
  286.  
  287.     //Реализация алгоритма
  288.     int flag;
  289.     do {
  290.         flag = 0;
  291.         Multiply_Ax(A, x, res, N);
  292.         for (i = 0; i < N; i++) {
  293.             res[i] = tau * (res[i] - B[i]);
  294.             x[i] -= res[i];
  295.         }
  296.  
  297.         //Проверка невязки (B - A*x' = 0)
  298.         for (i = 0; i < N; i++) {
  299.             double tmp = B[i];
  300.             for (j = 0; j < N; j++)
  301.                 tmp -= A[i][j] * x[j];
  302.  
  303.             if (abs(tmp) > deviation)
  304.                 flag = 1;
  305.         }
  306.  
  307.     } while (flag > 0);
  308. }
  309.  
  310. int main()
  311. {
  312.     setlocale(LC_ALL, "RUS");
  313.  
  314.     int i, j;
  315.     int N;
  316.     double deviation = 1e-5;
  317.     double max_lambda, min_lambda;
  318.  
  319.     double* B = new double[N];
  320.     double* x = new double[N];
  321.     //double* res = new double[N];
  322.     double** A;
  323.     A = new double*[N];
  324.    
  325.     //Читаем из файла матрицу
  326.     ifstream file("D:\\вычи\\test3.txt"); // окрываем файл для чтения
  327.     file >> N;
  328.  
  329.     for (i = 0; i < N; i++) {
  330.         A[i] = new double[N];
  331.         x[i] = 1;                         //Первое приближение
  332.         for (j = 0; j < N; j++)
  333.             file >> A[i][j];
  334.     }
  335.  
  336.     for (i = 0; i < N; i++)
  337.         file >> B[j];
  338.  
  339.     cout << "N = " << N << endl;
  340.     file.close();
  341.  
  342.     //Вывод до изменения
  343.     for (i = 0; i < N; i++) {
  344.         for (j = 0; j < N; j++)
  345.             cout << A[i][j] << "\t";
  346.         cout << " = " << B[i];
  347.         cout << "; x[" << i << "] = " << x[i] << endl;
  348.     } cout << endl << endl;
  349.  
  350.     Gauss_Seidel_method(A, B, x, N, deviation);
  351.     //Gradient_descent_method(A, B, x, N, deviation);
  352.     //Richardson_method(A, B, x, N, deviation);
  353.  
  354.     //Вывод после
  355.     cout << endl
  356.          << endl;
  357.     for (i = 0; i < N; i++) {
  358.         for (j = 0; j < N; j++)
  359.             cout << A[i][j] << "\t";
  360.         cout << " = " << B[i];
  361.         cout << "; x[" << i << "] = " << x[i] << endl;
  362.     }
  363.  
  364.     cout << endl;
  365.     system("pause");
  366.     return 0;
  367. }
Advertisement
Add Comment
Please, Sign In to add comment