public void toReducedRowEchelonForm() { InvertibleBinaryOperation<T> addition = ring.addition(); InvertibleBinaryOperation<T> multiplication = (InvertibleBinaryOperation<T>) ring.multiplication(); toRowEchelonForm(); int j = 0; for (int i = 0; i < m; i++) { while (j < n) { T aij = get(i, j); if (!aij.equals(zero)) { aij = multiplication.inverse(aij); for (int k = j + 1; k < n; k++) { T aik = multiplication.op(get(i, k), aij); set(i, k, aik); for (int l = 0; l < i; l++) set( l, k, addition.op(get(l, k), addition.inverse(multiplication.op(aik, get(l, j))))); } set(i, j, one); for (int l = 0; l < i; l++) set(l, j, zero); j++; break; } j++; } } }
public Matrix<T> getKernelBasis() { Matrix<T> reducedRowEchelonForm = getReducedRowEchelonForm(); boolean[] hasLeadingOne = new boolean[n]; List<Integer> indices = new ArrayList<Integer>(); int j = 0; for (int i = 0; i < m; i++) while (j < n) { T aij = reducedRowEchelonForm.get(i, j); if (!aij.equals(zero)) { if (!aij.equals(one)) throw new Error(); indices.add(j); hasLeadingOne[j] = true; j++; break; } j++; } InvertibleBinaryOperation<T> addition = ring.addition(); Matrix<T> kernelBasis = new Matrix<T>(ring, n, n - indices.size()); kernelBasis.zero(); int k = 0; for (int i = 0; i < n; i++) if (!hasLeadingOne[i]) { kernelBasis.set(i, k, one); for (int l = 0; l < indices.size(); l++) kernelBasis.set(indices.get(l), k, addition.inverse(reducedRowEchelonForm.get(l, i))); k++; } if (k != kernelBasis.n) throw new Error(k + " / " + indices.size()); return kernelBasis; }
public void toRowEchelonForm() { InvertibleBinaryOperation<T> plus = ring.addition(); BinaryOperationWithIdentity<T> times = ring.multiplication(); for (int row = 0, column = 0; column < n; column++) { int pivot; for (pivot = row; pivot < m; pivot++) if (!get(pivot, column).equals(zero)) break; if (pivot != m) { // is this column already done? if (pivot != row) // swap rows row and pivot for (int j = column; j < n; j++) { T tmp = get(pivot, j); set(pivot, j, get(row, j)); set(row, j, tmp); } for (int i = row + 1; i < m; i++) if (!(get(i, column).equals(zero))) { for (int j = column + 1; j < n; j++) // a_i,j = a_row,column * a_i,j - a_row,j * a_i,column set( i, j, plus.op( times.op(get(row, column), get(i, j)), plus.inverse(times.op(get(row, j), get(i, column))))); set(i, column, zero); } row++; } } }
public static <T> Matrix<T> subspaceIntersection(Matrix<T> m1, Matrix<T> m2) { if (m1.m != m2.m) throw new IllegalArgumentException(); if (m1.ring != m2.ring) throw new IllegalArgumentException(); Matrix<T> m = new Matrix<T>(m1.ring, m1.m, m1.n + m2.n); for (int i = 0; i < m1.m; i++) { for (int j = 0; j < m1.n; j++) m.set(i, j, m1.get(i, j)); for (int j = 0; j < m2.n; j++) m.set(i, m1.n + j, m2.get(i, j)); } Matrix<T> kernelBasis = m.getKernelBasis(); return product(m1, kernelBasis.getSubmatrix(m1.n, kernelBasis.n)); }
public void solveFor(Matrix<T> b) { if (m != n || m != b.m) throw new IllegalArgumentException(); Field<T> field = (Field<T>) ring; InvertibleBinaryOperation<T> times = field.multiplication(); InvertibleBinaryOperation<T> plus = field.addition(); for (int i = 0; i < m; i++) { int pivotIndex = i; for (; pivotIndex < m; pivotIndex++) if (!get(pivotIndex, i).equals(zero)) break; if (pivotIndex == m) throw new ArithmeticException("singular system"); // swap two equations to bring the pivot to the diagonal Object[] swapRow = matrix[pivotIndex]; matrix[pivotIndex] = matrix[i]; matrix[i] = swapRow; for (int j = 0; j < b.n; j++) { T swap = b.get(pivotIndex, j); b.set(pivotIndex, j, b.get(i, j)); b.set(i, j, swap); } // normalize current row. T pivot = times.inverse(get(i, i)); for (int j = i + 1; j < n; j++) set(i, j, times.op(get(i, j), pivot)); for (int j = 0; j < b.n; j++) b.set(i, j, times.op(b.get(i, j), pivot)); // subtract multiples of it from the ones below. for (int k = i + 1; k < m; k++) { T first = get(k, i); if (!first.equals(zero)) { for (int j = i + 1; j < n; j++) // buf [k] [j] -= first * buf [i] [j]; set(k, j, plus.op(get(k, j), plus.inverse(times.op(first, get(i, j))))); for (int j = 0; j < b.n; j++) // x [k] -= first * x [i]; b.set(k, j, plus.op(b.get(k, j), plus.inverse(times.op(first, b.get(i, j))))); } } } // now back-substitute for (int k = m - 1; k > 0; k--) for (int i = 0; i < k; i++) for (int j = 0; j < b.n; j++) b.set(i, j, plus.op(b.get(i, j), plus.inverse(times.op(get(i, k), b.get(k, j))))); }
private T determinantByDimensionalReduction(int k) { if (k == 0) return get(0, 0); InvertibleBinaryOperation<T> plus = ring.addition(); BinaryOperationWithIdentity<T> times = ring.multiplication(); T result = times.op( plus.op(get(k, k), plus.inverse(times.identity())), determinantByDimensionalReduction(k - 1)); for (int i = 0; i < k; i++) for (int j = 0; j < k; j++) set(i, j, plus.op(get(i, j), plus.inverse(times.op(get(i, k), get(k, j))))); result = plus.op(result, determinantByDimensionalReduction(k - 1)); for (int i = 0; i < k; i++) for (int j = 0; j < k; j++) set(i, j, plus.op(get(i, j), times.op(get(i, k), get(k, j)))); return result; }
public Matrix<T> getSubmatrix(int m1, int m2, int n1, int n2) { if (m1 > m2 || n1 > n2 || m1 < 0 || n2 < 0 || m2 > m || n2 > n) throw new IllegalArgumentException( "[" + m1 + "," + m2 + "] x [" + n1 + "," + n2 + "] from " + m + " x " + n); Matrix<T> submatrix = new Matrix<T>(ring, m2 - m1, n2 - n1); for (int i = m1; i < m2; i++) for (int j = n1; j < n2; j++) submatrix.set(i - m1, j - n1, get(i, j)); return submatrix; }
public static <T> Matrix<T> sum(Matrix<T> A, Matrix<T> B) { if (A.ring != B.ring || A.m != B.m || A.n != B.n) throw new IllegalArgumentException(A.m + " x " + A.n + ", " + B.m + " x " + B.n); InvertibleBinaryOperation<T> addition = A.ring.addition(); Matrix<T> sum = new Matrix<T>(A.ring, A.m, A.n); for (int i = 0; i < A.m; i++) for (int j = 0; j < A.n; j++) sum.set(i, j, addition.op(A.get(i, j), B.get(i, j))); return sum; }
public static <T> Matrix<T> product(Matrix<T> A, Matrix<T> B) { if (A.ring != B.ring || A.n != B.m) throw new IllegalArgumentException(); BinaryOperation<T> addition = A.ring.addition(); BinaryOperation<T> times = A.ring.multiplication(); Matrix<T> product = new Matrix<T>(A.ring, A.m, B.n); for (int i = 0; i < A.m; i++) for (int k = 0; k < B.n; k++) { T t = A.zero; for (int j = 0; j < A.n; j++) t = addition.op(t, times.op(A.get(i, j), B.get(j, k))); product.set(i, k, t); } return product; }
public void add(int i, int j, T t) { set(i, j, ring.addition().op(get(i, j), t)); }
public Matrix<T> changeRing(Ring<T> ring) { Matrix<T> result = new Matrix<T>(ring, m, n); for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) result.set(i, j, get(i, j)); return result; }
public Matrix<T> getTranspose() { Matrix<T> transpose = new Matrix<T>(ring, n, m); for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) transpose.set(j, i, get(i, j)); return transpose; }