public override IterativeStatistics Solve(ILinearTransformation matrix, IPreconditioner preconditioner, IVectorView rhs, IVector solution, bool initialGuessIsZero, Func <IVector> zeroVectorInitializer) { //TODO: find a better way to handle optimizations for the case x0=0, than using an initialGuessIsZero flag Preconditions.CheckMultiplicationDimensions(matrix.NumColumns, solution.Length); Preconditions.CheckSystemSolutionDimensions(matrix.NumRows, rhs.Length); this.Matrix = matrix; this.Preconditioner = preconditioner; this.Rhs = rhs; // Initial solution and rhs (r = b - A * x) this.solution = solution; if (ReorthoCache.Directions.Count > 0) { if (!initialGuessIsZero) { solution.Clear(); } CalculateInitialSolutionFromStoredDirections(rhs, solution); residual = ExactResidual.Calculate(matrix, rhs, solution); } else // preferably call base method { // r = b - A * x if (initialGuessIsZero) { residual = rhs.Copy(); } else { residual = ExactResidual.Calculate(matrix, rhs, solution); } } // Initialize vectors //TODO: Pehaps I can just clear them from previous iterations precondResidual = zeroVectorInitializer(); direction = zeroVectorInitializer(); matrixTimesDirection = zeroVectorInitializer(); int maxIterations = MaxIterationsProvider.GetMaxIterations(matrix.NumColumns); return(SolveInternal(maxIterations, zeroVectorInitializer)); }
/// <summary> /// Solves the linear system A * x = b by solving the preconditioned system inv(P) * A * inv(P)^T * y = inv(P) * b, /// where A = <paramref name="matrix"/>, b = <paramref name="rhsVector"/>, x is the solution, y = P^T * x, /// P*P^T = <paramref name="preconditioner"/>. /// Initially x = <paramref name="initialGuess"/> and then it converges to the solution. /// </summary> /// <param name="matrix"> /// Represents the matrix A of the linear system A * x = b, which must be symmetric positive definite. /// </param> /// <param name="rhs"> /// The right hand side vector b of the linear system A * x = b. Constraints: /// <paramref name="rhs"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumRows"/>. /// </param> /// <param name="preconditioner"> /// A preconditioner matrix that is also symmetric positive definite and has the same dimensions as A. /// </param> /// <param name="solution"> /// The vector from which to start refining the solution vector x. Constraints: /// <paramref name="solution"/>.<see cref="IIndexable1D.Length"/> /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumColumns"/>. /// </param> /// <param name="initialGuessIsZero"> /// If <paramref name="solution"/> is 0, then set <paramref name="initialGuessIsZero"/> to true to avoid performing the /// operation b-A*0 before starting. /// </param> /// <exception cref="NonMatchingDimensionsException"> /// Thrown if <paramref name="rhs"/> or <paramref name="solution"/> violate the described constraints. /// </exception> public virtual IterativeStatistics Solve(ILinearTransformation matrix, IPreconditioner preconditioner, IVectorView rhs, IVector solution, bool initialGuessIsZero, Func <IVector> zeroVectorInitializer) { //TODO: find a better way to handle optimizations for the case x0=0, than using an initialGuessIsZero flag Preconditions.CheckMultiplicationDimensions(matrix.NumColumns, solution.Length); Preconditions.CheckSystemSolutionDimensions(matrix.NumRows, rhs.Length); this.Matrix = matrix; this.Preconditioner = preconditioner; this.Rhs = rhs; this.solution = solution; // r = b - A * x if (initialGuessIsZero) { residual = rhs.Copy(); } else { residual = ExactResidual.Calculate(matrix, rhs, solution); } return(SolveInternal(MaxIterationsProvider.GetMaxIterations(matrix.NumColumns), zeroVectorInitializer)); }