vadimk772336

Untitled

Apr 19th, 2020
294
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.23 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;
  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 < 15) {
  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 < 50) {
  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.             r[i] = sum - B[i];
  106.             cout << "r[" << i << "] = " << r[i] << endl;
  107.         }
  108.  
  109.         Multiply_Ax(A, r, res, N);
  110.         for (j = 0; j < N; j++) {
  111.             cout << "res " << res[j] << endl;
  112.             denominator += res[j] * r[j];
  113.             numerator += r[j] * r[j];
  114.         }
  115.         cout << "denominator = " << denominator << endl;
  116.         cout << "numerator = " << numerator << endl;
  117.         tau = numerator / denominator;
  118.         denominator = 0;
  119.         numerator = 0;
  120.         cout << "tau " << tau << endl;
  121.  
  122.         for (i = 0; i < N; i++) {
  123.             x[i] -= tau * r[i];
  124.             cout << "x[" << i << "] = " << x[i] << endl;
  125.         }
  126.         //Проверка невязки (B - A*x' = 0)
  127.         for (i = 0; i < N; i++) {
  128.             tmp = B[i];
  129.             for (j = 0; j < N; j++)
  130.                 tmp -= A[i][j] * x[j];
  131.            // cout << "difference : " << tmp << endl;
  132.             if (abs(tmp) > deviation)
  133.                 flag = 1;
  134.             break;
  135.         }
  136.         k++;
  137.     }
  138. }
  139.  
  140. //Степенной метод нахождения макс собств числа
  141. double Power_iteration(double** A, int N, double deviation)
  142. {
  143.     int flag = 1, i, j, k = 0;
  144.     double lambda = 1, result;
  145.  
  146.     double* x = new double[N];
  147.     double* y = new double[N];
  148.     for (i = 0; i < N; i++)
  149.         x[i] = 0;
  150.     x[0] = 1;
  151.  
  152.     k = 0;
  153.     while (flag > 0 && k < 10) {
  154.         flag = 0;
  155.  
  156.         Multiply_Ax(A, x, y, N); //Строим новое приближение собств вектора у: y = A*x
  157.  
  158.         //Проверка на погрешность Ax - x*lambda = 0
  159.         for (i = 0; i < N; i++)
  160.             if (abs(y[i] - lambda * x[i]) > deviation) //Хотя бы одна компонента > deviation то продолжаем искать
  161.                 flag = 1;
  162.  
  163.         normalize(y, N); //нормируем найденный вектор
  164.  
  165.         for (i = 0; i < N; i++) {
  166.             lambda += x[i] * y[i]; //Строим новое приблежение макс. собств числа: lambda = <x,y>/norma
  167.             x[i] = y[i]; //Перезаписываем x
  168.         }
  169.  
  170.         k++; //Кол-во итераций, ограничим их, чтобы не ушло в бесконечность если не работает алгоритм
  171.     }
  172. }
  173.  
  174. int main()
  175. {
  176.     setlocale(LC_ALL, "RUS");
  177.  
  178.     int i, j;
  179.     int N = 3;
  180.     double deviation = 1e-5;
  181.  
  182.     double* B = new double[N];
  183.     double* x = new double[N];
  184.     double** A;
  185.     A = new double*[N];
  186.     for (i = 0; i < N; i++) {
  187.         A[i] = new double[N];
  188.         x[i] = 1; //Первое приближение
  189.     }
  190.  
  191.     A[2][0] = 3;
  192.     A[2][1] = 6;
  193.     A[2][2] = 4;
  194.     A[0][0] = 0;
  195.     A[0][1] = 5;
  196.     A[0][2] = 7;
  197.     A[1][0] = 0;
  198.     A[1][1] = 0;
  199.     A[1][2] = 2;
  200.     B[2] = 5;
  201.     B[0] = 2;
  202.     B[1] = 3;
  203.  
  204.     //Gauss_Seidel_method(A, B, x, N, deviation); //Работает
  205.  
  206.     //Вывод
  207.     for (i = 0; i < N; i++) {
  208.         for (j = 0; j < N; j++)
  209.             cout << A[i][j] << "\t";
  210.         cout << " = " << B[i];
  211.         cout << "; x[" << i << "] = " << x[i] << endl;
  212.     } cout << endl << endl;
  213.    
  214.     Gradient_descent_method(A, B, x, N, deviation);
  215.  
  216.     //Вывод
  217.     cout << endl << endl;
  218.     for (i = 0; i < N; i++) {
  219.         for (j = 0; j < N; j++)
  220.             cout << A[i][j] << "\t";
  221.         cout << " = " << B[i];
  222.         cout << "; x[" << i << "] = " << x[i] << endl;
  223.     }
  224.  
  225.     cout << endl;
  226.  
  227.     return 0;
  228. }
Advertisement
Add Comment
Please, Sign In to add comment