Обратная матрица методом Гаусса

Для получения матрицы будем исходить из того, что она является решением уравнения , где - единичная матрица. Представим искомую матрицу как набор векторов-столбцов img а единичную матрицу как набор единичных векторов img Матричное уравнение в соответствии с правилами умножения матриц возможно заменить не связанной между собой системой уравнений img Каждое из этих уравнений может быть решено методом Гаусса. Заметим то обстоятельство, что все СЛАУ имеют одну и ту же матрицу коэффициентов, поэтому

Суть метода Гаусса-Жордана заключается в том, что если с единичной матрицей провести элементарные преобразования, которыми невырожденная квадратная матрица приводится к , то получится обратная матрица . Для отображения всех элементарных преобразований, совершающихся над матрицей , на единичную матрицу , удобно "склеить" две матрицы в одну. Если матрицы и имели размер , то склеенная матрица будет иметь размер . Таким образом, все преобразования над матрицей (перестановка строк, умножение строки на константу) будут автоматически совершаться и над единичной матрицей). Обозначим склеенную матрицу как Приведение матрицы к единичной совершается в два этапа: на первом этапе будем двигаться "сверху-вниз", получая в итоге треугольную матрицу, с единицами на главной диагонали и нулями ниже. На втором этапе будем двигаться "снизу-вверх", преобразуя элементы, лежащие выше главной диагонали к нулю, тем самым добиваясь единичной матрицы в результате.

Прямой ход

Пусть матрица имеет размер . Тогда на первом этапе будет совершено шагов. На каждом шаге необходимо совершить три действия.

  1. Поменять местами строки и , в случае если . Этот шаг необходим для исключения ситуации нахождения на главной диагонали 0.
  2. Преобразовать элемент, стоящий на главной диагонали к 1. Для этого необохдимо домножить всю строку на .
  3. Обнулить все нижележащие элементы столбца. Для этого вычтем из каждой нижележащей строки c индексом результат умножения элемента c текущей строкой. Напомним, что в результате шага 2 первый элемент 1, поэтому первым элементом вычитаемой строки будет являться значение первого элемента строки , что и даст 0 в элементе

Обратный ход

Теперь необходимо преобразовать матрицу так, чтобы все элементы n-ого столбца выше стали равны нулю. Для этого прибавляем к n-1 строке соответсвующие элементы n-ой строки, умноженные на . К n-2 строке прибавляем соответсвующие элементы (n-1)-ой строки, умноженные на и т.д. Аналогичные действия необходимо совершить над оставшимися строками.

Реализация

Приведем реализацию функции inverse, принимающей в качестве аргумента исходную матрицу коэффициентов, и возвращающую матрицу, обратную к исходной. Склеим матрицу коэффициентов с единичной матрицей с помощью функции hstack

m = np.hstack((matrix_origin, 
                np.matrix(np.diag([1.0 for i in range(matrix_origin.shape[0])]))))

Прямой ход

# forward trace
    for k in range(n):
        # 1) Swap k-row with one of the underlying if m[k, k] = 0
        swap_row = pick_nonzero_row(m, k)
        if swap_row != k:
            m[k, :], m[swap_row, :] = m[swap_row, :], np.copy(m[k, :])
        # 2) Make diagonal element equals to 1
        if m[k, k] != 1:
            m[k, :] *= 1 / m[k, k]
        # 3) Make all underlying elements in column equal to zero
        for row in range(k + 1, n):
            m[row, :] -= m[k, :] * m[row, k]

Для проверки первгого условия реализуем вспомогательную функцию pick_non_zero_row, возвращающую индекс первой строки, в которой элемент интересующего нас столбца не равен нулю

def pick_nonzero_row(m, k):
    while k < m.shape[0] and not m[k, k]:
        k += 1
    return k

Обратный ход

# backward trace
    for k in range(n - 1, 0, -1):
        for row in range(k - 1, -1, -1):
            if m[row, k]:
                # 1) Make all overlying elements equal to zero in the former identity matrix
                m[row, :] -= m[k, :] * m[row, k]

Возвратим преобразованную единичную матрицу, т.е. вторую часть "склееного" массива, воспользовавшись функцией hsplit

return np.hsplit(m, n // 2)[1]