Обратная матрица методом Гаусса
Для получения матрицы будем исходить из того, что она является решением уравнения , где - единичная матрица. Представим искомую матрицу как набор векторов-столбцов img а единичную матрицу как набор единичных векторов img Матричное уравнение в соответствии с правилами умножения матриц возможно заменить не связанной между собой системой уравнений img Каждое из этих уравнений может быть решено методом Гаусса. Заметим то обстоятельство, что все СЛАУ имеют одну и ту же матрицу коэффициентов, поэтому
Суть метода Гаусса-Жордана заключается в том, что если с единичной матрицей провести элементарные преобразования, которыми невырожденная квадратная матрица приводится к , то получится обратная матрица . Для отображения всех элементарных преобразований, совершающихся над матрицей , на единичную матрицу , удобно "склеить" две матрицы в одну. Если матрицы и имели размер , то склеенная матрица будет иметь размер . Таким образом, все преобразования над матрицей (перестановка строк, умножение строки на константу) будут автоматически совершаться и над единичной матрицей). Обозначим склеенную матрицу как Приведение матрицы к единичной совершается в два этапа: на первом этапе будем двигаться "сверху-вниз", получая в итоге треугольную матрицу, с единицами на главной диагонали и нулями ниже. На втором этапе будем двигаться "снизу-вверх", преобразуя элементы, лежащие выше главной диагонали к нулю, тем самым добиваясь единичной матрицы в результате.
Прямой ход
Пусть матрица имеет размер . Тогда на первом этапе будет совершено шагов. На каждом шаге необходимо совершить три действия.
- Поменять местами строки и , в случае если . Этот шаг необходим для исключения ситуации нахождения на главной диагонали 0.
- Преобразовать элемент, стоящий на главной диагонали к 1. Для этого необохдимо домножить всю строку на .
- Обнулить все нижележащие элементы столбца. Для этого вычтем из каждой нижележащей строки 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]