vadimk772336

Untitled

May 7th, 2020
925
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.69 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 = 0;
  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) {
  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.     cout << "Число итераций: " << k << endl;
  88. }
  89.  
  90. void Gradient_descent_method(double** A, double* B, double* x, int N, double deviation)
  91. {
  92.     int i, j, k, flag = 1;
  93.     double tau = 0, sum = 0;
  94.     double denominator = 0, numerator = 0, tmp;
  95.     double* r = new double[N];
  96.     double* res = new double[N];
  97.  
  98.     k = 0;
  99.     while (flag > 0) {
  100.         flag = 0;
  101.  
  102.         for (i = 0; i < N; i++) {
  103.             sum = 0;
  104.             for (j = 0; j < N; j++)
  105.                 sum += A[i][j] * x[j];
  106.             r[i] = sum - B[i];
  107.         }
  108.  
  109.         Multiply_Ax(A, r, res, N);
  110.         for (j = 0; j < N; j++) {
  111.             denominator += res[j] * r[j];
  112.             numerator += r[j] * r[j];
  113.         }
  114.         tau = numerator / denominator;
  115.         denominator = 0;
  116.         numerator = 0;
  117.  
  118.         for (i = 0; i < N; i++) {
  119.             x[i] -= tau * r[i];
  120.         }
  121.         //Проверка невязки (B - A*x' = 0)
  122.         for (i = 0; i < N; i++) {
  123.             tmp = B[i];
  124.             for (j = 0; j < N; j++)
  125.                 tmp -= A[i][j] * x[j];
  126.             if (abs(tmp) > deviation)
  127.                 flag = 1;
  128.             break;
  129.         }
  130.         k++;
  131.     }
  132.     cout << "Число итераций: " << k << endl;
  133. }
  134.  
  135. //Степенной метод нахождения макс собств числа
  136. double Power_iteration(double** A, int N, double deviation)
  137. {
  138.     int flag = 1, i;
  139.     double lambda = 0;
  140.  
  141.     double* x = new double[N];
  142.     double* y = new double[N];
  143.     for (i = 0; i < N; i++)
  144.         x[i] = 1.0;
  145.  
  146.     while (flag > 0) {
  147.         flag = 0;
  148.  
  149.         Multiply_Ax(A, x, y, N);
  150.  
  151.         for (i = 0; i < N; i++)
  152.             if (abs(y[i] - lambda * x[i]) > deviation)
  153.                 flag = 1;
  154.  
  155.         lambda = 0;
  156.         for (i = 0; i < N; i++)
  157.             lambda += x[i] * y[i];
  158.  
  159.         normalize(y, N);
  160.         for (i = 0; i < N; i++)
  161.             x[i] = y[i];
  162.     }
  163.     return lambda;
  164. }
  165.  
  166. void Gaussian_elimination(double** A, double* B, double* x, int n)
  167. {
  168.  
  169.     double* tmp_mas;
  170.     tmp_mas = new double[n];
  171.  
  172.     int i, j, k, index;
  173.     double tmp, max, r;
  174.  
  175.     for (j = 0; j <= n - 2; j++) {
  176.  
  177.         max = abs(A[j][j]);
  178.         index = j;
  179.  
  180.         for (i = index + 1; i <= n - 1; i++) {
  181.             if (abs(A[i][index]) > max) {
  182.                 max = abs(A[i][index]);
  183.                 index = i;
  184.             }
  185.         }
  186.  
  187.         if (index != j) {
  188.             for (i = 0; i <= n - 1; i++) {
  189.                 tmp_mas[i] = A[j][i];
  190.                 A[j][i] = A[index][i];
  191.                 A[index][i] = tmp_mas[i];
  192.             }
  193.             tmp = B[j];
  194.             B[j] = B[index];
  195.             B[index] = tmp;
  196.         }
  197.  
  198.         for (i = j + 1; i <= n - 1; i++) {
  199.             r = -A[i][j] / A[j][j];
  200.  
  201.             for (k = j; k <= n - 1; k++) {
  202.                 A[i][k] = A[i][k] + r * A[j][k];
  203.             }
  204.             B[i] = B[i] + r * B[j];
  205.         }
  206.     }
  207.  
  208.     x[n - 1] = B[n - 1] / A[n - 1][n - 1];
  209.     for (i = n - 2; i >= 0; i--) {
  210.         tmp = 0.0;
  211.         for (int j = i + 1; j <= n - 1; j++)
  212.             tmp += A[i][j] * x[j];
  213.         x[i] = (B[i] - tmp) / A[i][i];
  214.     }
  215. }
  216.  
  217. double scalar(double* x, double* y, int N)
  218. {
  219.     double sum = 0;
  220.     for (int i = 0; i < N; i++)
  221.         sum += x[i] * y[i];
  222.     return sum;
  223. }
  224.  
  225. double Inverse_Power_iteration(double** A, int N, double deviation)
  226. {
  227.     int flag, i, j;
  228.     double lambda;
  229.  
  230.     double** A_copy;
  231.     A_copy = new double*[N];
  232.     for (i = 0; i < N; i++)
  233.         A_copy[i] = new double[N];
  234.     double* x_copy = new double[N];
  235.  
  236.     double* x = new double[N];
  237.     double* y = new double[N];
  238.     double* res = new double[N];
  239.  
  240.     for (i = 0; i < N; i++)
  241.         x[i] = 1.0;
  242.  
  243.     do {
  244.         flag = 0;
  245.  
  246.         for (i = 0; i < N; i++) {
  247.             x_copy[i] = x[i];
  248.             for (j = 0; j < N; j++)
  249.                 A_copy[i][j] = A[i][j];
  250.         }
  251.  
  252.         Gaussian_elimination(A_copy, x_copy, y, N); //Ay=x
  253.  
  254.         lambda = scalar(x, y, N) / scalar(y, y, N);
  255.  
  256.         Multiply_Ax(A, x, res, N);
  257.         for (i = 0; i < N; i++)
  258.             if (abs(res[i] - lambda * x[i]) > deviation)
  259.                 flag = 1;
  260.  
  261.         normalize(y, N);
  262.  
  263.         for (i = 0; i < N; i++)
  264.             x[i] = y[i];
  265.  
  266.     } while (flag > 0);
  267.  
  268.     return lambda;
  269. }
  270.  
  271. void Richardson_method(double** A, double* B, double* x, int N, double deviation)
  272. {
  273.     int i, j;
  274.     double max_lambda, min_lambda, tau;
  275.     double* res = new double[N];
  276.  
  277.     max_lambda = Power_iteration(A, N, deviation);
  278.     min_lambda = Inverse_Power_iteration(A, N, deviation);
  279.     tau = 2 / (max_lambda + min_lambda);
  280.  
  281.     //Реализация алгоритма
  282.     int flag, k = 0;
  283.     do {
  284.         k++;
  285.         flag = 0;
  286.         Multiply_Ax(A, x, res, N);
  287.         for (i = 0; i < N; i++) {
  288.             res[i] = tau * (res[i] - B[i]);
  289.             x[i] -= res[i];
  290.         }
  291.  
  292.         //Проверка невязки (B - A*x' = 0)
  293.         for (i = 0; i < N; i++) {
  294.             double tmp = B[i];
  295.             for (j = 0; j < N; j++)
  296.                 tmp -= A[i][j] * x[j];
  297.  
  298.             if (abs(tmp) > deviation)
  299.                 flag = 1;
  300.         }
  301.  
  302.     } while (flag > 0);
  303.     cout << "Число итераций: " << k << endl;
  304. }
  305.  
  306. int main()
  307. {
  308.     setlocale(LC_ALL, "RUS");
  309.  
  310.     int i, j;
  311.     int N;
  312.     double deviation = 1e-5;
  313.     double max_lambda, min_lambda;
  314.  
  315.     //Читаем из файла матрицу
  316.     ifstream file("D:\\вычи\\test3.txt");
  317.     file >> N;
  318.     double* B = new double[N];
  319.     double* x = new double[N];
  320.     double** A;
  321.     A = new double*[N];
  322.  
  323.     for (i = 0; i < N; i++) {
  324.         A[i] = new double[N];
  325.         x[i] = 1; //Первое приближение
  326.         for (j = 0; j < N; j++)
  327.             file >> A[i][j];
  328.     }
  329.  
  330.     for (i = 0; i < N; i++)
  331.         file >> B[i];
  332.  
  333.     file.close();
  334.  
  335.     //Gauss_Seidel_method(A, B, x, N, deviation);
  336.     //Gradient_descent_method(A, B, x, N, deviation);
  337.     Richardson_method(A, B, x, N, deviation);
  338.  
  339.     //Вывод
  340.     cout << "Решение: ";
  341.     for (i = 0; i < N; i++)
  342.         cout << x[i] << endl;
  343.    
  344.  
  345.     cout << endl <<  "N = " << N << endl;
  346.     cout << "Макс. собств. число: " << Power_iteration(A, N, deviation) << endl;
  347.     cout << "Мин. собств. число: " << Inverse_Power_iteration(A, N, deviation) << endl;
  348.  
  349.     cout << endl;
  350.     system("pause");
  351.     return 0;
  352. }
Advertisement
Add Comment
Please, Sign In to add comment