Проблема с LU-разложением С++

302
01 декабря 2021, 02:50

Я написал код в соответствии с алгоритмом, но результат неверен. Согласно алгоритму, мы должны указать размер матрицы и вручную заполнить основную матрицу A и вектор B. Нам нужно сгенерировать матрицу LU. Онf генерируется, но с неправильными числами. И в итоге мы должны получить вектор X с решениями. И это всё в оконном режиме. Я новичок в программировании, поэтому хотелось бы получить правильный кусок кода или даже целый код. Буду благодарен, если вы поможете с решением этой проблемы. https://imgur.com/a/4fn406Y

int N = 1; // matrix dimension
double R = 0;
typedef double Matrix [6][6];
typedef double Vec [6];
.
.
.
void Decomp (Matrix A, int N, int &Change)
{
int i, j, k ;
double R, L, U;
Change = 1;
R = Math::Abs(A[1][1]);
for(j=2; j<=N; j++)
    if (Math::Abs(A[j][1])>= R)
    {
        Change = j;
    R = Math::Abs(A[j][1]);
    }
    if (R<= 1E-7) 
    {
      MessageBox::Show("The system is degenerate");
    }
    if (k!=1)
    {
     for(i=1; i<=N; i++)
         { 
              R = A[Change][i];
              A[Change][i] = A[1][i];
               A[1][i] = R;
          }
    }
     for(i=2; i<=N; i++)
A[1][i] = A[1][i]/A[1][1];
for(i=2; i<=N; i++)
{
  for(k=i; k<=N; k++);
  {
    R = 0;
    for ( j=1; j<=(i-1); j++)
    R = R + A[k][j] * A[j][i];
    A[k][i] = A[k][i] - R;
  }
  if (A[i][i]<= 1E-7) 
    {
      MessageBox::Show("The system is degenerate[enter image description here][1]");
    }
  for(k = i+1; k<=N; k++)
  {
    R = 0;
    for (j=1; j<=(i-1); j++)
      R = R + A[i][j] * A[j][k];
    A[i][k] = (A[i][k] - R) / A[i][i];
  }
}
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
C_matrix_dgv->Rows[i]->Cells[j] -> Value = Convert::ToString(A[i+1][j+1]);
}
    }
void Solve (Matrix A, Vec b, Vec x, int Change, int N)
{
int i = 0,j = 0;
double R;
if (Change!=1)
{
  R = b[Change];
  b[Change] = b[1];
  b[1] = R;
}
b[1] = b[1]/A[1][1];
for(i=2; i<=N; i++)
{
  R = 0;
  for( j=1; j<=(i-1); j++)
    R = R + A[i][j] * b[j];
  b[i] = (b[i] - R) / A[i][i];
}
x[N] = b[N];
for( i=1; i<=(N-1); i++)
{
  R = 0;
  for(j = (N+1-i); j<=N; j++)
    R = R + A[N - i][j] * x[j];
  x[N - i] = b[N - i] - R;
}
}
Answer 1
  1. Если взять алгоритм из Википедии (https://ru.wikipedia.org/wiki/LU-разложение), то реализовать его можно так, как показано ниже. Проверок там нет, - их стоит добавить.
  2. Использование статических массивов, в данном случае, - не есть хорошо. Лучше использовать динамические, дабы программа могла оперировать с системами условно любой размерности.
  3. Смешивать логику программы и интерфейс – тоже не есть хорошо. Логика – в одни функции / методы, ввод-вывод данных (включая сообщения) – в другие.
  4. Если требуется граф. интерфейс (GUI), то прикрутить его к коду ниже (являющемуся кодом консольного приложения) не составит труда: в местах наполнения матриц и векторов случайными числами, а также в местах вывода результатов, нужно вставить соотв. функции / методы работы с элементами GUI.

Результаты работы программы:

A =
 42.000  68.000  35.000
  1.000  70.000  25.000
 79.000  59.000  63.000
B =
 65.000
  6.000
 46.000
L =
  1.000   0.000   0.000
  0.024   1.000   0.000
  1.881  -1.008   1.000
U =
 42.000  68.000  35.000
  0.000  68.381  24.167
  0.000   0.000  21.518
Y =
 65.000
  4.452
-71.775
X =
  2.313
  1.244
 -3.336

Проверка (https://ru.onlinemschool.com/math/assistance/equation/gaus/):

x1 = 142961/61801 = 2,313

x2 = 76876/61801 = 1,244

x3 = -206139/61801 = -3,336

Как видим, всё верно.

Собственно код:

#include "stdafx.h"
#include <iostream>
// печать матрицы
void printMatrix(float **matr, int n);
// печать вектор-столбца
void printVectorCol(float *v, int n);
//
float getSumU(int n, int i, int j, float **mL, float **mU);
//
float getSumL(int n, int i, int j, float **mL, float **mU);
// LU-разложение
void decomp(float **mA, int n, float **mL, float **mU);
//
float getSumY(int n, float **mL, float *vB, float *vY, int i);
//
float getSumX(int n, float **mU, float *vX, int i);
// решатель
void solver(float **mA, int n, float **mL, float **mU, float *vB, float *vY, float *vX);

int _tmain(int argc, _TCHAR* argv[])
{
    const int n = 3; // размерность системы
    // динамическое выделение памяти
    float **matrA = new float* [n];
    float **matrL = new float* [n];
    float **matrU = new float* [n];
    for (int i = 0; i < n; i++)
    {
        matrA[i] = new float [n];
        matrL[i] = new float [n];
        matrU[i] = new float [n];
    }
    float *vB = new float [n];
    float *vX = new float [n];
    float *vY = new float [n];
    // инициализация матриц и векторов нулями
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            matrA[i][j] = 0;
            matrL[i][j] = 0;
            matrU[i][j] = 0;
        }
        vB[i] = 0;
        vX[i] = 0;
        vY[i] = 0;
    }
    // заполнение матрицы A случайными числами из интервала [1; 100]
    for (int i = 0; i < n; i++) // по строкам
    {
        for (int j = 0; j < n; j++) // по столбцам
        {
            matrA[i][j] = rand() % 100 + 1;
        }
    }
    // задание случайных значений свободных коэффициентов
    for (int i = 0; i < n; i++)
    {
        vB[i] = rand() % 100 + 1;
    }
/***************************************************************************/
    // LU-разложение
    decomp(matrA, n, matrL, matrU);
    // решение системы
    solver(matrA, n, matrL, matrU, vB, vY, vX);
/***************************************************************************/
    // печать результатов
    printf("A = \n");
    printMatrix(matrA, n);
    printf("\n");
    printf("B = \n");
    printVectorCol(vB, n);
    printf("\n");
    printf("L = \n");
    printMatrix(matrL, n);
    printf("\n");
    printf("U = \n");
    printMatrix(matrU, n);
    printf("\n");
    printf("Y = \n");
    printVectorCol(vY, n);
    printf("\n");
    printf("X = \n");
    printVectorCol(vX, n);
    printf("\n");
/***************************************************************************/
    // освобождение памяти
    for (int i = 0; i < n; i++)
    {
        delete [] matrA[i];
        delete [] matrL[i];
        delete [] matrU[i];
    }
    delete [] matrA;
    delete [] matrL;
    delete [] matrU;
    delete [] vB;
    delete [] vX;
    delete [] vY;
    printf("\n");
    system("PAUSE");
    return 0;
}
// печать матрицы
void printMatrix(float **matr, int n)
{
    for (int i = 0; i < n; i++) // по строкам
    {
        for (int j = 0; j < n; j++) // по столбцам
        {
            printf("%7.3f ", matr[i][j]);
        }
        printf("\n"); // новая строка
    }
}
// печать вектор-столбца
void printVectorCol(float *v, int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("%7.3f ", v[i]);
        printf("\n");
    }
}
//
float getSumU(int n, int i, int j, float **mL, float **mU)
{
    float res = 0;
    for (int k = 0; k < i; k++)
    {
        res += mL[i][k] * mU[k][j];
    }
    return res;
}
//
float getSumL(int n, int i, int j, float **mL, float **mU)
{
    float res = 0;
    for (int k = 0; k < i; k++)
    {
        res += mL[j][k] * mU[k][i];
    }
    return res;
}
// LU-разложение
void decomp(float **mA, int n, float **mL, float **mU)
{
    // i = 0
    for (int j = 0; j < n; j++)
    {
        mU[0][j] = mA[0][j];
        mL[j][0] = mA[j][0] / mU[0][0];
    }
    // i = 1 .. n-1
    for (int i = 1; i < n; i++)
    {
        for (int j = i; j < n; j++)
        {
            mU[i][j] = mA[i][j] - getSumU(n, i, j, mL, mU);
            mL[j][i] = (mA[j][i] - getSumL(n, i, j, mL, mU)) / mU[i][i];
        }
    }
}
//
float getSumY(int n, float **mL, float *vB, float *vY, int i)
{
    float res = 0;
    for (int k = 0; k < i; k++)
    {
        res += mL[i][k] * vY[k];
    }
    return res;
}
//
float getSumX(int n, float **mU, float *vX, int i)
{
    float res = 0;
    for (int k = n - 1; k > i; k--)
    {
        res += mU[i][k] * vX[k];
    }
    return res;
}
// решатель
void solver(float **mA, int n, float **mL, float **mU, float *vB, float *vY, float *vX)
{
    // Y. Решение прямой подстановкой
    for (int i = 0; i < n; i++)
    {
        vY[i] = (vB[i] - getSumY(n, mL, vB, vY, i)) / mL[i][i];
    }
    // X. Решение обратной подстановкой
    for (int i = n - 1; i >= 0; i--)
    {
        vX[i] = (vY[i] - getSumX(n, mU, vX, i)) / mU[i][i];
    }
}
READ ALSO
Как запускать gui приложение Qt без консоли?

Как запускать gui приложение Qt без консоли?

Проблема такова : исполняемый файл готового приложения запускается вместе с консолью позадиПараметр "Run in terminal" снят, приложение создано...

113
Клонирование класса GameObject Unity

Клонирование класса GameObject Unity

Я хочу клонировать в скрипте GameObject без его появления на сцене(так что Instantiate не подойдёт)

157
Аналог (подобие) include в C#

Аналог (подобие) include в C#

(Просьба не удалять вопросЧетко сформулированного нет

74
Как правильно указать локальный путь?

Как правильно указать локальный путь?

Есть программа, в которой проигрывается музыкаПри передачи архива на другой компьютер, я не знаю где будет находится его папка со звуковыми...

253