/** * Sets the matrices to operate upon. */ public virtual void SetParameters(DoubleMatrix2D A, DoubleMatrix2D B) { this.A = A; this.B = B; this.C = A.Copy(); this.D = B.Copy(); }
/// <summary> /// Solves <i>A*X = B</i>; returns <i>X</i>. /// </summary> /// <param name="B">A Matrix with as many rows as <i>A</i> and any number of columns.</param> /// <returns><i>X</i> so that <i>L*L'*X = B</i>.</returns> /// <exception cref="ArgumentException">if <i>B.Rows != A.Rows</i>.</exception> /// <exception cref="ArgumentException">if <i>!isSymmetricPositiveDefinite()</i>.</exception> public DoubleMatrix2D Solve(DoubleMatrix2D B) { // Copy right hand side. DoubleMatrix2D X = B.Copy(); int nx = B.Columns; // fix by MG Ferreira <*****@*****.**> // old code is in method xxxSolveBuggy() for (int c = 0; c < nx; c++) { // Solve L*Y = B; for (int i = 0; i < n; i++) { double sum = B[i, c]; for (int k = i - 1; k >= 0; k--) { sum -= mL[i, k] * X[k, c]; } X[i, c] = sum / mL[i, i]; } // Solve L'*X = Y; for (int i = n - 1; i >= 0; i--) { double sum = X[i, c]; for (int k = i + 1; k < n; k++) { sum -= mL[k, i] * X[k, c]; } X[i, c] = sum / mL[i, i]; } } return(X); }
/// <summary> /// 9 point stencil operation. /// Applies a function to a moving <i>3 x 3</i> window. /// </summary> /// <param name="A"> /// the matrix to operate on. /// </param> /// <param name="function"> /// the function to be applied to each window. /// </param> /// <param name="maxIterations"> /// the maximum number of times the stencil shall be applied to the matrixd /// Should be a multiple of 2 because two iterations are always done in one atomic step. /// </param> /// <param name="hasConverged"> /// Convergence condition; will return before maxIterations are done when <i>hasConverged.apply(A)==true</i>. /// Set this parameter to <i>null</i> to indicate that no convergence checks shall be made. /// </param> /// <param name="convergenceIterations"> /// the number of iterations to pass between each convergence check. /// (Since a convergence may be expensive, you may want to do it only every 2,4 or 8 iterationsd) /// </param> /// <returns><the number of iterations actually executedd /returns> public static int Stencil9(DoubleMatrix2D A, Cern.Colt.Function.Double9Function function, int maxIterations, DoubleMatrix2DProcedure hasConverged, int convergenceIterations) { DoubleMatrix2D B = A.Copy(); if (convergenceIterations <= 1) { convergenceIterations = 2; } if (convergenceIterations % 2 != 0) { convergenceIterations++; // odd -> make it even } int i = 0; while (i < maxIterations) { // do two steps at a time for efficiency A.ZAssign8Neighbors(B, function); B.ZAssign8Neighbors(A, function); i = i + 2; if (i % convergenceIterations == 0 && hasConverged != null) { if (hasConverged(A)) { return(i); } } } return(i); }
/// <summary> /// Linear algebraic matrix power; <i>B = A<sup>k</sup> <==> B = A*A*...*A</i>. /// </summary> /// <param name="A">the source matrix; must be square.</param> /// <param name="k">the exponent, can be any number.</param> /// <returns>a new result matrix.</returns> /// <exception cref="ArgumentException">if <i>!Testing.isSquare(A)</i>.</exception> private static DoubleMatrix2D XPowSlow(DoubleMatrix2D A, int k) { //cern.colt.Timer timer = new cern.colt.Timer().start(); DoubleMatrix2D result = A.Copy(); for (int i = 0; i < k - 1; i++) { result = Mult(result, A); } //timer.stop().Display(); return(result); }
/// <summary> /// Least squares solution of <i>A*X = B</i>; <i>returns X</i>. /// </summary> /// <param name="B">A matrix with as many rows as <i>A</i> and any number of columns.</param> /// <returns><i>X</i> that minimizes the two norm of <i>Q*R*X - B</i>.</returns> /// <exception cref="ArgumentException">if <i>B.Rows != A.Rows</i>.</exception> /// <exception cref="ArgumentException">if <i>!this.hasFullRank()</i> (<i>A</i> is rank deficient).</exception> public DoubleMatrix2D Solve(DoubleMatrix2D B) { Functions F = Functions.functions; if (B.Rows != m) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatrixRowDimensionsMustAgree); } if (!this.HasFullRank) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatrixIsRankDeficient); } // Copy right hand side int nx = B.Columns; DoubleMatrix2D X = B.Copy(); // Compute Y = transpose(Q)*B for (int k = 0; k < n; k++) { for (int j = 0; j < nx; j++) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i, k] * X[i, j]; } s = -s / QR[k, k]; for (int i = k; i < m; i++) { X[i, j] = X[i, j] + s * QR[i, k]; } } } // Solve R*X = Y; for (int k = n - 1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X[k, j] = X[k, j] / Rdiag[k]; } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X[i, j] = X[i, j] - X[k, j] * QR[i, k]; } } } return(X.ViewPart(0, 0, n, nx)); }
public static DoubleMatrix2D Inverse(DoubleMatrix2D A) { if (A.IsSquare && A.IsDiagonal) { DoubleMatrix2D inv = A.Copy(); Boolean isNonSingular = Diagonal.Inverse(inv); if (!isNonSingular) { throw new ArgumentException("A is singular."); } return(inv); } return(Solve(A, DoubleFactory2D.Dense.Identity(A.Rows))); }
public static DoubleMatrix2D Inverse(DoubleMatrix2D A) { if (A.IsSquare && A.IsDiagonal) { DoubleMatrix2D inv = A.Copy(); Boolean IsNonSingular = Diagonal.Inverse(inv); if (!IsNonSingular) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatrixIsSingular); } return(inv); } return(Solve(A, DoubleFactory2D.Dense.Identity(A.Rows))); }
/// <summary> /// Solves <i>A*X = B</i>; returns <i>X</i>. /// </summary> /// <param name="B">A Matrix with as many rows as <i>A</i> and any number of columns.</param> /// <returns><i>X</i> so that <i>L*L'*X = B</i>.</returns> /// <exception cref="ArgumentException">if <i>B.Rows != A.Rows</i>.</exception> /// <exception cref="ArgumentException">if <i>!isSymmetricPositiveDefinite()</i>.</exception> private DoubleMatrix2D XXXsolveBuggy(DoubleMatrix2D B) { var F = Cern.Jet.Math.Functions.functions; if (B.Rows != n) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatrixRowDimensionsMustAgree); } if (!isSymmetricPositiveDefinite) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatrixIsNotSymmetricPositiveDefinite); } // Copy right hand side. DoubleMatrix2D X = B.Copy(); int nx = B.Columns; // precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] Xrows = new DoubleMatrix1D[n]; for (int k = 0; k < n; k++) { Xrows[k] = X.ViewRow(k); } // Solve L*Y = B; for (int k = 0; k < n; k++) { for (int i = k + 1; i < n; i++) { // X[i,j] -= X[k,j]*L[i,k] Xrows[i].Assign(Xrows[k], F2.MinusMult(mL[i, k])); } Xrows[k].Assign(F1.Div(mL[k, k])); } // Solve L'*X = Y; for (int k = n - 1; k >= 0; k--) { Xrows[k].Assign(F1.Div(mL[k, k])); for (int i = 0; i < k; i++) { // X[i,j] -= X[k,j]*L[k,i] Xrows[i].Assign(Xrows[k], F2.MinusMult(mL[k, i])); } } return(X); }
/// <summary> /// Constructs and returns a new QR decomposition object; computed by Householder reflections; /// The decomposed matrices can be retrieved via instance methods of the returned decomposition object. /// Return a decomposition object to access <i>R</i> and the Householder vectors <i>H</i>, and to compute <i>Q</i>. /// </summary> /// <param name="A">A rectangular matrix.</param> /// <exception cref="ArgumentException">if <i>A.Rows < A.Columns</i>.</exception> public QRDecomposition(DoubleMatrix2D A) { Property.DEFAULT.CheckRectangular(A); Functions F = Functions.functions; // Initialize. QR = A.Copy(); m = A.Rows; n = A.Columns; Rdiag = A.Like1D(n); //Rdiag = new double[n]; DoubleDoubleFunction hypot = Algebra.HypotFunction(); // precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] QRcolumns = new DoubleMatrix1D[n]; DoubleMatrix1D[] QRcolumnsPart = new DoubleMatrix1D[n]; for (int k = 0; k < n; k++) { QRcolumns[k] = QR.ViewColumn(k); QRcolumnsPart[k] = QR.ViewColumn(k).ViewPart(k, m - k); } // Main loop. for (int k = 0; k < n; k++) { //DoubleMatrix1D QRcolk = QR.ViewColumn(k).ViewPart(k,m-k); // Compute 2-norm of k-th column without under/overflow. double nrm = 0; //if (k<m) nrm = QRcolumnsPart[k].aggregate(hypot,F.identity); for (int i = k; i < m; i++) { // fixes bug reported by [email protected] nrm = Algebra.Hypot(nrm, QR[i, k]); } if (nrm != 0.0) { // Form k-th Householder vector. if (QR[k, k] < 0) { nrm = -nrm; } QRcolumnsPart[k].Assign(F2.Div(nrm)); /* * for (int i = k; i < m; i++) { * QR[i][k] /= nrm; * } */ QR[k, k] = QR[k, k] + 1; // Apply transformation to remaining columns. for (int j = k + 1; j < n; j++) { DoubleMatrix1D QRcolj = QR.ViewColumn(j).ViewPart(k, m - k); double s = QRcolumnsPart[k].ZDotProduct(QRcolj); /* * // fixes bug reported by John Chambers * DoubleMatrix1D QRcolj = QR.ViewColumn(j).ViewPart(k,m-k); * double s = QRcolumnsPart[k].ZDotProduct(QRcolumns[j]); * double s = 0.0; * for (int i = k; i < m; i++) { * s += QR[i][k]*QR[i][j]; * } */ s = -s / QR[k, k]; //QRcolumnsPart[j].Assign(QRcolumns[k], F.PlusMult(s)); for (int i = k; i < m; i++) { QR[i, j] = QR[i, j] + s * QR[i, k]; } } } Rdiag[k] = -nrm; } }
/// <summary> /// Constructs and returns a new LU Decomposition object; /// The decomposed matrices can be retrieved via instance methods of the returned decomposition object. /// Return structure to access L, U and piv. /// </summary> /// <param name="A">Rectangular matrix</param> public LUDecomposition(DoubleMatrix2D A) { quick = new LUDecompositionQuick(0); // zero tolerance for compatibility with Jama quick.Decompose(A.Copy()); }
/// <summary> /// Solves <i>A*X = B</i>. /// </summary> /// <param name="B">A matrix with as many rows as <i>A</i> and any number of columns.</param> /// <returns><i>X</i> so that <i>L*U*X = B(piv,:)</i>.</returns> /// <exception cref="ArgumentException">if B.rows() != A.rows().</exception> /// <exception cref="ArgumentException">if A is singular, that is, if !this.isNonsingular().</exception> /// <exception cref="ArgumentException">if A.rows() < A.columns().</exception> public DoubleMatrix2D Solve(DoubleMatrix2D B) { DoubleMatrix2D X = B.Copy(); quick.Solve(X); return X; }
/// <summary> /// Linear algebraic matrix power; <i>B = A<sup>k</sup> <==> B = A*A*...*A</i>. /// <ul> /// <li><i>p >= 1: B = A*A*...*A</i>.</li> /// <li><i>p == 0: B = identity matrix</i>.</li> /// <li><i>p < 0: B = pow(inverse(A),-p)</i>.</li> /// </ul> /// Implementation: Based on logarithms of 2, memory usage minimized. /// </summary> /// <param name="A">the source matrix; must be square; stays unaffected by this operation.</param> /// <param name="p">the exponent, can be any number.</param> /// <returns><i>B</i>, a newly constructed result matrix; storage-independent of <i>A</i>.</returns> ///<exception cref="ArgumentException">if <i>!property().isSquare(A)</i>.</exception> public static DoubleMatrix2D Pow(DoubleMatrix2D A, int p) { // matrix multiplication based on log2 method: A*A*....*A is slow, ((A * A)^2)^2 * ..D is faster // allocates two auxiliary matrices as work space IBlas blas = SmpBlas.smpBlas; // for parallel matrix mult; if not initialized defaults to sequential blas Property.DEFAULT.CheckSquare(A); if (p < 0) { A = Inverse(A); p = -p; } if (p == 0) { return(DoubleFactory2D.Dense.Identity(A.Rows)); } DoubleMatrix2D T = A.Like(); // temporary if (p == 1) { return(T.Assign(A)); // safes one auxiliary matrix allocation } if (p == 2) { blas.Dgemm(false, false, 1, A, A, 0, T); // mult(A,A); // safes one auxiliary matrix allocation return(T); } int k = Cern.Colt.Bitvector.QuickBitVector.MostSignificantBit(p); // index of highest bit in state "true" /* * this is the naive version: * DoubleMatrix2D B = A.Copy(); * for (int i=0; i<p-1; i++) { * B = mult(B,A); * } * return B; */ // here comes the optimized version: //cern.colt.Timer timer = new cern.colt.Timer().start(); int i = 0; while (i <= k && (p & (1 << i)) == 0) { // while (bit i of p == false) // A = mult(A,A); would allocate a lot of temporary memory blas.Dgemm(false, false, 1, A, A, 0, T); // A.zMult(A,T); DoubleMatrix2D swap = A; A = T; T = swap; // swap A with T i++; } DoubleMatrix2D B = A.Copy(); i++; for (; i <= k; i++) { // A = mult(A,A); would allocate a lot of temporary memory blas.Dgemm(false, false, 1, A, A, 0, T); // A.zMult(A,T); DoubleMatrix2D swap = A; A = T; T = swap; // swap A with T if ((p & (1 << i)) != 0) { // if (bit i of p == true) // B = mult(B,A); would allocate a lot of temporary memory blas.Dgemm(false, false, 1, B, A, 0, T); // B.zMult(A,T); swap = B; B = T; T = swap; // swap B with T } } //timer.stop().Display(); return(B); }