vadimk772336

Untitled

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