Нахождение обратной матрицы на C#

04.09.2019 at 09:38

Обратная матрица — это такая матрица, умножение которой на исходную матрицу дает единичную матрицу.

Искать обратную матрицу будем методом Крамера. По этому методу нужно построить матрицу алгебраических дополнений, транспонировать ее и поделить на детерминант исходной матрицы. Алгебраическое дополнение для элемента матрицы в 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

Tags: