public bool HasConverged(int currentIteration, double currentObjectiveFunction, IVectorView nextDesignVariables) { bool result; if (currentIteration == 0) { result = false; } else { result = nextDesignVariables.Subtract(currentDesignVariables).MaxAbsolute() <= changeTolerance; } currentDesignVariables = nextDesignVariables.Copy(); //TODO: Perhaps this copy can be avoided return(result); }
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, where A = <paramref name="matrix"/> and b = <paramref name="rhs"/>. /// 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="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 IterativeStatistics Solve(ILinearTransformation matrix, IVectorView rhs, IVector solution, bool initialGuessIsZero) //TODO: find a better way to handle the case x0=0 { //TODO: these will also be checked by the matrix vector multiplication. Preconditions.CheckMultiplicationDimensions(matrix.NumColumns, solution.Length); Preconditions.CheckSystemSolutionDimensions(matrix.NumRows, rhs.Length); this.Matrix = matrix; 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))); }
/// <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)); }
public IterativeStatistics Solve(ILinearTransformation matrix, IPreconditioner preconditioner, IVectorView rhs, IVector solution, bool initialGuessIsZero, Func <IVector> zeroVectorInitializer) { Preconditions.CheckMultiplicationDimensions(matrix.NumColumns, solution.Length); Preconditions.CheckSystemSolutionDimensions(matrix.NumRows, rhs.Length); var innerIterations = innerIterationsProvider.GetMaxIterations(matrix.NumRows); IVector[] v = new Vector[innerIterations + 1]; var y = Vector.CreateZero(innerIterations + 1); var c = Vector.CreateZero(innerIterations + 1); var s = Vector.CreateZero(innerIterations + 1); var delta = 0.001; double residualNorm = double.MaxValue; var usedIterations = 0; if (initialGuessIsZero) { residual = rhs.Copy(); } else { residual = ExactResidual.Calculate(matrix, rhs, solution); } for (var iteration = 0; iteration < maximumIterations; iteration++) { preconditioner.SolveLinearSystem(residual, residual); //var residual = ExactResidual.Calculate(matrix, rhs, solution); residualNorm = residual.Norm2(); double residualTolerance; if (iteration == 0) { residualTolerance = residualNorm * relativeTolerance; } v[0] = residual.Scale(1 / residualNorm); var g = Vector.CreateZero(innerIterations + 1); g[0] = residualNorm; var hessenbergMatrix = Matrix.CreateZero(innerIterations + 1, innerIterations); var indexIteration = 0; for (int innerIteration = 0; innerIteration < innerIterations; innerIteration++) { indexIteration = innerIteration; v[innerIteration + 1] = Vector.CreateZero(v[innerIteration].Length); matrix.Multiply(v[innerIteration], v[innerIteration + 1]); preconditioner.SolveLinearSystem(v[innerIteration + 1], v[innerIteration + 1]); var av = v[innerIteration + 1].Norm2(); for (var j = 0; j <= innerIteration; j++) { hessenbergMatrix[j, innerIteration] = v[j].DotProduct(v[innerIteration + 1]); v[innerIteration + 1] = v[innerIteration + 1].Subtract(v[j].Scale(hessenbergMatrix[j, innerIteration])); } hessenbergMatrix[innerIteration + 1, innerIteration] = v[innerIteration + 1].Norm2(); if (Math.Abs(av + delta * hessenbergMatrix[innerIteration + 1, innerIteration] - av) < 10e-9) { for (int j = 0; j <= innerIteration; j++) { var htmp = v[j].DotProduct(v[innerIteration + 1]); hessenbergMatrix[j, innerIteration] += htmp; v[innerIteration + 1].LinearCombinationIntoThis(1.0, v[j], -htmp); } hessenbergMatrix[innerIteration + 1, innerIteration] = v[innerIteration + 1].Norm2(); } if (Math.Abs(hessenbergMatrix[innerIteration + 1, innerIteration]) > 10e-17) { v[innerIteration + 1].ScaleIntoThis(1 / hessenbergMatrix[innerIteration + 1, innerIteration]); } if (innerIteration > 0) { y = hessenbergMatrix.GetColumn(innerIteration).GetSubvector(0, innerIteration + 2); for (int i = 0; i <= innerIteration - 1; i++) { y = CalculateGivensRotation(c[i], s[i], i, y); } hessenbergMatrix.SetSubcolumn(innerIteration, y); } var mu = Math.Sqrt(hessenbergMatrix[innerIteration, innerIteration] * hessenbergMatrix[innerIteration, innerIteration] + hessenbergMatrix[innerIteration + 1, innerIteration] * hessenbergMatrix[innerIteration + 1, innerIteration]); c[innerIteration] = hessenbergMatrix[innerIteration, innerIteration] / mu; s[innerIteration] = -hessenbergMatrix[innerIteration + 1, innerIteration] / mu; hessenbergMatrix[innerIteration, innerIteration] = c[innerIteration] * hessenbergMatrix[innerIteration, innerIteration] - s[innerIteration] * hessenbergMatrix[innerIteration + 1, innerIteration]; hessenbergMatrix[innerIteration + 1, innerIteration] = 0.0; g = CalculateGivensRotation(c[innerIteration], s[innerIteration], innerIteration, g); residualNorm = Math.Abs(g[innerIteration + 1]); usedIterations++; if (residualNorm <= relativeTolerance && residualNorm <= absoluteTolerance) { break; } } indexIteration = indexIteration - 1; y[indexIteration + 1] = g[indexIteration + 1] / hessenbergMatrix[indexIteration + 1, indexIteration + 1]; for (int i = indexIteration; i >= 0; i--) { y[i] = (g[i] - (hessenbergMatrix.GetRow(i).GetSubvector(i + 1, indexIteration + 2) .DotProduct(y.GetSubvector(i + 1, indexIteration + 2)))) / hessenbergMatrix[i, i]; } for (int i = 0; i < matrix.NumRows; i++) { var subV = Vector.CreateZero(indexIteration + 2); for (int j = 0; j < indexIteration + 2; j++) { subV[j] = v[j][i]; } solution.Set(i, solution[i] + subV.DotProduct(y.GetSubvector(0, indexIteration + 2))); } if (residualNorm <= relativeTolerance && residualNorm <= absoluteTolerance) { break; } } return(new IterativeStatistics() { HasConverged = residualNorm <= relativeTolerance && residualNorm <= absoluteTolerance, AlgorithmName = name, NumIterationsRequired = usedIterations, ResidualNormRatioEstimation = residualNorm }); }