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 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> 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 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 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 Matrix<T> getReducedRowEchelonForm() { Matrix<T> reducedRowEchelonForm = copy(); reducedRowEchelonForm.toReducedRowEchelonForm(); return reducedRowEchelonForm; }
public Matrix<T> getRowEchelonForm() { Matrix<T> rowEchelonForm = copy(); rowEchelonForm.toRowEchelonForm(); return rowEchelonForm; }
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 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))))); }
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; }