// ------------------------ // Constructor // ------------------------ /// <summary> /// Cholesky algorithm for symmetric and positive definite matrix. /// </summary> /// <param name="Arg">Square, symmetric matrix.</param> public CholeskyDecomposition (Matrix Arg) { // Initialize. double[][] A = Arg.GetArray(); n = Arg.GetRowDimension(); L = new double[n][]; for (int i=0;i<n;i++) L[i] = new double[n]; isspd = (Arg.GetColumnDimension() == n); // Main loop. for (int j = 0; j < n; j++) { double[] Lrowj = L[j]; double d = 0.0; for (int k = 0; k < j; k++) { double[] Lrowk = L[k]; double s = 0.0; for (int i = 0; i < k; i++) { s += Lrowk[i]*Lrowj[i]; } Lrowj[k] = s = (A[j][k] - s)/L[k][k]; d = d + s*s; isspd = isspd & (A[k][j] == A[j][k]); } d = A[j][j] - d; isspd = isspd & (d > 0.0); L[j][j] = Math.Sqrt(Math.Max(d,0.0)); for (int k = j+1; k < n; k++) { L[j][k] = 0.0; } } }
/// <summary> /// X.powEquals() calculates the power of each element of the matrix. /// </summary> /// <param name="exp"></param> /// <returns>Matrix</returns> public Matrix Pow(double exp) { Matrix X = new Matrix(rowCount,columnCount); double[][] C = X.GetArray(); for (int i = 0; i < rowCount; i++) for (int j = 0; j < columnCount; j++) C[i][j] = Math.Pow(matrixData[i][j], exp); return X; }
/// <summary>Get matrixData submatrix.</summary> /// <param name="r">Array of row indices.</param> /// <param name="j0">Initial column index</param> /// <param name="j1">Final column index</param> /// <returns>matrixData(r(:),j0:j1)</returns> /// <exception cref="">IndexOutOfRangeException Submatrix indices</exception> public Matrix GetMatrix(int[] r, int j0, int j1) { Matrix X = new Matrix(r.Length,j1-j0+1); double[][] B = X.GetArray(); try { for (int i = 0; i < r.Length; i++) { for (int j = j0; j <= j1; j++) { B[i][j-j0] = matrixData[r[i]][j]; } } } catch(Exception) { throw new Exception("Submatrix indices"); } return X; }
/// <summary>Matrix transpose.</summary> /// <returns>matrixData'</returns> public Matrix Transpose() { var X = new Matrix(columnCount,rowCount); var C = X.GetArray(); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { C[j][i] = matrixData[i][j]; } } return X; }
// Return lower triangular factor // @return L public Matrix GetL () { Matrix X = new Matrix(m,n); double[][] L = X.GetArray(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i > j) { L[i][j] = LU[i][j]; } else if (i == j) { L[i][j] = 1.0; } else { L[i][j] = 0.0; } } } return X; }
/// <summary>Divide matrixData matrix by matrixData scalar, C = matrixData/s</summary> /// <param name="s">scalar</param> /// <returns>matrixData/s</returns> public Matrix Divide(double s) { if (s == 0) return this; Matrix X = new Matrix(rowCount,columnCount); double[][] C = X.GetArray(); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { C[i][j] = matrixData[i][j] / s; } } return X; }
/// <summary>Element-by-element multiplication, C = matrixData.*B</summary> /// <param name="B">another matrix</param> /// <returns>matrixData.*B</returns> public Matrix ArrayTimes(Matrix B) { CheckMatrixDimensions(B); Matrix X = new Matrix(rowCount,columnCount); double[][] C = X.GetArray(); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { C[i][j] = matrixData[i][j] * B.matrixData[i][j]; } } return X; }
/// <summary>Construct matrixData matrix from matrixData copy of matrixData 2-D array.</summary> /// <param name="matrixData">Two-dimensional array of doubles.</param> /// <exception cref="">ArgumentException All rows must have the same length</exception> public static Matrix ConstructWithCopy(double[][] matrixData) { int rows = matrixData.Length; int columns = matrixData[0].Length; Matrix X = new Matrix(rows,columns); double[][] C = X.GetArray(); for (int i = 0; i < rows; i++) { if (matrixData[i].Length != columns) { throw new ArgumentException ("All rows must have the same length."); } for (int j = 0; j < columns; j++) { C[i][j] = matrixData[i][j]; } } return X; }
// Return the Householder vectors // @return Lower trapezoidal matrix whose columns define the reflections public Matrix GetH () { Matrix X = new Matrix(m,n); double[][] H = X.GetArray(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i >= j) { H[i][j] = QR[i][j]; } else { H[i][j] = 0.0; } } } return X; }
// ------------------------ // Constructor // ------------------------ /// <summary> /// Check for symmetry, then construct the eigenvalue decomposition /// </summary> /// <param name="Arg">Square matrix</param> public EigenvalueDecomposition (Matrix Arg) { double[][] A = Arg.GetArray(); n = Arg.GetColumnDimension(); V = new double[n][]; for (int i=0;i<n;i++) V[i] = new double[n]; d = new double[n]; e = new double[n]; issymmetric = true; for (int j = 0; (j < n) & issymmetric; j++) { for (int i = 0; (i < n) & issymmetric; i++) { issymmetric = (A[i][j] == A[j][i]); } } if (issymmetric) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { V[i][j] = A[i][j]; } } // Tridiagonalize. Tred2(); // Diagonalize. Tql2(); } else { H = new double[n][]; for (int i=0;i<n;i++) H[i] = new double[n]; ort = new double[n]; for (int j = 0; j < n; j++) { for (int i = 0; i < n; i++) { H[i][j] = A[i][j]; } } // Reduce to Hessenberg form. Orthes(); // Reduce Hessenberg to real Schur form. Hqr2(); } }
/// <summary> /// Return the block diagonal eigenvalue matrix /// </summary> /// <returns>D</returns> public Matrix GetD () { Matrix X = new Matrix(n,n); double[][] D = X.GetArray(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { D[i][j] = 0.0; } D[i][i] = d[i]; if (e[i] > 0) { D[i][i+1] = e[i]; } else if (e[i] < 0) { D[i][i-1] = e[i]; } } return X; }
/// <summary>Multiply matrixData matrix by matrixData scalar, C = s*matrixData</summary> /// <param name="s">scalar</param> /// <returns>s*matrixData</returns> public Matrix Times(double s) { var X = new Matrix(rowCount,columnCount); var C = X.GetArray(); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { C[i][j] = s * matrixData[i][j]; } } return X; }
/// <summary>Element-by-element left division, C = matrixData.\B</summary> /// <param name="B">another matrix</param> /// <returns>matrixData.\B</returns> public Matrix ArrayLeftDivide(Matrix B) { CheckMatrixDimensions(B); var X = new Matrix(rowCount,columnCount); var C = X.GetArray(); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { C[i][j] = B.matrixData[i][j] / matrixData[i][j]; } } return X; }
/// <summary>Unary minus</summary> /// <returns>-matrixData</returns> public Matrix Uminus() { var X = new Matrix(rowCount,columnCount); var C = X.GetArray(); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { C[i][j] = -matrixData[i][j]; } } return X; }
/// <summary>Linear algebraic matrix multiplication, matrixData * B</summary> /// <param name="B">another matrix</param> /// <returns>Matrix product, matrixData * B</returns> /// <exception cref="">ArgumentException Matrix inner dimensions must agree.</exception> public Matrix Times(Matrix B) { if (B.rowCount != columnCount) { throw new ArgumentException("Matrix inner dimensions must agree."); } Matrix X = new Matrix(rowCount, B.columnCount); double[][] C = X.GetArray(); double[] Bcolj = new double[columnCount]; for (int j = 0; j < B.columnCount; j++) { for (int k = 0; k < columnCount; k++) { Bcolj[k] = B.matrixData[k][j]; } for (int i = 0; i < rowCount; i++) { double[] Arowi = matrixData[i]; double s = 0; for (int k = 0; k < columnCount; k++) { s += Arowi[k] * Bcolj[k]; } C[i][j] = s; } } return X; }
/// <summary>Linear algebraic matrix multiplication, matrixData * B /// B being matrixData triangular matrix /// <b>Note:</b> /// Actually the matrix should be matrixData <b>column oriented, upper triangular /// matrix</b> but use the <b>row oriented, lower triangular matrix</b> /// instead (transposed), because this is faster due to the easyer array /// access.</summary> /// <param name="B">another matrix</param> /// <returns>Matrix product, matrixData * B</returns> /// <exception cref="">ArgumentException Matrix inner dimensions must agree.</exception> public Matrix TimesTriangular(Matrix B) { if (B.rowCount != columnCount) throw new ArgumentException("Matrix inner dimensions must agree."); Matrix X = new Matrix(rowCount,B.columnCount); double[][] c = X.GetArray(); double[][] b; double s = 0; double[] Arowi; double[] Browj; b = B.GetArray(); ///multiply with each row of matrixData for (int i = 0; i < rowCount; i++) { Arowi = matrixData[i]; ///for all columns of B for (int j = 0; j < B.columnCount; j++) { s = 0; Browj = b[j]; ///since B being triangular, this loop uses k <= j for (int k = 0; k <= j; k++) { s += Arowi[k] * Browj[k]; } c[i][j] = s; } } return X; }
// Return the upper triangular factor // @return R public Matrix GetR () { Matrix X = new Matrix(n,n); double[][] R = X.GetArray(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i < j) { R[i][j] = QR[i][j]; } else if (i == j) { R[i][j] = Rdiag[i]; } else { R[i][j] = 0.0; } } } return X; }
/// <summary>Generate identity matrix</summary> /// <param name="rows">Number of rows.</param> /// <param name="columns">Number of colums.</param> /// <returns>An rows-by-columns matrix with ones on the diagonal and zeros elsewhere.</returns> public static Matrix Identity(int rows, int columns) { Matrix matrixData = new Matrix(rows,columns); double[][] X = matrixData.GetArray(); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { X[i][j] = (i == j ? 1.0 : 0.0); } } return matrixData; }
// Generate and return the (economy-sized) orthogonal factor // @return Q public Matrix GetQ () { Matrix X = new Matrix(m,n); double[][] Q = X.GetArray(); for (int k = n-1; k >= 0; k--) { for (int i = 0; i < m; i++) { Q[i][k] = 0.0; } Q[k][k] = 1.0; for (int j = k; j < n; j++) { if (QR[k][k] != 0) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i][k]*Q[i][j]; } s = -s/QR[k][k]; for (int i = k; i < m; i++) { Q[i][j] += s*QR[i][k]; } } } } return X; }
/// Make matrixData deep copy of matrixData matrix public Matrix Copy() { Matrix X = new Matrix(rowCount,columnCount); double[][] C = X.GetArray(); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { C[i][j] = matrixData[i][j]; } } return X; }
/// <summary>Get matrixData submatrix.</summary> /// <param name="i0">Initial row index</param> /// <param name="i1">Final row index</param> /// <param name="j0">Initial column index</param> /// <param name="j1">Final column index</param> /// <returns>matrixData(i0:i1,j0:j1)</returns> /// <exception cref="">IndexOutOfRangeException Submatrix indices</exception> public Matrix GetMatrix(int i0, int i1, int j0, int j1) { Matrix X = new Matrix(i1-i0+1,j1-j0+1); double[][] B = X.GetArray(); try { for (int i = i0; i <= i1; i++) { for (int j = j0; j <= j1; j++) { B[i-i0][j-j0] = matrixData[i][j]; } } } catch(Exception) { throw new Exception("Submatrix indices"); } return X; }
/// <summary>Get matrixData submatrix.</summary> /// <param name="r">Array of row indices.</param> /// <param name="c">Array of column indices.</param> /// <returns>matrixData(r(:),c(:))</returns> /// <exception cref="">IndexOutOfRangeException Submatrix indices</exception> public Matrix GetMatrix(int[] r, int[] c) { Matrix X = new Matrix(r.Length,c.Length); double[][] B = X.GetArray(); try { for (int i = 0; i < r.Length; i++) { for (int j = 0; j < c.Length; j++) { B[i][j] = matrixData[r[i]][c[j]]; } } } catch(Exception) { throw new Exception("Submatrix indices"); } return X; }
/// <summary>Get matrixData submatrix.</summary> /// <param name="i0">Initial row index</param> /// <param name="i1">Final row index</param> /// <param name="c">Array of column indices.</param> /// <returns>matrixData(i0:i1,c(:))</returns> /// <exception cref="">IndexOutOfRangeException Submatrix indices</exception> public Matrix GetMatrix(int i0, int i1, int[] c) { Matrix X = new Matrix(i1-i0+1,c.Length); double[][] B = X.GetArray(); try { for (int i = i0; i <= i1; i++) { for (int j = 0; j < c.Length; j++) { B[i-i0][j] = matrixData[i][c[j]]; } } } catch(Exception) { throw new Exception("Submatrix indices"); } return X; }
// Return upper triangular factor // @return U public Matrix GetU () { Matrix X = new Matrix(n,n); double[][] U = X.GetArray(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i <= j) { U[i][j] = LU[i][j]; } else { U[i][j] = 0.0; } } } return X; }
// Return the diagonal matrix of singular values // @return S public virtual Matrix GetS () { Matrix X = new Matrix(n,n); double[][] S = X.GetArray(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { S[i][j] = 0.0; } S[i][i] = this.s[i]; } return X; }