Нахождение обратной матрицы на C#
Обратная матрица — это такая матрица, умножение которой на исходную матрицу дает единичную матрицу.
Искать обратную матрицу будем методом Крамера. По этому методу нужно построить матрицу алгебраических дополнений, транспонировать ее и поделить на детерминант исходной матрицы. Алгебраическое дополнение для элемента матрицы в i строке и j столбце — это соответствующий минор, умноженный на -1 в степени i+j.
Минор элемента матрицы в i строке и j столбце — это детерминант матрицы, получаемой из исходной вычеркиванием i строки и j столбца.
Так как в нашем классе матрицы уже написано достаточно много вспомогательных методов, кода написать нужно совсем немного
public Matrix CreateInvertibleMatrix() { if (this.M != this.N) return null; var determinant = CalculateDeterminant(); if (Math.Abs(determinant) < Constants.DoubleComparisonDelta) return null; var result = new Matrix(M, M); ProcessFunctionOverData((i, j) => { result[i, j] = ((i + j) % 2 == 1 ? -1 : 1) * CalculateMinor(i, j) / determinant; }); result = result.CreateTransposeMatrix(); return result; }
Первая половина метода — проверка того, что матрица квадратная и что детеринант не равен 0. Вторая — непосредственно метод крамера.
Осталось только посчитать минор:
private double CalculateMinor(int i, int j) { return CreateMatrixWithoutColumn(j) .CreateMatrixWithoutRow(i) .CalculateDeterminant(); }
При написании тестов столкнулся с необходимостью сравнивать матрицы и написал соответствующий метод:
public static void AssertMatrixEqual(Matrix expected, Matrix actual) { Assert.Equal(expected.M, actual.M); Assert.Equal(expected.N, actual.N); for (var i = 0; i < expected.M; i++) for (var j = 0; j < expected.N; j++) AssertDoubleEqual(expected[i, j], actual[i, j]); }
Полный исходный код можно найти на github