/// <summary> /// Given a positive-definite symmetric matrix <c>A[0..n][0..n]</c>, /// this routine constructs its Cholesky decomposition, <c> A = L*(L^T) </c>. /// </summary> /// <remarks> /// The operations count is <c>(N^3)/6</c> executions of the inner loop (consisting of /// one multiply and one subtract), with also N square roots. /// This is about a factor 2 better than LU decomposition of <c>A</c> /// (where its symmetry would be ignored). /// </remarks> /// <param name="matrix">Square Symmetric Definite-defined matrix A. /// </param> /// <exception cref="ArgumentNullException"><paramref name="matrix"/> is a null reference.</exception> /// <exception cref="ArgumentException"><paramref name="matrix"/> is a not Symmetric.</exception> /// <exception cref="ArgumentException"><paramref name="matrix"/> is a null Square.</exception> /// <returns> The Cholesky factor L is returned</returns> public void Decompose(Matrix matrix) { Guard.ArgumentNotNull(matrix, "a"); matrix.ValidateIsSymmetric(); var aRows = matrix.Rows; var res = new Matrix(aRows, aRows); for (var i = 0; i < aRows; i++) { int j; for (j = i; j < aRows; j++) { int k; double sum; for (sum = matrix[i, j], k = i - 1; k >= 0; k--) { sum -= res[i, k] * res[j, k]; } if (i == j) { if (sum <= 0) { throw new ArgumentException(isNotPositiveDefinite); } res[i, i] = Math.Sqrt(sum); } else { res[j, i] = sum / res[i, i]; } } } LeftFactorMatrix = res; }
public static double[] QuickSolveLinearEquation(Matrix a, double[] b) { #region Validation Guard.ArgumentNotNull(a, "a"); Guard.ArgumentNotNull(b, "b"); #endregion a.ValidateIsSymmetric(); var aRowCount = a.Rows; if (b.Length != aRowCount) { throw new ArgumentException(haveNonMatchingDimensions); } //L is a Cholesky Decomposition var decomposeMatrix = QuickDecompose(a); var x = new double[aRowCount]; int k; double sum; for (var i = 0; i < aRowCount; i++) { // Solve <c>L * y = b</c>, storing y in x. for (sum = b[i], k = i - 1; k >= 0; k--) { sum -= decomposeMatrix[i, k] * x[k]; } x[i] = sum / decomposeMatrix[i, i]; } for (var i = aRowCount - 1; i >= 0; i--) { // Solve L^T * x = y. for (sum = x[i], k = i + 1; k < aRowCount; k++) { sum -= decomposeMatrix[k, i] * x[k]; } x[i] = sum / decomposeMatrix[i, i]; } return x; }
public static Matrix QuickDecompose(Matrix a) { Guard.ArgumentNotNull(a, "a"); a.ValidateIsSymmetric(); var aRowCount = a.Rows; var res = new Matrix(aRowCount, aRowCount); for (var i = 0; i < aRowCount; i++) { int j; for (j = i; j < aRowCount; j++) { int k; double sum; for (sum = a[i, j], k = i - 1; k >= 0; k--) { sum -= res[i, k] * res[j, k]; } if (i == j) { if (sum <= 0) { throw new ArgumentException(isNotPositiveDefinite); } res[i, i] = Math.Sqrt(sum); } else { res[j, i] = sum / res[i, i]; } } } return res; }