/// <summary> /// Computes the reduced row echelon form of the matrix. /// </summary> /// <param name="matrix"></param> /// <returns></returns> public static AugmentedMatrix ReducedRowEchelonForm(this AugmentedMatrix augMatrix) { augMatrix = augMatrix.GaussianElimination(); var gaussElimResult = augMatrix[0]; int iMax = Math.Min(gaussElimResult.Columns, gaussElimResult.Rows); for (int i = 0, currentCol = 0; i < iMax && currentCol < gaussElimResult.Columns; i++, currentCol++) { var currentStartElement = gaussElimResult[i, currentCol]; if (Math.Abs(currentStartElement) > TOLERANCE) { // If the current start element does not equal 1 then fix it if (Math.Abs(currentStartElement - 1) > TOLERANCE) { augMatrix = augMatrix.MultiplyRowByScalar(i, 1.0 / currentStartElement); } for (int j = 0; j <= i - 1; j++) { var ratio = -1.0 * gaussElimResult[j, currentCol] * gaussElimResult[i, currentCol]; augMatrix = augMatrix.AddRows(i, j, ratio); } } else { i--; // The test element was zero, do not increment the row } } return(augMatrix); }
/// <summary> /// Performs gaussian elimination on the given matrix. /// </summary> /// <param name="matrix"></param> /// <returns></returns> public static AugmentedMatrix GaussianElimination(this AugmentedMatrix augMatrix) { // Derived from ref [1] Theorem 3.5 // identify the row with the first non zero element int nonZeroRowIndex = 0; bool run = true; int nonZeroColumnIndex = 0; while (run && nonZeroColumnIndex < augMatrix[0].Columns) { // Check if columns has non-zero entry var col = augMatrix[0].GetColumn(nonZeroColumnIndex); for (int j = 0; j < col.Length; j++) { if (Math.Abs(col[j]) > TOLERANCE) { nonZeroRowIndex = j; run = false; break; } } if (run) { nonZeroColumnIndex++; } } // Move this row into the top position if (nonZeroRowIndex != 0) { augMatrix = augMatrix.SwapRows(nonZeroRowIndex, 0); } // If the first non zero row does not equal 1 then normalize the if (Math.Abs(augMatrix[0][0, nonZeroColumnIndex] - 1.0) > TOLERANCE) { augMatrix = augMatrix.MultiplyRowByScalar(0, 1.0 / augMatrix[0][0, nonZeroColumnIndex]); } int iMax = Math.Min(augMatrix[0].Columns, augMatrix[0].Rows); // Zero-wise columns for (int i = 0, currentCol = 0; i < iMax && currentCol < augMatrix[0].Columns; i++, currentCol++) { var currentStartElement = augMatrix[0][i, currentCol]; if (Math.Abs(currentStartElement) > TOLERANCE) { for (int j = i + 1; j < iMax; j++) { var ratio = -1.0 * (augMatrix[0][j, currentCol] / currentStartElement); augMatrix = augMatrix.AddRows(i, j, ratio); } } else { i--; // The test element was zero, do not increment the row } } return(augMatrix); }