/// <summary> /// Creates a new householder decomposition. /// </summary> /// <param name="A">The matrix to decompose.</param> public HouseholderDecomposition(MatrixValue A) : base(A) { QR = A.GetComplexMatrix(); Rdiag = new ScalarValue[n]; // Main loop. for (int k = 0; k < n; k++) { var nrm = 0.0; for (int i = k; i < m; i++) { nrm = Helpers.Hypot(nrm, QR[i][k].Re); } if (nrm != 0.0) { // Form k-th Householder vector. if (QR[k][k].Re < 0) { nrm = -nrm; } for (int i = k; i < m; i++) { QR[i][k] /= nrm; } QR[k][k] += ScalarValue.One; // Apply transformation to remaining columns. for (int j = k + 1; j < n; j++) { var s = ScalarValue.Zero; for (int i = k; i < m; i++) { s += QR[i][k] * QR[i][j]; } s = (-s) / QR[k][k]; for (int i = k; i < m; i++) { QR[i][j] += s * QR[i][k]; } } } else { FullRank = false; } Rdiag[k] = new ScalarValue(-nrm); } }
/// <summary> /// Least squares solution of A * X = B /// </summary> /// <param name="b">A Matrix with as many rows as A and any number of columns.</param> /// <returns>X that minimizes the two norm of Q*R*X-B.</returns> public override MatrixValue Solve(MatrixValue b) { if (b.DimensionY != m) { throw new YAMPDifferentDimensionsException(m, 1, b.DimensionY, 1); } if (!this.FullRank) { throw new YAMPMatrixFormatException(SpecialMatrixFormat.NonSingular.ToString()); } // Copy right hand side var nx = b.DimensionX; var X = b.GetComplexMatrix(); // Compute Y = transpose(Q)*B for (var k = 0; k < n; k++) { for (var j = 0; j < nx; j++) { var s = ScalarValue.Zero; for (var i = k; i < m; i++) { s += QR[i][k] * X[i][j]; } s = (-s) / QR[k][k]; for (var i = k; i < m; i++) { X[i][j] += s * QR[i][k]; } } } // Solve R * X = Y; for (var k = n - 1; k >= 0; k--) { for (var j = 0; j < nx; j++) { X[k][j] /= Rdiag[k]; } for (var i = 0; i < k; i++) { for (var j = 0; j < nx; j++) { X[i][j] -= X[k][j] * QR[i][k]; } } } return(new MatrixValue(X, n, nx).GetSubMatrix(0, n, 0, nx)); }
/// <summary>Solve A*X = B</summary> /// <param name="B"> A Matrix with as many rows as A and any number of columns. /// </param> /// <returns> X so that L*L'*X = B /// </returns> /// <exception cref="System.ArgumentException"> Matrix row dimensions must agree. /// </exception> /// <exception cref="System.SystemException"> Matrix is not symmetric positive definite. /// </exception> public override MatrixValue Solve(MatrixValue B) { if (B.DimensionY != n) { throw new YAMPDifferentDimensionsException(n, 1, B.DimensionY, 1); } if (!isspd) { throw new YAMPMatrixFormatException(SpecialMatrixFormat.SymmetricPositiveDefinite); } // Copy right hand side. var X = B.GetComplexMatrix(); int nx = B.DimensionX; // Solve L*Y = B; for (int k = 0; k < n; k++) { for (int i = k + 1; i < n; i++) { for (int j = 0; j < nx; j++) { X[i][j] -= X[k][j] * L[i][k]; } } for (int j = 0; j < nx; j++) { X[k][j] /= L[k][k]; } } // Solve L'*X = Y; for (int k = n - 1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X[k][j] /= L[k][k]; } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X[i][j] -= X[k][j] * L[k][i]; } } } return(new MatrixValue(X, n, nx)); }
/// <summary> /// Cholesky algorithm for symmetric and positive definite matrix. /// </summary> /// <param name="Arg">Square, symmetric matrix.</param> /// <returns>Structure to access L and isspd flag.</returns> public CholeskyDecomposition(MatrixValue Arg) { // Initialize. var A = Arg.GetComplexMatrix(); n = Arg.DimensionY; L = new ScalarValue[n][]; for (int i = 0; i < n; i++) { L[i] = new ScalarValue[n]; } isspd = Arg.DimensionX == n; // Main loop. for (int i = 0; i < n; i++) { var Lrowi = L[i]; var d = ScalarValue.Zero; for (int j = 0; j < i; j++) { var Lrowj = L[j]; var s = new ScalarValue(); for (int k = 0; k < j; k++) { s += Lrowi[k] * Lrowj[k].Conjugate(); } s = (A[i][j] - s) / L[j][j]; Lrowi[j] = s; d += s * s.Conjugate(); isspd = isspd && (A[j][i] == A[i][j]); } d = A[i][i] - d; isspd = isspd & (d.Abs() > 0.0); L[i][i] = d.Sqrt(); for (int k = i + 1; k < n; k++) { L[i][k] = ScalarValue.Zero; } } }
/// <summary> /// Creates a new householder decomposition. /// </summary> /// <param name="A">The matrix to decompose.</param> public HouseholderDecomposition(MatrixValue A) : base(A) { QR = A.GetComplexMatrix(); Rdiag = new ScalarValue[n]; // Main loop. for (int k = 0; k < n; k++) { var nrm = 0.0; for (int i = k; i < m; i++) nrm = Helpers.Hypot(nrm, QR[i][k].Re); if (nrm != 0.0) { // Form k-th Householder vector. if (QR[k][k].Re < 0) nrm = -nrm; for (int i = k; i < m; i++) QR[i][k] /= nrm; QR[k][k] += ScalarValue.One; // Apply transformation to remaining columns. for (int j = k + 1; j < n; j++) { var s = ScalarValue.Zero; for (int i = k; i < m; i++) s += QR[i][k] * QR[i][j]; s = (-s) / QR[k][k]; for (int i = k; i < m; i++) QR[i][j] += s * QR[i][k]; } } else FullRank = false; Rdiag[k] = new ScalarValue(-nrm); } }
/// <summary> /// LU Decomposition /// </summary> /// <param name="A">Rectangular matrix</param> /// <returns>Structure to access L, U and piv.</returns> public LUDecomposition(MatrixValue A) { // Use a "left-looking", dot-product, Crout / Doolittle algorithm. LU = A.GetComplexMatrix(); m = A.DimensionY; n = A.DimensionX; piv = new int[m]; for (int i = 0; i < m; i++) { piv[i] = i; } pivsign = 1; var LUrowi = new ScalarValue[0]; var LUcolj = new ScalarValue[m]; // Outer loop. for (int j = 0; j < n; j++) { // Make a copy of the j-th column to localize references. for (int i = 0; i < m; i++) { LUcolj[i] = LU[i][j]; } // Apply previous transformations. for (int i = 0; i < m; i++) { LUrowi = LU[i]; // Most of the time is spent in the following dot product. var kmax = Math.Min(i, j); var s = ScalarValue.Zero; for (int k = 0; k < kmax; k++) { s += LUrowi[k] * LUcolj[k]; } LUrowi[j] = LUcolj[i] -= s; } // Find pivot and exchange if necessary. var p = j; for (int i = j + 1; i < m; i++) { if (LUcolj[i].Abs() > LUcolj[p].Abs()) { p = i; } } if (p != j) { for (int k = 0; k < n; k++) { var t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t; } var k2 = piv[p]; piv[p] = piv[j]; piv[j] = k2; pivsign = -pivsign; } // Compute multipliers. if (j < m & LU[j][j] != 0.0) { for (int i = j + 1; i < m; i++) { LU[i][j] = LU[i][j] / LU[j][j]; } } } }
/// <summary> /// LU Decomposition /// </summary> /// <param name="A">Rectangular matrix</param> /// <returns>Structure to access L, U and piv.</returns> public LUDecomposition(MatrixValue A) { // Use a "left-looking", dot-product, Crout / Doolittle algorithm. LU = A.GetComplexMatrix(); m = A.DimensionY; n = A.DimensionX; piv = new int[m]; for (int i = 0; i < m; i++) piv[i] = i; pivsign = 1; var LUrowi = new ScalarValue[0]; var LUcolj = new ScalarValue[m]; // Outer loop. for (int j = 0; j < n; j++) { // Make a copy of the j-th column to localize references. for (int i = 0; i < m; i++) LUcolj[i] = LU[i][j]; // Apply previous transformations. for (int i = 0; i < m; i++) { LUrowi = LU[i]; // Most of the time is spent in the following dot product. var kmax = Math.Min(i, j); var s = ScalarValue.Zero; for (int k = 0; k < kmax; k++) s += LUrowi[k] * LUcolj[k]; LUrowi[j] = LUcolj[i] -= s; } // Find pivot and exchange if necessary. var p = j; for (int i = j + 1; i < m; i++) { if (LUcolj[i].Abs() > LUcolj[p].Abs()) p = i; } if (p != j) { for (int k = 0; k < n; k++) { var t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t; } var k2 = piv[p]; piv[p] = piv[j]; piv[j] = k2; pivsign = -pivsign; } // Compute multipliers. if (j < m & LU[j][j] != 0.0) { for (int i = j + 1; i < m; i++) LU[i][j] = LU[i][j] / LU[j][j]; } } }
/// <summary> /// Least squares solution of A * X = B /// </summary> /// <param name="b">A Matrix with as many rows as A and any number of columns.</param> /// <returns>X that minimizes the two norm of Q*R*X-B.</returns> public override MatrixValue Solve(MatrixValue b) { if (b.DimensionY != m) throw new YAMPDifferentDimensionsException(m, 1, b.DimensionY, 1); if (!this.FullRank) throw new YAMPMatrixFormatException(SpecialMatrixFormat.NonSingular.ToString()); // Copy right hand side var nx = b.DimensionX; var X = b.GetComplexMatrix(); // Compute Y = transpose(Q)*B for (var k = 0; k < n; k++) { for (var j = 0; j < nx; j++) { var s = ScalarValue.Zero; for (var i = k; i < m; i++) { s += QR[i][k] * X[i][j]; } s = (-s) / QR[k][k]; for (var i = k; i < m; i++) { X[i][j] += s * QR[i][k]; } } } // Solve R * X = Y; for (var k = n - 1; k >= 0; k--) { for (var j = 0; j < nx; j++) { X[k][j] /= Rdiag[k]; } for (var i = 0; i < k; i++) { for (var j = 0; j < nx; j++) { X[i][j] -= X[k][j] * QR[i][k]; } } } return new MatrixValue(X, n, nx).GetSubMatrix(0, n, 0, nx); }