/// <summary> /// Solves a linear system Ax=b, where A is symmetric positive definite. /// </summary> /// <param name="input">Right hand side b.</param> /// <param name="result">Solution vector x.</param> public void Solve(double[] input, double[] result) { if (input == null) { throw new ArgumentNullException("input"); } if (result == null) { throw new ArgumentNullException("result"); } double[] x = new double[n]; Permutation.ApplyInverse(S.pinv, input, x, n); // x = P*b var lx = L.Values; var lp = L.ColumnPointers; var li = L.RowIndices; var d = this.D; int end; // Solve lower triangular system by forward elimination, x = L\x. for (int i = 0; i < n; i++) { end = lp[i + 1]; for (int p = lp[i]; p < end; p++) { x[li[p]] -= lx[p] * x[i]; } } // Solve diagonal system, x = D\x. for (int i = 0; i < n; i++) { x[i] /= d[i]; } // Solve upper triangular system by backward elimination, x = L'\x. for (int i = n - 1; i >= 0; i--) { end = lp[i + 1]; for (int p = lp[i]; p < end; p++) { x[i] -= lx[p] * x[li[p]]; } } Permutation.Apply(S.pinv, x, result, n); // b = P'*x }
/// <summary> /// Solves a system of linear equations, <c>A'x = b</c>. /// </summary> /// <param name="input">The right hand side vector, <c>b</c>.</param> /// <param name="result">The left hand side vector, <c>x</c>.</param> public void SolveTranspose(Complex[] input, Complex[] result) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } int m2 = S.m2; var x = new Complex[m2]; if (m >= n) { // x(q(0:m-1)) = b(0:m-1) Permutation.Apply(S.q, input, x, n); SolverHelper.SolveUpperTranspose(R, x); // x = R'\x // Apply Householder reflection to x. for (int k = n - 1; k >= 0; k--) { ApplyHouseholder(Q, k, beta[k], x); } // b(0:n-1) = x(p(0:n-1)) Permutation.Apply(S.pinv, x, result, m); } else { // x(0:m-1) = b(p(0:m-1) Permutation.ApplyInverse(S.pinv, input, x, n); // Apply Householder reflection to x. for (int k = 0; k < m; k++) { ApplyHouseholder(Q, k, beta[k], x); } SolverHelper.SolveUpper(R, x); // x = R\x // b(q(0:n-1)) = x(0:n-1) Permutation.ApplyInverse(S.q, x, result, m); } }
/// <summary> /// Solves a system of linear equations, <c>Ax = b</c>. /// </summary> /// <param name="input">The right hand side vector, <c>b</c>.</param> /// <param name="result">The left hand side vector, <c>x</c>.</param> /// <remarks> /// Let A be a m-by-n matrix. If m >= n a least-squares problem (min |Ax-b|) /// is solved. If m < n the underdetermined system is solved. /// </remarks> public override void Solve(double[] input, double[] result) { if (input == null) { throw new ArgumentNullException("input"); } if (result == null) { throw new ArgumentNullException("result"); } var x = new double[S.m2]; if (m >= n) { // x(0:m-1) = b(p(0:m-1) Permutation.ApplyInverse(S.pinv, input, x, m); // Apply Householder reflection to x. for (int k = 0; k < n; k++) { ApplyHouseholder(Q, k, beta[k], x); } SolverHelper.SolveUpper(R, x); // x = R\x // b(q(0:n-1)) = x(0:n-1) Permutation.ApplyInverse(S.q, x, result, n); } else { // x(q(0:m-1)) = b(0:m-1) Permutation.Apply(S.q, input, x, m); SolverHelper.SolveUpperTranspose(R, x); // x = R'\x // Apply Householder reflection to x. for (int k = m - 1; k >= 0; k--) { ApplyHouseholder(Q, k, beta[k], x); } // b(0:n-1) = x(p(0:n-1)) Permutation.Apply(S.pinv, x, result, n); } }
// TODO: implement SolveTranspose /// <summary> /// Solves a linear system Ax=b, where A is square and nonsingular. /// </summary> /// <param name="b">Right hand side, overwritten with solution</param> public void Solve(double[] b) { if (b == null) { throw new ArgumentNullException("b"); } var x = new double[n]; Permutation.ApplyInverse(pinv, b, x, n); // x = b(p) // LinearSolve lower triangular system by forward elimination, x = L\x. var lux = L.Values; var lup = L.ColumnPointers; var lui = L.RowIndices; for (int i = 0; i < n; i++) { x[i] /= lux[lup[i]]; for (int p = lup[i] + 1; p < lup[i + 1]; p++) { x[lui[p]] -= lux[p] * x[i]; } } // LinearSolve upper triangular system by backward elimination, x = U\x. lux = U.Values; lup = U.ColumnPointers; lui = U.RowIndices; for (int i = n - 1; i >= 0; i--) { x[i] /= lux[lup[i + 1] - 1]; for (int p = lup[i]; p < lup[i + 1] - 1; p++) { x[lui[p]] -= lux[p] * x[i]; } } Permutation.ApplyInverse(symFactor.q, x, b, n); // b(q) = x }
/// <summary> /// Solves a system of linear equations, <c>Ax = b</c>. /// </summary> /// <param name="input">The right hand side vector, <c>b</c>.</param> /// <param name="result">The left hand side vector, <c>x</c>.</param> public void Solve(Complex[] input, Complex[] result) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } var x = this.temp; Permutation.ApplyInverse(S.pinv, input, x, n); // x = P*b SolverHelper.SolveLower(L, x); // x = L\x SolverHelper.SolveLowerTranspose(L, x); // x = L'\x Permutation.Apply(S.pinv, x, result, n); // b = P'*x }
/// <summary> /// Solves a system of linear equations, <c>Ax = b</c>. /// </summary> /// <param name="input">The right hand side vector, <c>b</c>.</param> /// <param name="result">The left hand side vector, <c>x</c>.</param> public void Solve(Complex[] input, Complex[] result) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } var x = this.temp; Permutation.ApplyInverse(pinv, input, x, n); // x = b(p) SolverHelper.SolveLower(L, x); // x = L\x. SolverHelper.SolveUpper(U, x); // x = U\x. Permutation.ApplyInverse(S.q, x, result, n); // b(q) = x }
// TODO: implement SolveTranspose /// <summary> /// Solves a linear system Ax=b, where A is symmetric positive definite. /// </summary> /// <param name="b">Right hand side, overwritten with solution</param> public void Solve(double[] b) { if (b == null) { throw new ArgumentNullException("b"); } double[] x = new double[n]; Permutation.ApplyInverse(symFactor.pinv, b, x, n); // x = P*b var lx = L.Values; var lp = L.ColumnPointers; var li = L.RowIndices; // LinearSolve lower triangular system by forward elimination, x = L\x. for (int i = 0; i < n; i++) { x[i] /= lx[lp[i]]; for (int p = lp[i] + 1; p < lp[i + 1]; p++) { x[li[p]] -= lx[p] * x[i]; } } // LinearSolve upper triangular system by backward elimination, x = L'\x. for (int i = n - 1; i >= 0; i--) { for (int p = lp[i] + 1; p < lp[i + 1]; p++) { x[i] -= lx[p] * x[li[p]]; } x[i] /= lx[lp[i]]; } Permutation.Apply(symFactor.pinv, x, b, n); // b = P'*x }
// TODO: implement SolveTranspose /// <summary> /// LinearSolve a least-squares problem (min ||Ax-b||_2, where A is m-by-n /// with m >= n) or underdetermined system (Ax=b, where m < n) /// </summary> /// <param name="b">size max(m,n), b (size m) on input, x(size n) on output</param> /// <returns>true if successful, false on error</returns> public void Solve(double[] b) { if (b == null) { throw new ArgumentNullException("b"); } var x = new double[symFactor.m2]; var up = R.ColumnPointers; var ui = R.RowIndices; var ux = R.Values; if (m >= n) { // x(0:m-1) = b(p(0:m-1) Permutation.ApplyInverse(symFactor.pinv, b, x, m); // Apply Householder reflection to x. for (int k = 0; k < n; k++) { ApplyHouseholder(Q, k, beta[k], x); } // LinearSolve upper triangular system, x = R\x. for (int i = n - 1; i >= 0; i--) { x[i] /= ux[up[i + 1] - 1]; for (int p = up[i]; p < up[i + 1] - 1; p++) { x[ui[p]] -= ux[p] * x[i]; } } // b(q(0:n-1)) = x(0:n-1) Permutation.ApplyInverse(symFactor.q, x, b, n); } else { // x(q(0:m-1)) = b(0:m-1) Permutation.Apply(symFactor.q, b, x, m); // TODO: int n = R.ColumnCount; // LinearSolve lower triangular system, x = R'\x. for (int i = 0; i < n; i++) { for (int p = up[i]; p < up[i + 1] - 1; p++) { x[i] -= ux[p] * x[ui[p]]; } x[i] /= ux[up[i + 1] - 1]; } // Apply Householder reflection to x. for (int k = m - 1; k >= 0; k--) { ApplyHouseholder(Q, k, beta[k], x); } // b(0:n-1) = x(p(0:n-1)) Permutation.Apply(symFactor.pinv, x, b, n); } }