Skip to content

Instantly share code, notes, and snippets.

@wanooknox
Created March 12, 2013 02:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wanooknox/5139902 to your computer and use it in GitHub Desktop.
Save wanooknox/5139902 to your computer and use it in GitHub Desktop.
Recursive matrix determinants by cofactor expansion. Contains Minor, Cofactor, CofactorMatrix, Transpose, Adjoint, and Inverse methods. The corresponding IMatrix, AMatrix, and full Matrix class structure is not mine to post. Structure assumes matrix indexing is 1 based, not 0 based.
public double Minor(int row, int col)
{
//can only calculate a Minor value if the matrix is square
if (this.Rows != this.Cols)
{
throw new ApplicationException("Number of rows does not match number of columns");
}
//the sub matrix
Matrix subMatrix = (Matrix)this.NewMatrix(this.Rows - 1, this.Cols - 1);
//submatrix counters
int subRows = 1;
int subCols = 1;
for (int i = 1; i <= this.Rows; i++)
{
//if we are not on the passed in row
if (i != row)
{
for (int j = 1; j <= this.Cols; j++)
{
//if we are not on the passed in col
if (j != col)
{
//add this element to the sub matrix
subMatrix.SetElement(subRows, subCols, this.GetElement(i, j));
//increment cols
subCols++;
}
}
//increment rows, restart columns
subRows++;
subCols = 1;
}
}
//minor equals the determinant of the subMatrix
return subMatrix.Determinant();
}
public double Cofactor(int row, int col)
{
//a cofactor is (-1)^(i+j) * Minor(i,j)
return Math.Pow(-1, row + col) * this.Minor(row, col);
}
public double Determinant()
{
double result = 0;
//BASE CASE: if one of our dimesions is too small.
if (this.Rows <= 1 || this.Cols <= 1)
{
throw new ApplicationException("Row/Col less than 2");
}
//BASE CASE: if this is a 2x2 matrix
else if (this.Rows == 2 && this.Cols == 2)
{
//det(2x2) = ad-bc
result = (this.GetElement(1, 1) * this.GetElement(2, 2)) - (this.GetElement(1, 2) * this.GetElement(2, 1));
}
else //anything bigger than a 2x2
{
//for now, always use the first column to perform cofactor expansion.
//this could be done more efficiently if there is a row/col with multiple 0 elements
for (int i = 1; i <= this.Rows; i++)
{
result += this.GetElement(i, 1) * this.Cofactor(i, 1);
}
}
return result;
}
public Matrix CofactorMatrix()
{
//get a new mtrix to opperate on
Matrix coMatrix = (Matrix)this.NewMatrix(this.Rows, this.Cols);
//for every element
for (int i = 1; i <= this.Rows; i++)
{
for (int j = 1; j <= this.Cols; j++)
{
//insert the respective cofactor
coMatrix.SetElement(i, j, this.Cofactor(i, j));
}
}
return coMatrix;
}
public Matrix Adjoint()
{
//adjoint is the traspose of the cofactor matrix
return this.CofactorMatrix().Transpose();
}
public Matrix Transpose()
{
//get a matrix to opperate on
Matrix matrixT = (Matrix)this.NewMatrix(this.Rows, this.Cols);
//for every element
for (int i = 1; i <= this.Rows; i++)
{
for (int j = 1; j <= this.Cols; j++)
{
//transpose it's location
matrixT.SetElement(i, j, this.GetElement(j,i));
}
}
return matrixT;
}
public Matrix Inverse()
{
//get the determinant of the matrix
double det = this.Determinant();
//if it's not zero
if (det == 0)
{
throw new ApplicationException("Matrix is not invertible, determinant of 0");
}
//inverse is 1/det * adj()
// the * has been overloaded for scalar multiplication.
return (1 / det) * this.Adjoint();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment