Обработка математики: 6%

Подразделы

Другие разделы

Дата и время

01/04/2025 18:21:18

Авторизация

Имя:
Пароль:
Зарегистрироваться
Восстановить пароль
 

printМатрицы

printLU-разложение и вычисление обратной матрицы

Для нахождения обратной матрицы нужно найти n2 чисел xij, таких что
[a11...


Мы можем найти неизвестные числа, решая n систем линейных уравнений с одной и той же матрицей коэффициентов A, у которых вектор неизвестных x^j представляет собой j-ый столбец обратной матрицы, а вектор свободных членов e^jj-ый столбец единичной матрицы:
A*x^j=e^j

Для вычислений можно использовать преобразование матрицы A в форму, именуемую LU-разложением, или LU-декомпозицией матрицы коэффициентов.

Данная форма может быть получена с помощью алгоритма исключения Гаусса за Theta(n^3).

Верхнетреугольная матрица U представляет собой результат исключения, а нижнетреугольную матрицу L образована единицами на главной диагонали и множителями, вычисляемыми в процессе исключения Гаусса для обнуления соответствующих коэффициентов в строках матрицы.


Произведение LU этих матриц равно исходной матрице А.

Следовательно, решение системы линейных уравнений Ax=b эквивалентно решению системы LUx = b. Решить ее можно следующим образом. Обозначим y = Ux, тогда Ly = b.

Сначала решим систему Ly =b, что очень просто сделать, поскольку L — нижнетреугольная матрица. Затем решим систему Ux = y, что опять же несложно, поскольку U — верхнетреугольная матрица.

Таким образом, с помощью LU-разложения матрицы A, мы можем решать системы линейных уравнений Ax = b для разных векторов свободных членов b за Theta(n^2).

Так как каждое решение можно найти за Theta(n^2), то общее время для нахождения обратной матрицы равно Theta(n^3).


bool LUdecomp(vector<vector<double>>&A, vector<int> &P /*, bool& inv */) {
  int n=A.size();
//bool inv=0; для определителя
  P.resize(n);
  for(int i=0;i<n;++i) P[i]=i;
  for(int i=0; i<n-1; ++i)
  { // находим маскимальное значение в столбце для уменьшения ошибки вычислений
    int imax=i;
    for(int j=i+1; j<n; ++j)
      if(fabs(A[j][i])>fabs(A[imax][i])) imax=j;
    if(fabs(A[imax][i])<1e-12) return 0;
    if(imax!=i)
    { swap(A[imax],A[i]);
      swap(P[imax],P[i]);
//    inv=!inv;
    }
    for(int j=i+1; j<n; ++j)
    {
      double t=A[j][i]/A[i][i];
      for(int k=i; k<n; ++k)
        A[j][k]-=A[i][k]*t;
      A[j][i]=t;
    }
  }
  return 1;
}
// решение системы LUx=b
vector<double> LUsolve(const vector<vector<double>>&LU, 
    const vector<int> &P, const vector<double>& b) {
  int n=LU.size();
  vector<double> x(n),y(n);
// Ly=b
  for (int i = 0; i < n; i++) {
        y[i] = b[P[i]];
        for (int j = 0; j < i; j++)
            y[i] -= LU[i][j] * y[j];
    }
// Ux=y
    for (int i = n - 1; i >= 0; i--) {
        for (int j = i + 1; j < n; j++)
            y[i] -= LU[i][j] * x[j];
        x[i] = y[i]/LU[i][i];
    }
  return x;
}
bool LUinverse(vector<vector<double>> A, vector<vector<double>>&IA)
{ int n=A.size();
  vector<int> P;
  if(! LUdecomp(A,P)) return 0;
  IA.assign(n,vector<double>(n));
  for(int i=0;i<n;++i)
  { vector<double> b(n,0.0);
    b[i]=1;
    auto x=LUsolve(A,P,b);
    for(int j=0;j<n;++j)
      IA[j][i]=x[j];
  }
  return 1;
}

Метод исключения Гаусса помогает и при вычислении определителя.

Определитель верхнетреугольной матрицы равен произведению ее элементов на главной диагонали, а элементарные операции, выполняемые алгоритмом исключения Гаусса либо оставляют его значение неизменным, либо меняют знак, либо приводят к умножению его на константу. В результате мы можем вычислить определитель матрицы за кубическое время.

// определитель
double LUdeterm(const vector<vector<double>>&LU, bool inv) {
    double det =inv?-1:1;
    for (int i = 0; i < LU.size(); i++)
        det *= LU[i][i];
    return det;
}
loading