Wolfed_7

Untitled

Oct 3rd, 2022
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.61 KB | None | 0 0
  1. // LLT разложение, матрица в профильном формате.
  2. /*
  3. * Структура программы:
  4. * Ввод матрицы и вектора F
  5. * Разложение матрицы на LLT составляющие
  6. * Решение системы Ly = F  (прямой ход)
  7. * Решение системы LTx = y (обратный ход)
  8. */
  9.  
  10. #include <iostream>
  11. #include <iomanip>
  12. #include <fstream>
  13. #include <string>
  14. #include <vector>
  15.  
  16. typedef float real;
  17. typedef float real_acc;
  18.  
  19. using namespace std;
  20.  
  21. const string file1("matrix.txt"); // Имя файла, содержащего матрицу в профильном формате.
  22. const string file2("vector.txt"); // Вектор - результат умножения матрицы на искомый вектор.
  23. const string file3("result.txt"); // Искомый вектор - решение СЛАУ.
  24. const string file4("subs.txt");   // Погрешность вычислений.
  25.  
  26. size_t N = 0; // Размерность матрицы
  27. vector<size_t> ia;
  28. vector<real> di;
  29. vector<real> al;
  30. vector<real> F;
  31.  
  32. vector<real> x;
  33. vector<real> y; // Промежуточный вектор для прямого хода.
  34.  
  35. void input(string file1, string file2);
  36. void LLT_dec();
  37. void straight_stroke();
  38. void reverse_stroke();
  39. void cond_test_gen(size_t k, string file3, string file4);
  40. void gilbert_test_gen(size_t k, string file3, string file4);
  41. void Gauss_test_gen(size_t k, string file3, string file4);
  42.  
  43. void main()
  44. {
  45.    size_t k = 5;
  46.  
  47.  
  48.    //input(file1, file2);
  49.    //cond_test_gen(k, file3, file4);
  50.  
  51.    //gilbert_test_gen(k, file3, file4);
  52.  
  53.    Gauss_test_gen(k, file3, file4);
  54.  
  55.  
  56.  
  57.  
  58.  
  59.    N = 2;
  60.    int SUMMA = 0;
  61.  
  62.    for (size_t k = 0; k < N; k++)
  63.    {
  64.       for (size_t i = 0; i < N + 1; i++)
  65.          SUMMA++;
  66.  
  67.       for (size_t i = k + 1; i < N; i++)                    
  68.       {
  69.          SUMMA++;
  70.          for (size_t j = 0; j < N + 1; j++)
  71.             SUMMA += 2;    
  72.       }
  73.    }
  74.  
  75.    cout << SUMMA;
  76.    for (int k = N - 1; k > -1; k--)
  77.    {
  78.       for (int i = N; i > -1; i--)
  79.          SUMMA++;
  80.       for (int i = k - 1; i > -1; i--)
  81.       {
  82.          SUMMA++;
  83.          for (int j = N; j > -1; j--)
  84.             SUMMA += 2;
  85.       }
  86.    }
  87. }
  88.  
  89. /*
  90. * 1. Преобразование особых матрицы и вектора F
  91. *    к нужному виду.
  92. * 2. Решение СЛАУ.
  93. * 3. Запись результата и погрешности относительно
  94. *    точного решения.
  95. */
  96. void cond_test_gen(size_t k, string file3, string file4)
  97. {
  98.    di[0] += 1.0 / pow(10, k);
  99.    F[0]  += 1.0 / pow(10, k);
  100.  
  101.    LLT_dec();
  102.    straight_stroke();
  103.    reverse_stroke();
  104.  
  105.    // Вывод искомого вектора.
  106.    size_t prec = 0;
  107.    k < 7 ? prec = 7 : prec = 14;
  108.    ofstream fout(file3);
  109.    for (size_t i = 0; i < N; i++)
  110.       fout << scientific << setprecision(prec) << x[i] << endl;
  111.    fout.close();
  112.  
  113.    // Вывод погрешности относительно точного вектора.
  114.    ofstream fout2(file4);
  115.    vector<real> x_acc = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };
  116.    for (size_t i = 0; i < 10; i++)
  117.       fout2 << scientific << setprecision(2) << abs(x_acc[i] - x[i]) << endl;
  118.    fout2.close();
  119. }
  120.  
  121. /*
  122. * 1. Создание матрицы Гильберта k-той размерности и
  123. *    вектора F умножением на x(1, ..., N).
  124. * 2. Решение СЛАУ.
  125. * 3. Запись результата и погрешности относительно
  126. *    точного решения.
  127. */
  128. void gilbert_test_gen(size_t k, string file3, string file4)
  129. {
  130.    N = k;
  131.    ia.resize(N + 1);
  132.    ia[0] = 0;
  133.    for (size_t i = 0; i < N; i++)
  134.       ia[i + 1] = ia[i] + i;
  135.  
  136.    al.resize(ia[N]);
  137.    di.resize(N);
  138.    for (size_t i = 0; i < N; i++)
  139.    {
  140.       size_t i0 = ia[i];        // Индекс начального элемента i-той строки в массиве al.
  141.       size_t i1 = ia[i + 1];    // Индекс начального элемента i + 1 стоки.
  142.       size_t j = i - (i1 - i0); // Номер столбца первого элемента в строке.
  143.  
  144.       for (size_t ij = i0; ij < i1; ij++, j++)
  145.          al[ij] = 1.0 / (i + j + 1);
  146.       di[i] = 1.0 / (2 * i + 1);
  147.    }
  148.  
  149.    F.resize(N);
  150.    for (size_t i = 0; i < N; i++)
  151.    {
  152.       size_t ind = i + ia[i] - ia[i + 1];
  153.       for (size_t j = ia[i]; j < ia[i + 1]; j++)
  154.       {
  155.          F[i] += al[j] * (ind + 1);
  156.          F[ind] += al[j] * (i + 1);
  157.          ind++;
  158.       }
  159.       F[i] += di[i] * (i + 1);
  160.    }
  161.  
  162.    y.resize(N);
  163.    x.resize(N);
  164.  
  165.    LLT_dec();
  166.    straight_stroke();
  167.    reverse_stroke();
  168.  
  169.    // Вывод искомого вектора.
  170.    size_t prec = 0;
  171.    k < 7 ? prec = 7 : prec = 14;
  172.    ofstream fout(file3);
  173.    fout << scientific << setprecision(14);
  174.    for (size_t i = 0; i < N; i++)
  175.       fout << x[i] << endl;
  176.    fout.close();
  177.  
  178.    // Вывод погрешности относительно точного вектора.
  179.    ofstream fout2(file4);
  180.    vector<real> x_acc(N);
  181.    for (size_t i = 0; i < N; i++)
  182.       x_acc[i] = i + 1;
  183.    fout2 << scientific << setprecision(2);
  184.    for (size_t i = 0; i < N; i++)
  185.       fout2 << abs(x_acc[i] - x[i]) << endl;
  186.    fout2.close();
  187. }
  188.  
  189. void input(string file1, string file2)
  190. {
  191.    // Переделать в сишные сканфс
  192.    // для контроля количества вводимых знаков.
  193.  
  194.    ifstream fin(file1);
  195.    ifstream fin2(file2);
  196.    fin >> N;
  197.    ia.resize(N + 1);
  198.    for (size_t i = 0; i < N + 1; i++)
  199.    {
  200.       fin >> ia[i];
  201.       ia[i]--;
  202.    }
  203.  
  204.    di.resize(N);
  205.    for (size_t i = 0; i < N; i++)
  206.       fin >> di[i];
  207.  
  208.    al.resize(ia[N]);
  209.    for (size_t i = 0; i < ia[N]; i++)
  210.       fin >> al[i];
  211.    fin.close();
  212.  
  213.    F.resize(N);
  214.    for (size_t i = 0; i < N; i++)
  215.       fin2 >> F[i];
  216.    fin2.close();
  217.  
  218.    y.resize(N);
  219.    x.resize(N);
  220. }
  221.  
  222. // LLT - разложение.
  223. // Заменяет матрицу в массивах di и al нижнетреугольной L
  224. void LLT_dec()
  225. {
  226.    for (size_t i = 0; i < N; i++)
  227.    {
  228.       real_acc sumdi = 0.0;
  229.  
  230.       size_t i0 = ia[i];        // Индекс начального элемента i-той строки в массиве al.
  231.       size_t i1 = ia[i + 1];    // Индекс начального элемента i + 1 стоки.
  232.       size_t j = i - (i1 - i0); // Номер столбца первого элемента в строке.
  233.  
  234.       for (size_t ij = i0; ij < i1; ij++, j++)
  235.       {
  236.          real_acc suml = 0.0;
  237.  
  238.          size_t j0 = ia[j];       // Индекс начального элемента j-той строки в массиве al.
  239.          size_t j1 = ia[j + 1];   // Индекс начального элемента j + 1 стоки.
  240.  
  241.          size_t ik = i0;
  242.          size_t jk = j0;
  243.  
  244.          size_t ci = ij - i0;  // Количество элементов i-той строки.
  245.          size_t cj = j1 - j0;  // Количество элементов j-той строки.
  246.  
  247.          // Сдвиг индексов начальных элементов строк
  248.          // к первому существующему элементу наименьшей строки.
  249.          ci > cj ? ik += ci - cj : jk += cj - ci;
  250.  
  251.          // Суммируем произведения элементов двух строк, стоящих до искомого.
  252.          for (; ik < ij; ik++, jk++)
  253.             suml += al[ik] * al[jk];
  254.          al[ij] = (al[ij] - suml) / di[j];
  255.  
  256.          sumdi += al[ij] * al[ij];
  257.       }
  258.       di[i] = sqrt(di[i] - sumdi);
  259.    }
  260. }
  261.  
  262. // Прямой ход. (Ly = F)
  263. // Заполнение вектора y.
  264. void straight_stroke()
  265. {
  266.    for (size_t i = 0; i < N; i++)
  267.    {
  268.       size_t in = ia[i + 1];
  269.       size_t in_prev = ia[i];
  270.  
  271.       size_t j = i - (in - in_prev);
  272.       real_acc sum = 0.0;
  273.       for (size_t k = in_prev; k < in; k++, j++)
  274.          sum += al[k] * y[j];
  275.  
  276.       y[i] = (F[i] - sum) / di[i];
  277.    }
  278. }
  279.  
  280. // Обратный ход. (LTx = y)
  281. // Заполнение искомого вектора.
  282. void reverse_stroke()
  283. {
  284.    vector<real_acc> temp(N);
  285.    fill(temp.begin(), temp.end(), 0.0);
  286.  
  287.    for (size_t i = N; i >= 1; i--)
  288.    {
  289.       size_t in = ia[i];
  290.       size_t in_prev = ia[i - 1];
  291.  
  292.       x[i - 1] = (y[i - 1] - temp[i - 1]) / di[i - 1];
  293.       size_t j = i - 2;
  294.       for (size_t k = in; k > in_prev; k--, j--)
  295.          temp[j] += al[k - 1] * x[i - 1];
  296.    }
  297. }
  298.  
  299. void Gauss_test_gen(size_t p, string file3, string file4)
  300. {
  301.    vector<vector<real_acc>> Matrix_Clone =
  302.    {                                                                            
  303.       {  8.0,    0.0,  -3.0,   0.0,   0.0,   0.0,  -1.0,  -4.0,    0.0,    0.0,       -40.0 },
  304.       {  0.0,    5.0,   0.0,  -1.0,   0.0,   0.0,   0.0,   0.0,   -2.0,   -2.0,       -32.0 },
  305.       { -3.0,    0.0,   7.0,   0.0,  -1.0,   0.0,  -3.0,   0.0,    0.0,    0.0,       -8.0  },
  306.       {  0.0,   -1.0,   0.0,   8.0,   0.0,  -2.0,   0.0,   0.0,   -1.0,   -4.0,       -31.0 },
  307.       {  0.0,    0.0,  -1.0,   0.0,   4.0,   0.0,   0.0,  -3.0,    0.0,    0.0,       -7.0  },
  308.       {  0.0,    0.0,   0.0,  -2.0,   0.0,   6.0,  -3.0,   0.0,   -1.0,    0.0,       -2.0  },
  309.       { -1.0,    0.0,  -3.0,   0.0,   0.0,  -3.0,   9.0,   0.0,    0.0,   -2.0,        15.0 },
  310.       { -4.0,    0.0,   0.0,   0.0,  -3.0,   0.0,   0.0,   11.0,  -4.0,    0.0,        33.0 },
  311.       {  0.0,   -2.0,   0.0,  -1.0,   0.0,  -1.0,   0.0,  -4.0,    11.0,  -3.0,        23.0 },
  312.       {  0.0,   -2.0,   0.0,  -4.0,   0.0,   0.0,  -2.0,   0.0,   -3.0,    11.0,       49.0 }
  313.    };
  314.  
  315.    N = Matrix_Clone.size();
  316.    Matrix_Clone[0][0] += 1.0 / pow(10, p);
  317.    Matrix_Clone[0][N] += 1.0 / pow(10, p);
  318.  
  319.    vector<vector <real>> Matrix(N, vector <real>(N + 1));
  320.    for (size_t i = 0; i < N; i++)
  321.       for (size_t j = 0; j < N + 1; j++)
  322.          Matrix[i][j] = Matrix_Clone[i][j];
  323.  
  324.    // Прямой ход (Зануление нижнего левого угла)
  325.    for (size_t k = 0; k < N; k++)      // k-номер строки.
  326.    {
  327.       for (size_t i = 0; i < N + 1; i++)      // i-номер столбца.
  328.          Matrix_Clone[k][i] /= Matrix[k][k];  // Деление k-строки на первый член !=0 для преобразования его в единицу.
  329.  
  330.       for (size_t i = k + 1; i < N; i++)                         // i-номер следующей строки после k.
  331.       {
  332.          real K = Matrix_Clone[i][k] / Matrix_Clone[k][k];       // Коэффициент.
  333.          for (size_t j = 0; j < N + 1; j++)                      // j-номер столбца следующей строки после k.
  334.             Matrix_Clone[i][j] -= Matrix_Clone[k][j] * K;        // Зануление элементов матрицы ниже первого члена, преобразованного в единицу
  335.       }
  336.  
  337.       for (size_t i = 0; i < N; i++)                             // Обновление, внесение изменений в начальную матрицу
  338.          for (size_t j = 0; j < N + 1; j++)
  339.             Matrix[i][j] = Matrix_Clone[i][j];
  340.    }
  341.  
  342.    // Обратный ход (Зануление верхнего правого угла)
  343.    for (int k = N - 1; k > -1; k--) // k-номер строки
  344.    {
  345.       for (int i = N; i > -1; i--)  // i-номер столбца
  346.          Matrix_Clone[k][i] /= Matrix[k][k];
  347.       for (int i = k - 1; i > -1; i--) //i-номер следующей строки после k
  348.       {
  349.          real K = Matrix_Clone[i][k] / Matrix_Clone[k][k];
  350.          for (int j = N; j > -1; j--) //j-номер столбца следующей строки после k
  351.             Matrix_Clone[i][j] -= Matrix_Clone[k][j] * K;
  352.       }
  353.    }
  354.  
  355.    // Отделяем от общей матрицы ответы
  356.    vector<real> x(N);
  357.    for (size_t i = 0; i < N; i++)
  358.       x[i] = Matrix_Clone[i][N];
  359.  
  360.    // Вывод искомого вектора.
  361.    size_t prec = 0;
  362.    p < 7 ? prec = 7 : prec = 14;
  363.    ofstream fout(file3);
  364.    for (size_t i = 0; i < N; i++)
  365.       fout << scientific << setprecision(prec) << x[i] << endl;
  366.    fout.close();
  367.  
  368.    // Вывод погрешности относительно точного вектора.
  369.    ofstream fout2(file4);
  370.    vector<real> x_acc = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };
  371.    for (size_t i = 0; i < 10; i++)
  372.       fout2 << scientific << setprecision(2) << abs(x_acc[i] - x[i]) << endl;
  373.    fout2.close();
  374. }
  375.  
Add Comment
Please, Sign In to add comment