From ab78365644f52a0330b430bf314accdb77e31d42 Mon Sep 17 00:00:00 2001 From: Daniel Weschke Date: Fri, 14 Mar 2014 22:10:43 +0100 Subject: [PATCH] Deploy matrix --- src/math/matrix/Matrix.java | 2603 +++++++++++++++++++++++++++++++++++ 1 file changed, 2603 insertions(+) create mode 100644 src/math/matrix/Matrix.java diff --git a/src/math/matrix/Matrix.java b/src/math/matrix/Matrix.java new file mode 100644 index 0000000..e45cd53 --- /dev/null +++ b/src/math/matrix/Matrix.java @@ -0,0 +1,2603 @@ +package math.matrix; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Serializable; +import java.io.StreamTokenizer; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Locale; +import java.util.Scanner; + +import math.Maths; +import string.WString; +import thisandthat.WObject; +import exception.ComplexException; +import exception.IllegalDimensionException; +import exception.NoSquareException; +import exception.SingularException; + +/** + * Matrix object M∈ℝ + * with m rows and n columns + * @author Daniel Weschke + * @version 01 November 2013 + */ +public class Matrix extends WObject implements Cloneable, Serializable{ + + enum Flag{Square, Symmetric} // TODO: subclass? + + /** + * UID + */ + private static final long serialVersionUID = 6314556279121894887L; + + /** + * Row dimension. + * @serial m rows + */ + protected int m; + + /** + * Column dimension. + * @serial n columns + */ + protected int n; + + /** + * @serial data array for internal storage of elements + */ +// private double[][] data; + protected double[] data; + + /** + * @serial solution of eigenvalue decomposition + */ + private EigenvalueDecomposition eig; + + /** + * Create null-object matrix + */ + public Matrix(){ + } + + /** + * Create an m-by-n matrix of zeros. + * @param m number of rows + * @param n number of columns + */ + public Matrix(int m, int n){ + this.m = m; + this.n = n; +// data = new double[m][n]; + data = new double[m*n]; + } + + /** + * Create an m-by-n matrix of scalar value. + * @param m number of rows + * @param n number of columns + * @param s scalar value + */ + public Matrix(int m, int n, double s){ + this(m, n); + int i,j; + for(i=0; ib.length ? a.length : b.length, 2); + int i; + for(i=0; i1, a2, ..., amn} → + * {{a1, a2, ..., a1n}, + * {a1n+1, a1n+2, ..., a2n} + * @param n number of columns. + * @param a one-dimensional array of doubles, packed by rows. + * @exception IllegalArgumentException Array length must be a multiple of m. + */ + public Matrix(int n, double[] a){ + this((n!=0 ? a.length/n : 0),n); + if(m*n != a.length) + throw new IllegalArgumentException("Array length must be a multiple of n."); + int i,j; + for(i=0; i1, a2, ..., amn} → + * {{a1, a2, ..., a1n}, + * {a1n+1, a1n+2, ..., a2n} + * @param a one-dimensional array of doubles, packed by columns. + * @param m number of rows. + * @exception IllegalArgumentException Array length must be a multiple of m. + */ + public Matrix(double[] a, int m){ + this(m,(m!=0 ? a.length/m : 0)); + if(m*n != a.length) + throw new IllegalArgumentException("Array length must be a multiple of m."); + int i,j; + for(i=0; iij at given row i and column j + * @param i row + * @param j column + * @return the value at the given row i and column j + * @throws IllegalDimensionException + */ + public double get(int i, int j){ +// return data[i][j]; + int index; + index = i*n + j; + return data[index]; + } + + /** + * Get a sub matrix. + * @param is first row index + * @param ie last row index + * @param js first column index + * @param je last column index + * @return sub matrix + */ + public Matrix get(int is, int ie, int js, int je) throws ArrayIndexOutOfBoundsException{ + int i,j; + Matrix c = new Matrix(ie-is+1,je-js+1); + for(i=is; i<=ie; i++) + for(j=js; j<=je; j++) + c.set(i-is, j-js, get(i,j)); + return c; + } + + /** + * Get a sub matrix only with chosen rows and columns. + * @param i row indices + * @param j column indices + * @return sub matrix + */ + public Matrix get(int[] i, int[] j){ + return get(i, j, false); + } + + /** + * Get a sub matrix only with chosen rows and columns. + * @param i row indices + * @param j column indices + * @return sub matrix + */ + public Matrix get(int[] i, int[] j, boolean positions){ + int ii,jj; + int ni = i.length; + int mj = j.length; + int d = positions?1:0; + Matrix a = new Matrix(ni,mj); + for(ii=0; iiij = aij + b + * @param i row + * @param j column + * @param b scalar + */ + public void plus(int i, int j, double b){ + set(i,j, get(i,j)+b); + } + + /** + * Adds two matrices of the same dimension (entrywise addition). + * The addition of two m-by-n matrices A and B, + * is again an m-by-n matrix computed by adding corresponding elements. + * @param B matrix + * @return C = A + B, entrywise summarized matrix + * @throws IllegalDimensionException + */ + public Matrix plus(Matrix B) throws IllegalDimensionException{ + checkDimensions(B); + int i,j; + Matrix c = create(this); + if(B instanceof Diagonal) + for(i=0; iA and B, + * is again an m-by-n matrix computed by adding corresponding elements. + * @param B matrix + * @return A = A + B, entrywise summarized matrix + * @throws IllegalDimensionException + */ + public Matrix plusEquals(Matrix B) throws IllegalDimensionException { + checkDimensions(B); + int i, j; + if(B instanceof Diagonal) + for(i=0; iA and B, + * is again an m-by-n matrix computed by subtracting corresponding elements. + * @param B matrix + * @return C = A - B, entrywise subtracted matrix + * @throws IllegalDimensionException + */ + public Matrix minus(Matrix B) throws IllegalDimensionException{ + checkDimensions(B); + int i,j; + Matrix c = create(B); + System.out.println(this); + System.out.println(B); + if(B instanceof Diagonal) + for(i=0; iA and B, + * is again an m-by-n matrix computed by subtracting corresponding elements. + * @param B matrix + * @throws IllegalDimensionException + */ + public Matrix minusEquals(Matrix B) throws IllegalDimensionException { + checkDimensions(B); + int i,j; + if(B instanceof Diagonal) + for(i=0; iA of size m x n and + * B of size p x q is a matrix of size (m + p) x (n + q). + * @param B matrix + * @return C = AB matrix of size (m + p) × (n + q) + */ + public Matrix sumDirect(Matrix B){ + int i,j = 0,k,l; + Matrix c = new Matrix(m+B.m,n+B.n); + for(i=0; iC = s A + */ + public Matrix times(double s){ + int i,j; + Matrix c = create(m,n); + if(this instanceof Diagonal) + for(i=0; iij = scij + * @param i + * @param j + * @param s + */ + public void times(int i, int j, double s){ + set(i,j, s*get(i,j)); + } + + /** + * Scalar multiplication. Multiply a matrix element-wise by a scalar. + * @param s scalar + * @return A = s A + */ + public Matrix timesEquals(double s){ + int i,j; + if(this instanceof Diagonal) + for(i=0; iC = Ab = A b + * @throws IllegalDimensionException Illegal vector dimensions. + */ + public Vector times(Vector b) throws IllegalDimensionException{ + int i,j; + if(n != b.n()) throw new IllegalDimensionException("Illegal vector dimensions."); + Vector c = create(m); + if(this instanceof Diagonal) + for(i=0; iC = A B + * @throws IllegalDimensionException Inner matrix dimensions must agree. + */ + public Matrix times(Matrix B) throws IllegalDimensionException{ + int i,j,k; + if(n != B.m) throw new IllegalDimensionException("Inner matrix dimensions must agree."); + Matrix c = create(m,B.n,B); + if(B instanceof Diagonal) + for(i=0; iC = A sB + * @throws IllegalDimensionException Inner matrix dimensions must agree. + */ + public Matrix times(double s, Matrix B) throws IllegalDimensionException{ + return times(s).times(B); + } + + // TODO: too lame, check 0 then calculate only sub matrix + /** + * Multiply a matrix right + * @param B matrix + * @return C = A B + * @throws IllegalDimensionException Inner matrix dimensions must agree. + */ + public Matrix timesV2(Matrix B) throws IllegalDimensionException{ + int i,j,k; + Vector p,q; + if(n != B.m) throw new IllegalDimensionException("Inner matrix dimensions must agree."); + Matrix c = create(m,B.n); + for(i=0; iu • Av = uT A v + * @throws IllegalDimensionException + */ + public double times(Vector u, Vector v) throws IllegalDimensionException{ + return u.times(this).dot(v); + } + + /** + * Multiply a matrix left and a matrix right + * @param U matrix + * @param V matrix + * @return C = U A V + * @throws IllegalDimensionException + */ + public Matrix times(Matrix U, Matrix V) throws IllegalDimensionException{ + return U.times(this).times(V); + } + + /** + * Hadamard / Schur Product. Element-wise multiplication with a matrix B + * @param B matrix + * @return ci,j = ai,j bi,j + * @throws IllegalDimensionException + */ + public Matrix hadamardProduct(Matrix B) throws IllegalDimensionException { + checkDimensions(B); + int i,j; + if(this instanceof Diagonal){ + Diagonal c = new Diagonal(m,B.n); + for(i=0; ii,j = ai,j bi,j + * @throws IllegalDimensionException + */ + public Matrix hadamardProductEquals(Matrix B) throws IllegalDimensionException { + checkDimensions(B); + int i,j; + for(i=0; iA:B= + * ΣiΣjAijBij= + * vec(A)Tvec(B)= + * tr(ATB)=tr(ABT) + * @throws IllegalDimensionException + * @throws NoSquareException + */ + public double frobeniusProduct(Matrix B) throws IllegalDimensionException, NoSquareException{ + return this.transpose().times(B).trace(); + } + + /** + * Kronecker product. + * @param B matrix + * @return (A⊗B)ij=(A)ijB + */ + public Matrix kroneckerProduct(Matrix B){ + int i, j; + Matrix C = new Matrix(m*B.m,n*B.n); + for(i=0; ii,j = ai,j / bi,j + * @throws IllegalDimensionException + */ + public Matrix hadamardDivision(Matrix B) throws IllegalDimensionException { + checkDimensions(B); + int i,j; + Matrix c = create(m,n); + for(i=0; ii,j = ai,j / bi,j + * @throws IllegalDimensionException + */ + public Matrix hadamardDivisionRightEquals(Matrix B) throws IllegalDimensionException { + checkDimensions(B); + int i,j; + for(i=0; ii,j = bi,j / ai,j + * @throws IllegalDimensionException + */ + public Matrix hadamardDivisionLeftEquals(Matrix B) throws IllegalDimensionException { + checkDimensions(B); + int i,j; + for(i=0; iC = A / s + */ + public Matrix over(double s){ + return times(1/s); + } + + /** + * Divide this matrix A by a matrix B + * @param B matrix + * @return C = A / B + * @throws NoSquareException + * @throws SingularException + * @throws IllegalDimensionException + */ + public Matrix over(Matrix B) throws NoSquareException, SingularException, IllegalDimensionException{ + return times(B.inverse()); + } + + /** + * @param e exponent + * @return the matrix to the power of e + * @throws IllegalDimensionException + */ + public Matrix pow(double e) throws IllegalDimensionException{ + int i; + Matrix C = create(m,n); + if(this instanceof Diagonal) + for(i=0; i<(mT + */ + public Matrix transpose(){ + int i, j; + if(this instanceof Diagonal || isDiagonal()) + return new Diagonal(this); + Matrix c = create(n,m); +// System.out.println(m + " " + n); +// System.out.println(c.m + " " + c.n); + for(i=0; i<(mA is the matrix A-1 + * where A-1 A = I , + * with I as the identity matrix. + * A matrix that have inverse is called non-singular or invertible + * otherwise it is called singular. + * @return the inverse matrix. For a singular matrix the values of the + * inverted matrix are either NaN or Infinity + * @throws SingularException + * @see #inverse() + */ + public Matrix inverse() throws SingularException{ + if(n==1 && n==m){ + if(get(0,0)==0.0) throw new SingularException(); + return new Matrix(1.0/det()); + } + return cofactor().transpose().times(1/det()); + } + + /** + * Inverse of a square matrix A is the matrix A-1 + * where A-1 A = I , + * with I as the identity matrix. + * A matrix that have inverse is called non-singular or invertible + * otherwise it is called singular. + * @return the inverse matrix. For a singular matrix the values of the + * inverted matrix are either NaN or Infinity + * @throws NoSquareException + * @throws SingularException + * @see #inverse() + */ + public Matrix inverse(int analytic) throws NoSquareException, SingularException{ + if(n==1 && n==m){ + if(get(0,0)==0.0) throw new SingularException(); + return new Matrix(1.0/det(analytic)); + } + return cofactor(1).transpose().times(1/det(analytic)); + } + + /** + * Inverse or pseudoinverse of a square matrix + * NOTE: No good in FachwerkLinear: K-1 + * @return inverse(A) if A is square, pseudoinverse otherwise. + * @see #inverse() + */ + public Matrix inverse2() { + return solve(identity(m,m)); + } + + /** + * Cofactor of a matrix
+ * The cofactor of a matrix A is matrix C + * that the value of element Cij equals the determinant of a matrix + * created by removing row i and column j from matrix A. + * @return the cofactor of the matrix + */ + public Matrix cofactor(){ + if(m==1) return new Matrix(get()); + int i, j; + Matrix mat = create(m, n); + for(i=0; i + * The cofactor of a matrix A is matrix C + * that the value of element Cij equals the determinant of a matrix + * created by removing row i and column j from matrix A. + * @return the cofactor of the matrix + * @throws NoSquareException + */ + public Matrix cofactor(int analytic) throws NoSquareException { + if(m==1) return new Matrix(get()); + int i, j; + Matrix mat = create(m, n); + for(i=0; im?n:m; + Vector d = create(nn); + int i; + for(i=0; imax/smin. + */ + public double cond(){ + return new SingularValueDecomposition(this).cond(); + } + + /** + * Solve A X = B + * @param B right hand side + * @return solution if A is square, least squares solution otherwise + */ + public Matrix solve(Matrix B){ + return (m == n ? (new LUDecomposition(this)).solve(B) : + (new QRDecomposition(this)).solve(B)); + } + + /** + * Solve X A = B, which is also A' X' = B' + * @param B right hand side + * @return solution if A is square, least squares solution otherwise. + */ + public Matrix solveTranspose(Matrix B){ + return transpose().solve(B.transpose()); + } + + /** + * A x = b, + * assuming A is square and has full rank + * @param b matrix (as vector) + * @return x = A-1 b + */ + public Vector solve(Vector b){ + if (m != n || b.n() != n) + throw new IllegalArgumentException("Illegal matrix dimensions."); + + // create copies of the data + Matrix A = create(this); + Vector B = create(b); + + // Gaussian elimination with partial pivoting + for (int i = 0; i < n; i++) { + + // find pivot row and swap + int max = i; + for (int j = i + 1; j < n; j++) + if(Math.abs(A.get(j,i)) > Math.abs(A.get(max,i))) + max = j; + A.swap(i, max); + B.swap(i, max); + + // singular + if (A.get(i,i) == 0.0){ + System.err.println("Matrix is singular."); + return null; + } + + // pivot within b + for (int j = i + 1; j < n; j++) + B.set(j, B.get(j) - B.get(i) * A.get(j,i) / A.get(i,i)); + + // pivot within A + for (int j = i + 1; j < n; j++) { + double m = A.get(j,i) / A.get(i,i); + for (int k = i+1; k < n; k++) { + A.minus(j,k, A.get(i,k) * m); + } + A.set(j,i, 0.0); + } + } + + // back substitution + Vector x = create(n); + for (int j = n - 1; j >= 0; j--) { + double t = 0.0; + for (int k = j + 1; k < n; k++) + t += A.get(j,k) * x.get(k); + x.set(j, (B.get(j) - t) / A.get(j,j)); + } + return x; + } + + /** + * @return LUDecomposition + * @see LUDecomposition + */ + public LUDecomposition lu(){ + return new LUDecomposition(this); + } + + /** + * @return QRDecomposition + * @see QRDecomposition + */ + public QRDecomposition qr(){ + return new QRDecomposition(this); + } + + /** + * @return CholeskyDecomposition + * @see CholeskyDecomposition + */ + public CholeskyDecomposition chol(){ + return new CholeskyDecomposition(this); + } + + /** + * @return SingularValueDecomposition + * @see SingularValueDecomposition + */ + public SingularValueDecomposition svd(){ + return new SingularValueDecomposition(this); + } + + /** + * @return EigenvalueDecomposition + * @see EigenvalueDecomposition + */ + public EigenvalueDecomposition eig(){ + eig = new EigenvalueDecomposition(this); + return eig; + } + + /** + * Eigenvalues calculated with the QR algorithm. + * @return eigenvalues λi + * @see EigenvalueDecomposition + */ + public Matrix eigenvalues(){ + if(eig == null) eig(); + return create(eig.getD()); + } + + /** + * Real eigenvalues calculated with the QR algorithm. + * @return eigenvalues λi + * @see EigenvalueDecomposition + */ + public Vector eigenvaluesRe(){ + if(eig == null) eig(); + return create(eig.getRealEigenvalues()); + } + + /** + * Imaginary eigenvalues calculated with the QR algorithm. + * @return eigenvalues λi + * @see EigenvalueDecomposition + */ + public VectorComplex eigenvaluesIm(){ + if(eig == null) eig(); + return new VectorComplex(eig.getRealEigenvalues(), eig.getImagEigenvalues()); + } + + /** + * @return eigenvectors xi in matrix Λ + */ + public Matrix eigenvectors(){ + if(eig == null) eig(); + return create(eig.getV()); + } + + /** + * Real eigenvalue calculated with the root formula of second and third degree. + * @return eigenvalues λi + * @throws NoSquareException + * @throws IllegalDimensionException + * @throws ComplexException + */ + public Vector eigenvaluesRe(int analytic) throws NoSquareException, IllegalDimensionException, ComplexException{ + // TODO also n > 3 + // TODO: also Imaginary + if(m!=n && m>3) throw new IllegalDimensionException("Illegal matrix dimensions."); + Vector lambda = new Vector(m); + if(m==1) lambda.set(0, get(0, 0)); + else if(isR2()) lambda = new Matrix2D(this).eigenvaluesRe(analytic); + else if(isR3()) lambda = new Matrix3D(this).eigenvaluesRe(analytic); + return lambda; + } + + /** + * Compute Cholesky decomposition of symmetric positive definite + * matrix A = LL^T. + * @return Cholesky factor L of psd matrix A = L L^T + */ + public Matrix cholesky() { + if(!isSquare()) throw new RuntimeException("Matrix is not square"); + if(!isSymmetric()) throw new RuntimeException("Matrix is not symmetric"); + int i, j, k; + Matrix L = create(n,n); + for(i=0; i2 + * 2x2 matrix + * @return true or false + */ + public boolean isR2(){ + return (m==2 && n==2); + } + + /** + * Vectors or Matrix in euclidean plane ℝ2 + * 2xn matrix + * @return true or false + */ + public boolean isM2(){ + return (m==2); + } + + /** + * Values in euclidean space ℝ3 + * 3x3 matrix + * @return true or false + */ + public boolean isR3(){ + return (m==3 && n==3); + } + + /** + * Check if size(A) == size(B) + * @throws IllegalDimensionException + **/ + private void checkDimensions(Matrix b) throws IllegalDimensionException { + if(b.m != m || b.n != n) + throw new IllegalDimensionException("Two matrices have to be the same dimension."); + } + + /** + * xij == xji? + * @return true or false + */ + public boolean isSymmetric(){ + int i, j; + for(i=0; iij == aji? + * @param A double array + * @return true or false + */ + public static boolean isSymmetric(double[][] A) { + int i, j; + int N = A.length; + for(i=0; ii⋅xjij. xi ⊥ xj , i ≠ j + * @return true or false + * @throws SingularException + * @throws NoSquareException + * @throws IllegalDimensionException + */ + public boolean isOrthogonal() throws IllegalDimensionException, NoSquareException, SingularException{ + return (inverse().equals(transpose())); + } + + /** + * xi⋅xjij + * @return true or false + * @throws IllegalDimensionException + */ + public boolean isOrthonormalized() throws IllegalDimensionException{ + int i, j; + double x; + for(i=0;iA is B? + * @param B matrix + * @return true or false + * @throws IllegalDimensionException + */ + public boolean equals(Matrix B) throws IllegalDimensionException{ + int i,j; + if (B.m != m || B.n != n) + throw new IllegalDimensionException("Illegal matrix dimensions."); + for(i=0; i=0?log:0)+1 + (Maths.min(mat)>=0.?0:1); // max/10+1 = Zehnerpotenz+1; 0/+1 = Vorzeichen + String[] zahlaufteilung; + for(i=0; i1 && !zahlaufteilung[1].equals("0") && Double.valueOf(zahlaufteilung[1]) > main) + main = zahlaufteilung[1].length(); // max. Nachstellen + } + if(main != 0) pre++; // false = +1 für Komma + post = main>3 ? 3 : main; // 4 = max Nachstellen in der Ausgabe; + } +// System.out.println(pre); + // begin with new line, so the first line will not translate + outputMatrix.append("\u250C"+WString.generateStringWithLength((pre+post+1)*n+1, ' ')+"\u2510\n"); + for(i=0; i= -Maths.ε) ? 0.0 : get(i,j)); + outputMatrix.append(String.format("%"+(pre+post)+"."+post+"f", get(i,j))); + outputMatrix.append(" "); + } + outputMatrix.append("\u2502\n"); + } + outputMatrix.append("\u2514"+WString.generateStringWithLength((pre+post+1)*n+1, ' ')+"\u2518"); + } else outputMatrix.append(mat); + StringBuffer output = outputMatrix; + if(getName() != null) { + i = 0; + StringBuffer outputBuffer = new StringBuffer(); + Scanner scanner = new Scanner(output.toString()); + String line; // = scanner.nextLine(); // cut off first row + while(scanner.hasNextLine()) { + line = scanner.nextLine(); + if(i==((int)(getM()/2)+1)) + outputBuffer.append(getName() + " = "); + else outputBuffer.append(WString.generateStringWithLength(getName().length(), ' ') + " "); + if(scanner.hasNextLine()) outputBuffer.append(line + "\n"); + else outputBuffer.append(line); + i++; + } + scanner.close(); + output = outputBuffer; + } + return output.toString(); + } + + public static String toString(int[][] array){ + return new Matrix(array).toString(); + } + + public static String toString(double[][] array){ + return new Matrix(array).toString(); + } + + public void println(){ + System.out.println(toString()); + } + + /** + * Print the matrix to the "standard" output stream. + * Line the elements up in columns. + */ + public void print(){ + int significantDigits = 4; + double[] minmax = minmax(); + int maxlog = (int) (Math.log10(minmax[1])); + int numerator = maxlog<0 ? maxlog - 1 : maxlog + 1; + int denominator = Maths.decimalPlaces(this); + int number = numerator+denominator; + int d = denominator; + if(denominator>0 && number>significantDigits) d = number - significantDigits; + int w = numerator + (minmax[0]<0?1:0) + d; // (+1 sign), +1 space + if(numerator<0) w = 2 + (minmax[0]<0?1:0) + d; // +2 : 0, +// System.out.println(numerator+" "+denominator+" "+w+" "+d); + print(new PrintWriter(System.out,true),w,d); + } + + /** + * Print the matrix to the "standard" output stream. + * Line the elements up in columns. + * @param w column width + * @param d number of digits after the decimal + */ + public void print(int w, int d){ + print(new PrintWriter(System.out,true),w,d); + } + + /** + * Print the matrix to the chosen output stream. + * Line the elements up in columns. + * @param output stream + * @param w column width + * @param d number of digits after the decimal + */ + public void print(PrintWriter output, int w, int d){ + DecimalFormat format = new DecimalFormat(); + format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.getDefault())); + format.setMinimumIntegerDigits(1); + format.setMaximumFractionDigits(d); + format.setMinimumFractionDigits(d); + format.setGroupingUsed(false); + print(output,format,w+2); + } + + /** + * Print the matrix to "standard" output stream. Line the elements up in columns. + * Use the format object, and right justify within columns of width characters. + * @param format a formatting object for individual elements + * @param width field width for each column + * @see java.text.DecimalFormat#setDecimalFormatSymbols + */ + public void print(NumberFormat format, int width){ + print(new PrintWriter(System.out,true),format,width); + } + + /** + * Print the matrix to the output stream. Line the elements up in columns. + * Use the format object, and right justify within columns of width characters. + * @param output the output stream + * @param format a formatting object to format the matrix elements + * @param width column width + * @see java.text.DecimalFormat#setDecimalFormatSymbols + */ + public void print(PrintWriter output, NumberFormat format, int width){ + int i, j, k, padding; + String s; + output.println(); // start on new line. + for(i=0; i vD = new java.util.Vector(); + + // Ignore initial empty lines + while(tokenizer.nextToken() == StreamTokenizer.TT_EOL); + if(tokenizer.ttype == StreamTokenizer.TT_EOF) + throw new IOException("Unexpected EOF on matrix read."); + do vD.addElement(Double.valueOf(tokenizer.sval)); // Read & store 1st row. + while(tokenizer.nextToken() == StreamTokenizer.TT_WORD); + + int n = vD.size(); // Now we've got the number of columns! + double row[] = new double[n]; + int j; + for(j=0; j v = new java.util.Vector(); + v.addElement(row); // Start storing rows instead of columns. + while (tokenizer.nextToken() == StreamTokenizer.TT_WORD){ + // While non-empty lines + v.addElement(row = new double[n]); + j = 0; + do { + if(j >= n) throw new IOException("Row " + v.size() + " is too long."); + row[j++] = Double.valueOf(tokenizer.sval).doubleValue(); + } while(tokenizer.nextToken() == StreamTokenizer.TT_WORD); + if(j < n) throw new IOException("Row " + v.size() + " is too short."); + } + int m = v.size(); // Now we've got the number of rows. + double[][] A = new double[m][]; + v.copyInto(A); // copy the rows out of the vector + return new Matrix(A); + } + + /** + * Demo + * @param args + */ + public static void main(String[] args){ + try { + Matrix.setSupressErrorMessage(true); + + Matrix A, B, C, D; + + A = Matrix.random(5, 5); + A.setName("A").println(); + + A.swap(1, 2); + System.out.println("A.swap(1, 2)"); + A.println(); + + B = A.transpose(); + System.out.println("A' = \n" + B.setName("B")); + + C = Matrix.identity(5); + System.out.println("identity(5) = \n"+C.setName("C")); + + System.out.println(A); + + // shouldn't be equal since AB != BA in general + System.out.println("A*B =? B*A : \n"+A.times(B).equals(B.times(A))); + System.out.println(A); + + Matrix f = Matrix.random(5, 1); + System.out.println("random(5, 1) = \n"+f.setName("f")); + + Matrix x = A.solve(f); + System.out.println("A^-1*f = \n"+x.setName("x")); + + Matrix2D a = new Matrix2D(0,1,1,0); + System.out.println(a.setName("a")); + System.out.println("rot90(a) = \n"+a.rotate90()); + Matrix b = Matrix.random(2, 1).times(5); + System.out.println("Matrix.random(2, 1).times(5) = \n"+b.setName("b")); + Matrix c = a.sumDirect(b); + System.out.println("c = a.sumDirect(b) = \n"+c); + System.out.println("m="+c.m+", n="+c.n); + Maths.print(c.get()); + Maths.print(c.getD()); + + D = new Matrix(new double[][]{{1,2,3,4},{5,6,7,8}}); + System.out.println("D = \n"+D); + System.out.println("D' = \n"+D.transpose()+" : "+(D.transpose().equals(new Matrix(new double[][]{{1,5},{2,6},{3,7},{4,8}})))); + System.out.println("D = \n"+D); + System.out.println("D'' = \n"+D.transpose().transpose()+" : "+(D.transpose().transpose().equals(D))); + + Matrix S = new Matrix(new double[][]{{3,1,2},{2,0,5},{1,2,3}}); + System.out.println("S = \n"+S); + System.out.println("det(S) = " + S.det(1) + " Rank " +S.rank()); + + Matrix T = new Matrix(new double[][]{{3,1,2},{2,0,5},{5,1,7}}); + System.out.println("det(T) = " + T.det(1) + " Rank " +T.rank()); + + Matrix U = new Matrix(new double[][]{{3,1},{2,0}}); + System.out.println("det(U) = " + U.det(1) + " Rank " +U.rank()); + + Matrix V = new Matrix(new double[][]{ + {1,-2,2,3,3}, + {4,3,1,-1,0}, + {5,-1,1,2,7}, + {-1,0,0,1,6}, + {1,10,3,4,3}}); + System.out.println("det(V) = " + V.det(1) + " Rank " +V.rank()); + + Matrix W = new Matrix(new double[][]{ + {1,-2,2,3,3,11}, + {4,3,1,-1,0,6}, + {5,-1,1,2,7,1}, + {-1,0,0,1,6,5}, + {1,10,3,4,3,10}, + {1,12,14,1,2,6}}); + System.out.println("det(W) = " + W.det(1) + " Rank " +W.rank()); + + Matrix W2 = new Matrix(new double[][]{ + {1,-2,2,3,3,11}, + {4,3,1,-1,0,6}, + {5,-1,1,2,7,1}, + {-1,0,0,1,6,5}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}}); + System.out.println("det(W2) = " + W2.det(1) + " Rank " +W2.rank()); + + Matrix W3 = new Matrix(new double[][]{ + {1,-2,2,3,3,11}, + {4,3,1,-1,0,6}, + {5,-1,1,2,7,1}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}}); + System.out.println("det(W3) = " + W3.det(1) + " Rank " +W3.rank()); + + Matrix W4 = new Matrix(new double[][]{ + {1,-2,2,3,3,11}, + {4,3,1,-1,0,6}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}}); + System.out.println("det(W4) = " + W4.det(1) + " Rank " +W4.rank()); + + Matrix W5 = new Matrix(new double[][]{ + {1,-2,2,3,3,11}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}}); + System.out.println("det(W5) = " + W5.det(1) + " Rank " +W5.rank()); + + Matrix W6 = new Matrix(new double[][]{ + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}, + {1,10,3,4,3,10}}); + System.out.println("det(W6) = " + W6.det(1) + " Rank " +W6.rank()); + try{ + System.out.println("inv(W6) = \n"+W6.inverse()); + } catch(Exception e){ + System.err.println("singulär"); + } + + Matrix E = new Matrix(new double[][]{ { 5 } }); + System.out.println(E.setName("E")); + System.out.println("det(E) = " + E.det(1) + " Rank " +E.rank()); + System.out.println("inv(E) = \n"+E.inverse()); + + Matrix E2 = new Matrix(new double[][]{ { 1, 2 }, { 3, 4 } }); + System.out.println(E2.setName("E2")); + System.out.println("det(E2) = " + E2.det(1) + " Rank " +E2.rank()); + System.out.println("inv(E2) = \n"+E2.inverse()); + + Matrix E3 = new Matrix(new double[][]{ { 1, 2, 3 }, { 4, 5, 6 }, { 9, 1, 3} }); + System.out.println(E3.setName("E3")); + System.out.println("det(E3) = " + E3.det(1) + " Rank " +E3.rank()); + System.out.println("inv(E3) = \n"+E3.inverse()); + System.out.println("sum(E3) = \n"+E3.sum()); + System.out.println(E3); + System.out.println("eigenvalue(E3) = \n"+E3.eigenvalues()); + + Matrix[] F = new Matrix[3]; + F[0] = new Matrix(1); + F[1] = new Matrix(2); + F[2] = new Matrix(3); + System.out.println(first(F)); + + T = new Matrix(new double[][]{{1,0,0},{0,1,0},{0,0,1}}); + System.out.println(T.setName("T")); + T = T.inverse(); + System.out.println(T.setName("T^-1")); + + B = new Matrix(new double[][]{ { 2, -1 }, { -1, 1 } }); + System.out.println(B.setName("B")); + Vector lambda = B.eigenvaluesRe(); + System.out.println("Eigenvalues(B) = \n"+lambda); + Matrix X = B.eigenvectors(); + System.out.println("Eigenvectors(B) = \n"+X); +// Matrix Lambda = new Matrix(2,2).set(0, 0, lambda.get(0)).set(1, 1, lambda.get(0)); +// C = B.minus(Lambda); +// System.out.println("B-l1E = "+C); +// System.out.println("(B-l1E)^-1 = "+C.inverse()); +// Vector X1 = Vector.zeros(2).set(0,1); +// System.out.println("X1 = "+X1); +// System.out.println("Eigenvectors(B) = "+C.times(X1)); +// System.out.println("Eigenvectors(B) = "+C.inverse().times(X1)); +// System.out.println("Eigenvectors(B) = "+C.inverse().times(X1)); + + Matrix2D P = new Matrix2D(new double[][]{ { 1, 1 }, { 0, -1 } }); + System.out.println(P.setName("P")); + System.out.println("P' = \n"+P.transpose()+" : "+(P.transpose().equals(new Matrix(new double[][]{ { 1, 0 }, { 1, -1 } })))); + System.out.println("P^-1 = \n" + P.inverse()); + System.out.println("P'P = \n"+P.transpose().times(P)); + System.out.println("rot(P'P,45°) = \n" + ((Matrix2D) P.transpose().times(P)).rotate45()); + + P = new Matrix2D(new double[][]{ { 1 }, { 1 } }); + System.out.println(P.setName("P")); + System.out.println("rot(P,45°) = \n" + P.rotate(45)); + + Vector2D v = new Vector2D(1,1); + Vector2D w = new Vector2D(0,1); + P = (Matrix2D) Matrix2D.mirror(v); + System.out.println("Pw = "); + P.times(w).println(); + + A = new Matrix2D(new double[][]{ { 2, 1 }, { 0, 1 } }); + System.out.println(A.setName("A")); + B = A.transpose().times(A); + System.out.println("A'A = \n" + B); + X = B.eigenvectors(); + System.out.println("X = \n" + X); + System.out.println("X'A'A = \n" + X.transpose().times(B)); + Matrix L2 = X.transpose().times(B).times(X); + System.out.println("L^2 = X'A'AX = \n" + L2); + // TODO: Wurzeln für Diagonalmatrix hinzufügen + Matrix L = L2.times(new Matrix(new double[][]{ { 1/Math.sqrt(L2.get(0, 0)), 0 }, { 0, 1/Math.sqrt(L2.get(1, 1)) } })); + System.out.println("L = \n" + L); + S = X.times(L).times(X); + System.out.println("S = XLX' = \n" + S); + Matrix2D Q = (Matrix2D) A.times(S.inverse()); + System.out.println("Q = AS^-1 = \n" + Q); + Q.plot(); + + A = new Matrix(new double[][]{ { 3, 2, 6 }, { 2, 2, 5 }, { -2, -1, -4} }); + System.out.println(A.setName("A")); + System.out.println("eigenvalue(A) = \n"+A.eigenvaluesRe()); + + A = new Matrix(new double[][]{ + { 38, -43./7, -63./2, -1149./14 }, + { 14, -19./7, -7, -181./7 }, + { 8./7, 122./49, -24./7, -177./49 }, + { 16, -26./7, -13, -244./7 } }); + System.out.println(A.setName("A")); + System.out.println("eigenvalue(A) = \n"+A.eigenvalues()); + + A = new Matrix(new double[][]{ + { 7, -3, -11, 2 }, + { -7, -5, -11, 5 }, + { -11, 0, -2, -15 }, + { -14, 15, -5, 7 } }); + System.out.println(A.setName("A")); + System.out.println("eigenvalue(A) = \n"+A.eigenvaluesIm()); + + System.out.println("power of:"); + A = new Matrix(new double[][]{ { 0, 0, 0 }, { 0, 1, 0 }, {0, 0, 3 } }); + System.out.println(A.setName("A")); + System.out.println("A^2 = \n"+A.pow(2)); +// A = new Matrix(new double[][]{ { 2, 2, 0 }, { 0, 1, 0 }, {0, 0, 3 } }); +// System.out.println(A.setName("A")); +// System.out.println("A^1 = "+A.pow(1)); + + System.out.println("\nKronecker product:"); + A = new Matrix(new double[][]{ { 1, 2 }, { 3, 4 } }); + System.out.println(A.setName("A")); + B = new Matrix(new double[][]{ { 0, 5 }, { 6, 7 } }); + System.out.println(B.setName("B")); + C = A.kroneckerProduct(B); + System.out.println("A \u24E7 B = \n"+C); + D = new Matrix(new double[][]{ { 0, 5, 0, 10 }, { 6, 7, 12, 14 }, { 0, 15, 0, 20 }, { 18, 21, 24, 28 } }); + if(C.equals(D)) System.out.println("test successful"); + + A.times(0.00001).print(); + A.times(0.001).print(); + A.times(10).print(); + A.times(25).print(); + A.times(250000).print(); + + System.out.println(A); + Maths.print(new Matrix(A).get()); + System.out.println(new Matrix(A.get())); + System.out.println(new Matrix(A.n, A.get())); + System.out.println(new Matrix(A.get(), A.m)); + + D = new Diagonal(2.,3); + System.out.println(A); + System.out.println(D); + System.out.println(A.plus(D)); + + Matrix I = Matrix.identity(2); + System.out.println(I); + System.out.println(I instanceof Diagonal); + I = I.toDiagonal(); + System.out.println(I instanceof Diagonal); + + Diagonal diag = new Diagonal(2.,3); + System.out.println(diag); + System.out.println(A.plus(diag)); + + boolean speedtest = false; + if(speedtest){ + A = Matrix.random(1000,500); + B = Matrix.random(500,1000); + System.out.println("C = A B"); + long startTime, endTime, duration; + // V1 + System.out.println("V1"); + { + startTime = System.nanoTime(); + C = A.times(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.times(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.times(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.times(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.times(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + + // V2 + System.out.println("V2"); + { + startTime = System.nanoTime(); + C = A.timesV2(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.timesV2(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.timesV2(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.timesV2(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + { + startTime = System.nanoTime(); + C = A.timesV2(B); + endTime = System.nanoTime(); + duration = (endTime - startTime)/1000000; + System.out.println("That took " + duration + " milliseconds"); + } + } + + A = new Matrix(new double[][]{ { 4, 1, 1 }, + { 1, 5, 3 }, + { 1, 3, 15 } }); + L = A.cholesky(); + L.println(); + /* + * 2.00000 0.00000 0.00000 + * 0.50000 2.17945 0.00000 + * 0.50000 1.26179 3.62738 + */ + + + } catch (Exception e) { + e.printStackTrace(); + } + + } +}