import java.util.*; import java.lang.Math; import org.apache.commons.math.fraction.Fraction; import org.apache.commons.math.fraction.FractionConversionException; /* Matrix class * Handles elementary Matrix operations: * Interchange * Multiply and Add * Scale * Reduced Row Echelon Form */ class Matrix { LinkedList> matrix; int numRows; int numCols; static class Coordinate { int row; int col; Coordinate(int r, int c) { row = r; col = c; } public String toString() { return "(" + row + ", " + col + ")"; } } Matrix(double [][] m) { numRows = m.length; numCols = m[0].length; matrix = new LinkedList>(); for (int i = 0; i < numRows; i++) { matrix.add(new LinkedList()); for (int j = 0; j < numCols; j++) { try { matrix.get(i).add(new Fraction(m[i][j])); } catch (FractionConversionException e) { System.err.println("Fraction could not be converted from double by apache commons . . ."); } } } } public void Interchange(Coordinate a, Coordinate b) { LinkedList temp = matrix.get(a.row); matrix.set(a.row, matrix.get(b.row)); matrix.set(b.row, temp); int t = a.row; a.row = b.row; b.row = t; } public void Scale(Coordinate x, Fraction d) { LinkedList row = matrix.get(x.row); for (int i = 0; i < numCols; i++) { row.set(i, row.get(i).multiply(d)); } } public void MultiplyAndAdd(Coordinate to, Coordinate from, Fraction scalar) { LinkedList row = matrix.get(to.row); LinkedList rowMultiplied = matrix.get(from.row); for (int i = 0; i < numCols; i++) { row.set(i, row.get(i).add((rowMultiplied.get(i).multiply(scalar)))); } } public void RREF() { Coordinate pivot = new Coordinate(0,0); int submatrix = 0; for (int x = 0; x < numCols; x++) { pivot = new Coordinate(pivot.row, x); //Step 1 //Begin with the leftmost nonzero column. This is a pivot column. The pivot position is at the top. for (int i = x; i < numCols; i++) { if (isColumnZeroes(pivot) == false) { break; } else { pivot.col = i; } } //Step 2 //Select a nonzero entry in the pivot column with the highest absolute value as a pivot. pivot = findPivot(pivot); if (getCoordinate(pivot).doubleValue() == 0.0) { pivot.row++; continue; } //If necessary, interchange rows to move this entry into the pivot position. //move this row to the top of the submatrix if (pivot.row != submatrix) { Interchange(new Coordinate(submatrix, pivot.col), pivot); } //Force pivot to be 1 if (getCoordinate(pivot).doubleValue() != 1) { /* System.out.println(getCoordinate(pivot)); System.out.println(pivot); System.out.println(matrix); */ Fraction scalar = getCoordinate(pivot).reciprocal(); Scale(pivot, scalar); } //Step 3 //Use row replacement operations to create zeroes in all positions below the pivot. //belowPivot = belowPivot + (Pivot * -belowPivot) for (int i = pivot.row; i < numRows; i++) { if (i == pivot.row) { continue; } Coordinate belowPivot = new Coordinate(i, pivot.col); Fraction complement = (getCoordinate(belowPivot).negate().divide(getCoordinate(pivot))); MultiplyAndAdd(belowPivot, pivot, complement); } //Step 5 //Beginning with the rightmost pivot and working upward and to the left, create zeroes above each pivot. //If a pivot is not 1, make it 1 by a scaling operation. //Use row replacement operations to create zeroes in all positions above the pivot for (int i = pivot.row; i >= 0; i--) { if (i == pivot.row) { if (getCoordinate(pivot).doubleValue() != 1.0) { Scale(pivot, getCoordinate(pivot).reciprocal()); } continue; } if (i == pivot.row) { continue; } Coordinate abovePivot = new Coordinate(i, pivot.col); Fraction complement = (getCoordinate(abovePivot).negate().divide(getCoordinate(pivot))); MultiplyAndAdd(abovePivot, pivot, complement); } //Step 4 //Ignore the row containing the pivot position and cover all rows, if any, above it. //Apply steps 1-3 to the remaining submatrix. Repeat until there are no more nonzero entries. if ((pivot.row + 1) >= numRows || isRowZeroes(new Coordinate(pivot.row+1, pivot.col))) { break; } submatrix++; pivot.row++; } } public boolean isColumnZeroes(Coordinate a) { for (int i = 0; i < numRows; i++) { if (matrix.get(i).get(a.col).doubleValue() != 0.0) { return false; } } return true; } public boolean isRowZeroes(Coordinate a) { for (int i = 0; i < numCols; i++) { if (matrix.get(a.row).get(i).doubleValue() != 0.0) { return false; } } return true; } public Coordinate findPivot(Coordinate a) { int first_row = a.row; Coordinate pivot = new Coordinate(a.row, a.col); Coordinate current = new Coordinate(a.row, a.col); for (int i = a.row; i < (numRows - first_row); i++) { current.row = i; if (getCoordinate(current).doubleValue() == 1.0) { Interchange(current, a); } } current.row = a.row; for (int i = current.row; i < (numRows - first_row); i++) { current.row = i; if (getCoordinate(current).doubleValue() != 0) { pivot.row = i; break; } } return pivot; } public Fraction getCoordinate(Coordinate a) { return matrix.get(a.row).get(a.col); } public String toString() { return matrix.toString().replace("], ", "]\n"); } public static void main (String[] args) { double[][] matrix_1 = { {1, 2, -1, -4}, {2, 3, -1, -11}, {-2, 0, -3, 22} }; Matrix x = new Matrix(matrix_1); System.out.println("before\n" + x.toString() + "\n"); x.RREF(); System.out.println("after\n" + x.toString() + "\n"); double matrix_2 [][] = { {2, 0, -1, 0, 0}, {1, 0, 0, -1, 0}, {3, 0, 0, -2, -1}, {0, 1, 0, 0, -2}, {0, 1, -1, 0, 0} }; Matrix y = new Matrix(matrix_2); System.out.println("before\n" + y.toString() + "\n"); y.RREF(); System.out.println("after\n" + y.toString() + "\n"); double matrix_3 [][] = { {1, 2, 3, 4, 3, 1}, {2, 4, 6, 2, 6, 2}, {3, 6, 18, 9, 9, -6}, {4, 8, 12, 10, 12, 4}, {5, 10, 24, 11, 15, -4} }; Matrix z = new Matrix(matrix_3); System.out.println("before\n" + z.toString() + "\n"); z.RREF(); System.out.println("after\n" + z.toString() + "\n"); double matrix_4 [][] = { {0, 1}, {1, 2}, {0,5} }; Matrix a = new Matrix(matrix_4); System.out.println("before\n" + a.toString() + "\n"); a.RREF(); System.out.println("after\n" + a.toString() + "\n"); } }