/// <summary>
        /// Check the result.
        /// </summary>
        /// <param name="preconditioner">Specific preconditioner.</param>
        /// <param name="matrix">Source matrix.</param>
        /// <param name="vector">Initial vector.</param>
        /// <param name="result">Result vector.</param>
        protected override void CheckResult(IPreconditioner<float> preconditioner, SparseMatrix matrix, Vector<float> vector, Vector<float> result)
        {
            Assert.AreEqual(typeof (UnitPreconditioner<float>), preconditioner.GetType(), "#01");

            // Unit preconditioner is doing nothing. Vector and result should be equal
            for (var i = 0; i < vector.Count; i++)
            {
                Assert.IsTrue(vector[i] == result[i], "#02-" + i);
            }
        }
예제 #2
0
        /// <summary>
        /// Check the result.
        /// </summary>
        /// <param name="preconditioner">Specific preconditioner.</param>
        /// <param name="matrix">Source matrix.</param>
        /// <param name="vector">Initial vector.</param>
        /// <param name="result">Result vector.</param>
        protected override void CheckResult(IPreconditioner<double> preconditioner, SparseMatrix matrix, Vector<double> vector, Vector<double> result)
        {
            Assert.AreEqual(typeof (DiagonalPreconditioner), preconditioner.GetType(), "#01");

            // Compute M * result = product
            // compare vector and product. Should be equal
            var product = new DenseVector(result.Count);
            matrix.Multiply(result, product);
            for (var i = 0; i < product.Count; i++)
            {
                Assert.IsTrue(vector[i].AlmostEqualNumbersBetween(product[i], -Epsilon.Magnitude()), "#02-" + i);
            }
        }
예제 #3
0
        /// <summary>
        /// Check the result.
        /// </summary>
        /// <param name="preconditioner">Specific preconditioner.</param>
        /// <param name="matrix">Source matrix.</param>
        /// <param name="vector">Initial vector.</param>
        /// <param name="result">Result vector.</param>
        protected override void CheckResult(IPreconditioner<Complex32> preconditioner, SparseMatrix matrix, Vector<Complex32> vector, Vector<Complex32> result)
        {
            Assert.AreEqual(typeof(Diagonal), preconditioner.GetType(), "#01");

            // Compute M * result = product
            // compare vector and product. Should be equal
            var product = new DenseVector(result.Count);
            matrix.Multiply(result, product);
            for (var i = 0; i < product.Count; i++)
            {
                Assert.IsTrue(vector[i].Real.AlmostEqual(product[i].Real, -Epsilon.Magnitude()), "#02-" + i);
                Assert.IsTrue(vector[i].Imaginary.AlmostEqual(product[i].Imaginary, -Epsilon.Magnitude()), "#03-" + i);
            }
        }
예제 #4
0
        /// <summary>
        /// Solves the matrix equation AX = B, where A is the coefficient matrix (this matrix), B is the solution matrix and X is the unknown matrix.
        /// </summary>
        /// <param name="input">The solution matrix <c>B</c>.</param>
        /// <param name="solver">The iterative solver to use.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        /// <returns>The result matrix <c>X</c>.</returns>
        public Matrix <T> SolveIterative(Matrix <T> input, IIterativeSolver <T> solver, Iterator <T> iterator = null, IPreconditioner <T> preconditioner = null)
        {
            var result = Build.Dense(input.RowCount, input.ColumnCount);

            TrySolveIterative(input, result, solver, iterator, preconditioner);
            return(result);
        }
예제 #5
0
        /// <summary>
        /// Solves the matrix equation AX = B, where A is the coefficient matrix (this matrix), B is the solution matrix and X is the unknown matrix.
        /// </summary>
        /// <param name="input">The solution matrix <c>B</c>.</param>
        /// <param name="result">The result matrix <c>X</c></param>
        /// <param name="solver">The iterative solver to use.</param>
        /// <param name="stopCriteria">Criteria to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public IterationStatus TrySolveIterative(Matrix <T> input, Matrix <T> result, IIterativeSolver <T> solver, IPreconditioner <T> preconditioner, params IIterationStopCriterion <T>[] stopCriteria)
        {
            var iterator = new Iterator <T>(stopCriteria.Length == 0 ? Build.IterativeSolverStopCriteria() : stopCriteria);

            return(TrySolveIterative(input, result, solver, iterator, preconditioner));
        }
예제 #6
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            BCGStabParametrs ConGradParametrs = solverParametrs as BCGStabParametrs;
            if (ConGradParametrs == null)
            {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in BSGStab");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in BSGSTab");
            }
            else
            {
                int oIter = 0;
                double nPi, oPi, alpha, w, oNev, bNev, betta;
                oPi = alpha = w = 1;
                int size = rightPart.Size;
                Vector x, r, rTab, s, t, z, sqt, y;
                Vector v = new Vector(size);
                Vector p = new Vector(size);
                v.Nullify();
                p.Nullify();
                x = initialSolution;
                r = rightPart - matrix.SourceMatrix.Multiply(x);
                rTab = r;
                bNev = rightPart.Norm();
                oNev = r.Norm() / bNev;
                solverLogger.AddIterationInfo(oIter, oNev);//logger
                if (System.Double.IsInfinity(oNev))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by BSG Stab.");
                    return x;
                }

                if (System.Double.IsNaN(oNev))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by BSG Stab.");
                    return x;
                }
                while (oIter < ConGradParametrs.MaxIterations && oNev > ConGradParametrs.Epsilon)
                {
                    nPi = rTab * r;
                    betta = (nPi / oPi) * (alpha / w);
                    p = r + (p - v * w) * betta;
                    y= matrix.QSolve(matrix.SSolve(p));
                    v = matrix.SourceMatrix.Multiply(y);
                    alpha = nPi / (rTab * v);
                    x = x + y * alpha;//УТОЧНИТЬ!!!!!!!!!!!!!!!
                    s = r - v * alpha;
                    if (s.Norm() / bNev < ConGradParametrs.Epsilon) return x;
                    z = matrix.QSolve(matrix.SSolve(s));
                    t = matrix.SourceMatrix.Multiply(z);
                    sqt = matrix.QSolve(matrix.SSolve(t));
                    w = (z * sqt) / (sqt * sqt);
                    x = x + z * w;//УТОЧНИТЬ!!!!!!!!!!!!!!!!!!!
                    r = s - t * w;

                    oPi = nPi;
                    oIter++;
                    oNev = r.Norm() / bNev;

                    if (System.Double.IsInfinity(oNev))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by BSG Stab.");
                        return x;
                    }

                    if (System.Double.IsNaN(oNev))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by BSG Stab.");
                        return x;
                    }
                    solverLogger.AddIterationInfo(oIter, oNev);//logger
                }

                return x;
            }
        }
 /// <summary>
 /// Check the result.
 /// </summary>
 /// <param name="preconditioner">Specific preconditioner.</param>
 /// <param name="matrix">Source matrix.</param>
 /// <param name="vector">Initial vector.</param>
 /// <param name="result">Result vector.</param>
 protected abstract void CheckResult(IPreconditioner <double> preconditioner, SparseMatrix matrix, Vector <double> vector, Vector <double> result);
예제 #8
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                                     ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            if (solverParametrs is GaussSeidelParametrs)
            {
                GaussSeidelParametrs GZParametrs = solverParametrs as GaussSeidelParametrs;

                Vector x, xnext, r, di;
                int    size, k;
                double Residual, w;
                Vector DEx, DEb, Dx, Fx, Ex;

                size  = initialSolution.Size;
                x     = new Vector(size);
                xnext = new Vector(size);
                r     = new Vector(size);
                di    = new Vector(size);

                x  = initialSolution;
                w  = GZParametrs.Relaxation;
                di = matrix.SourceMatrix.Diagonal;

                Dx = Vector.Mult(di, x);
                Fx = matrix.SourceMatrix.LMult(x, false);
                Ex = matrix.SourceMatrix.UMult(x, false);
                r  = Dx + Fx + Ex - rightPart;
                var rpnorm = rightPart.Norm();
                Residual = r.Norm() / rpnorm;

                DEb = Vector.Division(rightPart, di);


                solverLogger.AddIterationInfo(0, Residual);
                for (k = 1; k <= GZParametrs.MaxIterations && Residual > GZParametrs.Epsilon; k++)
                {
                    DEx   = Vector.Division(Ex + Fx, di);
                    xnext = (DEb - DEx) * w + x * (1 - w);
                    Ex    = matrix.SourceMatrix.UMult(xnext, false);
                    Dx    = Vector.Mult(di, xnext);


                    DEx   = Vector.Division(Ex + Fx, di);
                    x     = xnext;
                    xnext = (DEb - DEx) * w + x * (1 - w);
                    Dx    = Vector.Mult(di, xnext);
                    Fx    = matrix.SourceMatrix.LMult(xnext, false);


                    r = Dx + Fx + Ex - rightPart;

                    Residual = r.Norm() / rpnorm;

                    if (System.Double.IsInfinity(Residual))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by GaussSeidel .");
                        return(xnext);
                    }

                    if (System.Double.IsNaN(Residual))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by GaussSeidel.");
                        return(xnext);
                    }

                    solverLogger.AddIterationInfo(k, Residual);
                }

                return(xnext);
            }
            else
            {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GaussSeidel");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GaussSeidel");
            }
        }
예제 #9
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            if (solverParametrs is LOSParametrs)
            {
                LOSParametrs LOSParametrs = solverParametrs as LOSParametrs;

                Vector x, r, z, p;
                double alpha, betta;
                int size, k;
                double Residual,pp,rightnorm;
                Vector Ax;
                Vector LAU, Ur;

                size = initialSolution.Size;
                x = new Vector(size);
                r = new Vector(size);
                z = new Vector(size);
                p = new Vector(size);
                Ax = new Vector(size);
                LAU = new Vector(size);
                Ur = new Vector(size);

                x = initialSolution;
                Ax = matrix.SourceMatrix.Multiply(x);
                r = matrix.SSolve(rightPart - Ax);
                z = matrix.QSolve(r);
                p = matrix.SSolve(matrix.SourceMatrix.Multiply(z));

                rightnorm = matrix.SSolve(rightPart).Norm();
                Residual = r.Norm()/rightnorm;

                solverLogger.AddIterationInfo(0, Residual);
                for (k = 1; k <= LOSParametrs.MaxIterations && Residual > LOSParametrs.Epsilon; k++)
                {
                    pp = p*p;

                    alpha = (p * r) / pp;
                    x = x + z * alpha;
                    r = r - p * alpha;

                    Ur = matrix.QSolve(r);
                    LAU = matrix.SourceMatrix.Multiply(Ur);
                    LAU = matrix.SSolve(LAU);

                    betta = - (p * LAU) / pp;
                    z = Ur + z * betta;
                    p = LAU + p * betta;

                    Residual = r.Norm() / rightnorm;

                    if (System.Double.IsInfinity(Residual))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by LOS.");
                        return x;
                    }

                    if (System.Double.IsNaN(Residual))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by LOS.");
                        return x;
                    }

                    solverLogger.AddIterationInfo(k, Residual);

                }

                return x;
            }
            else {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GaussSeidel");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GaussSeidel");

            }
        }
예제 #10
0
 private void InitializeSolver()
 {
     result = Vector<double>.Build.Dense(n * m);
       Control.LinearAlgebraProvider = new OpenBlasLinearAlgebraProvider();
     //Control.UseNativeMKL();
     //Control.LinearAlgebraProvider = new MklLinearAlgebraProvider();
     //Control.UseManaged();
     var iterationCountStopCriterion = new IterationCountStopCriterion<double>(1000);
     var residualStopCriterion = new ResidualStopCriterion<double>(1e-7);
     monitor = new Iterator<double>(iterationCountStopCriterion, residualStopCriterion);
     solver = new BiCgStab();
     preconditioner = new MILU0Preconditioner();
 }
예제 #11
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                                     ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            GMRESParameters GMRESParameters = solverParametrs as GMRESParameters;
            if (GMRESParameters != null)
            {
                Vector[] V, H;
                Vector residual, x, d, z, w, tmp;
                bool continueCalculations;
                double epsilon = GMRESParameters.Epsilon;
                int m = GMRESParameters.M;
                int maxIterations = GMRESParameters.MaxIterations;
                int n = rightPart.Size;

                x = initialSolution;
                residual = rightPart - matrix.SourceMatrix.Multiply(x);
                residual = matrix.SSolve(residual);
                double rightPartNorm = matrix.SSolve(rightPart).Norm();
                double residualNorm = residual.Norm();

                if (System.Double.IsInfinity(residualNorm / rightPartNorm))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES.");
                    return x;
                }

                if (System.Double.IsNaN(residualNorm / rightPartNorm))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES.");
                    return x;
                }

                x = matrix.QMultiply(initialSolution);

                V = new Vector[m];
                for (int i = 0; i < m; i++)
                    V[i] = new Vector(n);

                H = new Vector[m];
                for (int i = 0; i < m; i++)
                    H[i] = new Vector(m + 1);

                d = new Vector(m + 1);

                for (int k = 1; k <= maxIterations && residualNorm / rightPartNorm > epsilon; k++)
                {
                    d.Nullify();
                    V[0] = residual * (1.0 / residualNorm);

                    continueCalculations = true;
                    for (int j = 1; j <= m && continueCalculations; j++)
                    {
                        tmp = matrix.QSolve(V[j - 1]);
                        w = matrix.SSolve(matrix.SourceMatrix.Multiply(tmp));

                        for (int l = 1; l <= j; l++)
                        {
                            H[j - 1][l - 1] = V[l - 1] * w;
                            w = w - V[l - 1] * H[j - 1][l - 1];
                        }

                        H[j - 1][j] = w.Norm();
                        if (Math.Abs(H[j - 1][j]) < 1e-10)
                        {
                            m = j;
                            continueCalculations = false;
                        }
                        else
                        {
                            if(j != m)
                                V[j] = w * (1.0 / H[j - 1][j]);
                        }
                    }

                    d[0] = residualNorm;
                    z = solveMinSqrProblem(d, H, m);
                    x = x + multiplyMatrixVector(z, V);

                    tmp = rightPart - matrix.SourceMatrix.Multiply(matrix.QSolve(x));
                    residual = matrix.SSolve(tmp);
                    residualNorm = residual.Norm();

                    if (System.Double.IsInfinity(residualNorm / rightPartNorm))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES.");
                        return x;
                    }

                    if (System.Double.IsNaN(residualNorm / rightPartNorm))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES.");
                        return x;
                    }

                    solverLogger.AddIterationInfo(k, residualNorm / rightPartNorm);
                }

                return matrix.QSolve(x);
            }
            else {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GMRES");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GMRES");

            }
        }
예제 #12
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                                    ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            if (solverParametrs is GaussSeidelParametrs)
            {
                GaussSeidelParametrs GZParametrs = solverParametrs as GaussSeidelParametrs;

                Vector x,xnext, r, di;
                int size, k;
                double Residual, w;
                Vector DEx,DEb, Dx, Fx, Ex;

                size = initialSolution.Size;
                x = new Vector(size);
                xnext = new Vector(size);
                r = new Vector(size);
                di = new Vector(size);

                x = initialSolution;
                w = GZParametrs.Relaxation;
                di = matrix.SourceMatrix.Diagonal;

                Dx = Vector.Mult(di, x);
                Fx = matrix.SourceMatrix.LMult(x, false);
                Ex = matrix.SourceMatrix.UMult(x, false);
                r = Dx+Fx+ Ex - rightPart;
                var rpnorm = rightPart.Norm();
                Residual = r.Norm() / rpnorm;

                DEb = Vector.Division(rightPart,di);

                solverLogger.AddIterationInfo(0, Residual);
                for (k = 1; k <= GZParametrs.MaxIterations && Residual > GZParametrs.Epsilon; k++)
                {

                    DEx = Vector.Division(Ex+Fx,di);
                    xnext = (DEb - DEx) * w + x * (1 - w);
                    Ex = matrix.SourceMatrix.UMult(xnext, false);
                    Dx = Vector.Mult(di, xnext);

                    DEx = Vector.Division(Ex + Fx, di);
                    x = xnext;
                    xnext = (DEb - DEx) * w + x * (1 - w);
                    Dx = Vector.Mult(di, xnext);
                    Fx = matrix.SourceMatrix.LMult(xnext, false);

                    r = Dx + Fx + Ex - rightPart;

                    Residual = r.Norm() / rpnorm;

                    if (System.Double.IsInfinity(Residual))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by GaussSeidel .");
                        return xnext;
                    }

                    if (System.Double.IsNaN(Residual))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by GaussSeidel.");
                        return xnext;
                    }

                    solverLogger.AddIterationInfo(k, Residual);

                }

                return xnext;
            }
            else {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GaussSeidel");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GaussSeidel");

            }
        }
예제 #13
0
        /// <summary>
        /// Решение СЛАУ методом сопряженных градиентов
        /// </summary>
        /// <param name="A">Матрица СЛАУ</param>
        /// <param name="b">Ветор правой части</param>
        /// <param name="Initial">Ветор начального приближения</param>
        /// <param name="Precision">Точность</param>
        /// <param name="Maxiter">Максимальное число итераций</param>
        /// <returns>Вектор x - решение СЛАУ Ax=b с заданной точностью</returns>
        public IVector Solve(IPreconditioner Preconditioner, IMatrix A, IVector b, IVector Initial, double Precision, int Maxiter, ILogger Logger)
        {
            Logger.WriteNameSolution("MSG", Preconditioner.getName());
            string start = DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff");

            Logger.setMaxIter(Maxiter);
            IVector x = Preconditioner.MultU(Initial);

            double scalAzZ, scalRR, alpha, beta = 1.0;

            IVector r = b.Add(A.Mult(Initial), 1, -1);

            r = Preconditioner.T.SolveL(Preconditioner.SolveL(r));
            IVector Az, Atz, z = A.Transpose.Mult(r);

            z = Preconditioner.T.SolveU(z);

            r      = z.Clone() as IVector;
            scalRR = r.ScalarMult(r);
            double normR = Math.Sqrt(scalRR) / b.Norm;

            for (int iter = 0; iter < Maxiter && normR > Precision && beta > 0; iter++)
            {
                Az = Preconditioner.SolveU(z);

                Atz = A.Mult(Az);
                Atz = Preconditioner.T.SolveL(Preconditioner.SolveL(Atz));
                Az  = A.Transpose.Mult(Atz);
                Az  = Preconditioner.T.SolveU(Az);

                scalAzZ = Az.ScalarMult(z);

                if (scalAzZ == 0)
                {
                    Logger.WriteSolution(x, Maxiter, b.Add(A.Mult(x), -1, 1).Norm);
                    Logger.WriteTime(start, DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"));
                    throw new DivideByZeroException("Division by 0");
                }

                alpha = scalRR / scalAzZ;

                x.Add(z, 1, alpha, true);
                r.Add(Az, 1, -alpha, true);

                beta = scalRR;
                if (scalRR == 0)
                {
                    Logger.WriteSolution(x, Maxiter, b.Add(A.Mult(x), -1, 1).Norm);
                    Logger.WriteTime(start, DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"));
                    throw new DivideByZeroException("Division by 0");
                }
                scalRR = r.ScalarMult(r);
                beta   = scalRR / beta;

                z     = r.Add(z, 1, beta);
                normR = Math.Sqrt(scalRR) / b.Norm;
                Factory.Residual.Add(normR);
                Logger.WriteIteration(iter, normR);

                if (double.IsNaN(normR) || double.IsInfinity(normR))
                {
                    x = Preconditioner.SolveU(x);
                    Logger.WriteSolution(x, Maxiter, b.Add(A.Mult(x), -1, 1).Norm);
                    Logger.WriteTime(start, DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"));
                    throw new CantSolveException();
                }
            }
            ;
            x = Preconditioner.SolveU(x);
            Logger.WriteSolution(x, Maxiter, b.Add(A.Mult(x), -1, 1).Norm);
            Logger.WriteTime(start, DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"));
            return(x);
        }
예제 #14
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <double> matrix, Vector <double> input, Vector <double> result,
                          Iterator <double> iterator, IPreconditioner <double> preconditioner)
        {
            var A = (SparseMatrix)matrix;
            var M = preconditioner;

            var b = (DenseVector)input;
            var x = (DenseVector)result;

            double atolf  = 0.0;
            double rtol_1 = 0.0;
            int    recompute_residual_p = 0;

            var p = new DenseVector(b.Count);
            var s = new DenseVector(b.Count);
            var r = new DenseVector(b.Count);

            double alpha, beta;
            double gamma, gamma_old;
            double bi_prod;

            double sdotp;
            bool   recompute_true_residual = false;

            int i = 0;

            M.Initialize(A);

            // Start pcg solve

            // bi_prod = <C*b,b>
            //VectorHelper.Clear(p);
            M.Approximate(input, p);
            bi_prod = VectorHelper.DotProduct(p, b);

            if (bi_prod > 0.0)
            {
                if (atolf > 0)  // mixed relative and absolute tolerance
                {
                    bi_prod += atolf;
                }
            }
            else    // bi_prod==0.0: the rhs vector b is zero
            {
                // Set x equal to zero and return
                VectorHelper.Copy(b, x);
                return;
            }

            // r = b - Ax
            VectorHelper.Copy(b, r);
            A.Multiply(-1.0, result, 1.0, r);

            // p = C*r
            //VectorHelper.Clear(p);
            M.Approximate(r, p);

            // gamma = <r,p>
            gamma = VectorHelper.DotProduct(r, p);

            while (iterator.DetermineStatus(i, x, b, r) == IterationStatus.Continue)
            {
                // the core CG calculations...
                i++;

                // At user request, periodically recompute the residual from the formula
                // r = b - A x (instead of using the recursive definition). Note that this
                // is potentially expensive and can lead to degraded convergence (since it
                // essentially a "restarted CG").
                recompute_true_residual = (recompute_residual_p > 0) && !((i % recompute_residual_p) == 0);

                // s = A*p
                A.Multiply(1.0, p, 0.0, s);

                // alpha = gamma / <s,p>
                sdotp = VectorHelper.DotProduct(s, p);
                if (sdotp == 0.0)
                {
                    throw new NumericalBreakdownException();
                }
                alpha = gamma / sdotp;

                gamma_old = gamma;

                // x = x + alpha*p
                VectorHelper.Add(alpha, p, x, x);

                // r = r - alpha*s
                if (recompute_true_residual)
                {
                    //Recomputing the residual...
                    VectorHelper.Copy(b, r);
                    A.Multiply(-1.0, result, 1.0, r);
                }
                else
                {
                    VectorHelper.Add(-alpha, s, r, r);
                }

                // s = C*r
                VectorHelper.Clear(s);
                M.Approximate(r, s);

                // gamma = <r,s>
                gamma = VectorHelper.DotProduct(r, s);

                // residual-based stopping criteria: ||r_new-r_old||_C < rtol ||b||_C
                if (rtol_1 > 0)
                {
                    // use that ||r_new-r_old||_C^2 = (r_new ,C r_new) + (r_old, C r_old)
                    if ((gamma + gamma_old) / bi_prod < rtol_1 * rtol_1)
                    {
                        break;
                    }
                }

                // ... gamma should be >=0.  IEEE subnormal numbers are < 2**(-1022)=2.2e-308
                // (and >= 2**(-1074)=4.9e-324).  So a gamma this small means we're getting
                // dangerously close to subnormal or zero numbers (usually if gamma is small,
                // so will be other variables).  Thus further calculations risk a crash.
                // Such small gamma generally means no hope of progress anyway.
                if (Math.Abs(gamma) < TINY)
                {
                    throw new NumericalBreakdownException();
                }

                // beta = gamma / gamma_old
                beta = gamma / gamma_old;

                // p = s + beta p
                if (recompute_true_residual)
                {
                    VectorHelper.Copy(s, p);
                }
                else
                {
                    p.Scale(beta);
                    VectorHelper.Add(1.0, s, p, p);
                }
            }
        }
예제 #15
0
        /// <summary>
        /// Решение СЛАУ методом локально-оптимальной схемы
        /// </summary>
        /// <param name="preconditioner">Матрица СЛАУ</param>
        /// <param name="b">Ветор правой части</param>
        /// <param name="Initial">Ветор начального приближения</param>
        /// <param name="Precision">Точность</param>
        /// <param name="Maxiter">Максимальное число итераций</param>
        /// <returns>Вектор x - решение СЛАУ Ax=b с заданной точностью</returns>
        public IVector Solve(IPreconditioner preconditioner, IMatrix A, IVector b, IVector Initial, double Precision, int Maxiter, ILogger Logger)
        {
            Logger.WriteNameSolution("LOS", preconditioner.getName());
            string start = DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff");

            Logger.setMaxIter(Maxiter);
            IVector x = Initial.Clone() as IVector;

            double alpha = 0.0, beta = 0.0;

            IVector r = b.Add(A.Mult(Initial), 1, -1);    //r_0 = f - Ax_0

            r = preconditioner.SolveL(r);                 // r_0 = L^-1 * (f - Ax_0)

            IVector Ar, z = preconditioner.SolveU(r);     // z_0 = U^-1 * r_0
            IVector p = preconditioner.SolveL(A.Mult(z)); // p_0 = L^-1 * Az_0

            double p_r = 0.0, p_p = 0.0;

            double scalRR = r.ScalarMult(r);
            double normR  = Math.Sqrt(scalRR) / b.Norm;

            for (int iter = 0; iter < Maxiter && normR > Precision; iter++)
            //for (int iter = 0; iter < Maxiter && ; iter++)
            {
                p_r   = p.ScalarMult(r); //(p_k-1,r_k-1)
                p_p   = p.ScalarMult(p); //(p_k-1,p_k-1)
                alpha = p_r / p_p;

                x.Add(z, 1, alpha, true);                                     // x_k = x_k-1 + alfa_k*z_k-1

                r.Add(p, 1, -alpha, true);                                    // r_k = r_k-1 - alfa_k*p_k-1

                Ar = preconditioner.SolveL(A.Mult(preconditioner.SolveU(r))); //Ar_k = L^-1 * A * U^-1 * r_k
                //Ar = A.SolveU(r);
                //Ar = AA.Mult(Ar);
                //Ar = A.SolveL(Ar);

                beta = -(p.ScalarMult(Ar) / p_p);

                z = preconditioner.SolveU(r).Add(z, 1, beta); //z_k = U^-1 * r_k + beta_k*z_k-1
                p = Ar.Add(p, 1, beta);                       // p_k = L^-1 * A * U^-1 * r_k + beta_k*p_k-1

                if (scalRR == 0)
                {
                    Logger.WriteSolution(x, Maxiter, b.Add(A.Mult(x), -1, 1).Norm);
                    Logger.WriteTime(start, DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"));
                    throw new DivideByZeroException("Division by 0");
                }
                scalRR = r.ScalarMult(r);

                normR = Math.Sqrt(scalRR) / b.Norm;
                Factory.Residual.Add(normR);
                Logger.WriteIteration(iter, normR);

                if (double.IsNaN(normR) || double.IsInfinity(normR))
                {
                    Logger.WriteSolution(x, Maxiter, b.Add(A.Mult(x), -1, 1).Norm);
                    Logger.WriteTime(start, DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"));
                    throw new CantSolveException();
                }
            }
            Logger.WriteSolution(x, Maxiter, b.Add(A.Mult(x), -1, 1).Norm);
            Logger.WriteTime(start, DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"));
            return(x);
        }
예제 #16
0
        /// <summary>
        /// Solves the matrix equation AX = B, where A is the coefficient matrix (this matrix), B is the solution matrix and X is the unknown matrix.
        /// </summary>
        /// <param name="input">The solution matrix <c>B</c>.</param>
        /// <param name="solver">The iterative solver to use.</param>
        /// <param name="stopCriteria">Criteria to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        /// <returns>The result matrix <c>X</c>.</returns>
        public Matrix <T> SolveIterative(Matrix <T> input, IIterativeSolver <T> solver, IPreconditioner <T> preconditioner, params IIterationStopCriterion <T>[] stopCriteria)
        {
            var result = Build.Dense(input.RowCount, input.ColumnCount);

            TrySolveIterative(input, result, solver, preconditioner, stopCriteria);
            return(result);
        }
예제 #17
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                                     ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            JacobiParametrs JacParametrs = solverParametrs as JacobiParametrs;

            if (JacParametrs != null)
            {
                Vector x, r, diagonal;
                int    size, k;
                double relativeResidual, w, rightPartNorm;
                Vector Db, Dx, Lx, Ux, DULx;

                size     = initialSolution.Size;
                x        = new Vector(size);
                r        = new Vector(size);
                diagonal = new Vector(size);

                x             = initialSolution;
                w             = JacParametrs.Relaxation;
                diagonal      = matrix.SourceMatrix.Diagonal;
                rightPartNorm = rightPart.Norm();

                Dx = Vector.Mult(diagonal, x);
                Lx = matrix.SourceMatrix.LMult(x, false);
                Ux = matrix.SourceMatrix.UMult(x, false);
                r  = Lx + Dx + Ux - rightPart;
                relativeResidual = r.Norm() / rightPartNorm;

                if (System.Double.IsInfinity(relativeResidual))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by Jacobi.");
                    return(x);
                }

                if (System.Double.IsNaN(relativeResidual))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by Jacobi.");
                    return(x);
                }

                Db = Vector.Division(rightPart, diagonal);

                solverLogger.AddIterationInfo(0, relativeResidual);

                for (k = 1; k <= solverParametrs.MaxIterations && relativeResidual > solverParametrs.Epsilon; k++)
                {
                    DULx = Vector.Division(Ux + Lx, diagonal);

                    x = (Db - DULx) * w + x * (1 - w);

                    Dx = Vector.Mult(diagonal, x);
                    Lx = matrix.SourceMatrix.LMult(x, false);
                    Ux = matrix.SourceMatrix.UMult(x, false);
                    r  = Lx + Dx + Ux - rightPart;
                    relativeResidual = r.Norm() / rightPartNorm;

                    if (System.Double.IsInfinity(relativeResidual))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by Jacobi.");
                        return(x);
                    }

                    if (System.Double.IsNaN(relativeResidual))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by Jacobi.");
                        return(x);
                    }

                    solverLogger.AddIterationInfo(k, relativeResidual);
                }

                return(x);
            }
            else
            {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in Jacobi");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in Jacobi");
            }
        }
예제 #18
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
        /// <param name="input">The solution vector, <c>b</c></param>
        /// <param name="result">The result vector, <c>x</c></param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <Numerics.Complex32> matrix, Vector <Numerics.Complex32> input, Vector <Numerics.Complex32> result, Iterator <Numerics.Complex32> iterator, IPreconditioner <Numerics.Complex32> preconditioner)
        {
            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, nameof(matrix));
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, matrix);
            }

            if (iterator == null)
            {
                iterator = new Iterator <Numerics.Complex32>();
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <Numerics.Complex32>();
            }

            preconditioner.Initialize(matrix);

            var d = new DenseVector(input.Count);
            var r = DenseVector.OfVector(input);

            var uodd  = new DenseVector(input.Count);
            var ueven = new DenseVector(input.Count);

            var v = new DenseVector(input.Count);
            var pseudoResiduals = DenseVector.OfVector(input);

            var x     = new DenseVector(input.Count);
            var yodd  = new DenseVector(input.Count);
            var yeven = DenseVector.OfVector(input);

            // Temp vectors
            var temp  = new DenseVector(input.Count);
            var temp1 = new DenseVector(input.Count);
            var temp2 = new DenseVector(input.Count);

            // Define the scalars
            Numerics.Complex32 alpha = 0;
            Numerics.Complex32 eta   = 0;
            float theta = 0;

            // Initialize
            var tau = (float)input.L2Norm();

            Numerics.Complex32 rho = tau * tau;

            // Calculate the initial values for v
            // M temp = yEven
            preconditioner.Approximate(yeven, temp);

            // v = A temp
            matrix.Multiply(temp, v);

            // Set uOdd
            v.CopyTo(ueven);

            // Start the iteration
            var iterationNumber = 0;

            while (iterator.DetermineStatus(iterationNumber, result, input, pseudoResiduals) == IterationStatus.Continue)
            {
                // First part of the step, the even bit
                if (IsEven(iterationNumber))
                {
                    // sigma = (v, r)
                    var sigma = r.ConjugateDotProduct(v);
                    if (sigma.Real.AlmostEqualNumbersBetween(0, 1) && sigma.Imaginary.AlmostEqualNumbersBetween(0, 1))
                    {
                        // FAIL HERE
                        iterator.Cancel();
                        break;
                    }

                    // alpha = rho / sigma
                    alpha = rho / sigma;

                    // yOdd = yEven - alpha * v
                    v.Multiply(-alpha, temp1);
                    yeven.Add(temp1, yodd);

                    // Solve M temp = yOdd
                    preconditioner.Approximate(yodd, temp);

                    // uOdd = A temp
                    matrix.Multiply(temp, uodd);
                }

                // The intermediate step which is equal for both even and
                // odd iteration steps.
                // Select the correct vector
                var uinternal = IsEven(iterationNumber) ? ueven : uodd;
                var yinternal = IsEven(iterationNumber) ? yeven : yodd;

                // pseudoResiduals = pseudoResiduals - alpha * uOdd
                uinternal.Multiply(-alpha, temp1);
                pseudoResiduals.Add(temp1, temp2);
                temp2.CopyTo(pseudoResiduals);

                // d = yOdd + theta * theta * eta / alpha * d
                d.Multiply(theta * theta * eta / alpha, temp);
                yinternal.Add(temp, d);

                // theta = ||pseudoResiduals||_2 / tau
                theta = (float)pseudoResiduals.L2Norm() / tau;
                var c = 1 / (float)Math.Sqrt(1 + (theta * theta));

                // tau = tau * theta * c
                tau *= theta * c;

                // eta = c^2 * alpha
                eta = c * c * alpha;

                // x = x + eta * d
                d.Multiply(eta, temp1);
                x.Add(temp1, temp2);
                temp2.CopyTo(x);

                // Check convergence and see if we can bail
                if (iterator.DetermineStatus(iterationNumber, result, input, pseudoResiduals) != IterationStatus.Continue)
                {
                    // Calculate the real values
                    preconditioner.Approximate(x, result);

                    // Calculate the true residual. Use the temp vector for that
                    // so that we don't pollute the pseudoResidual vector for no
                    // good reason.
                    CalculateTrueResidual(matrix, temp, result, input);

                    // Now recheck the convergence
                    if (iterator.DetermineStatus(iterationNumber, result, input, temp) != IterationStatus.Continue)
                    {
                        // We're all good now.
                        return;
                    }
                }

                // The odd step
                if (!IsEven(iterationNumber))
                {
                    if (rho.Real.AlmostEqualNumbersBetween(0, 1) && rho.Imaginary.AlmostEqualNumbersBetween(0, 1))
                    {
                        // FAIL HERE
                        iterator.Cancel();
                        break;
                    }

                    var rhoNew = r.ConjugateDotProduct(pseudoResiduals);
                    var beta   = rhoNew / rho;

                    // Update rho for the next loop
                    rho = rhoNew;

                    // yOdd = pseudoResiduals + beta * yOdd
                    yodd.Multiply(beta, temp1);
                    pseudoResiduals.Add(temp1, yeven);

                    // Solve M temp = yOdd
                    preconditioner.Approximate(yeven, temp);

                    // uOdd = A temp
                    matrix.Multiply(temp, ueven);

                    // v = uEven + beta * (uOdd + beta * v)
                    v.Multiply(beta, temp1);
                    uodd.Add(temp1, temp);

                    temp.Multiply(beta, temp1);
                    ueven.Add(temp1, v);
                }

                // Calculate the real values
                preconditioner.Approximate(x, result);

                iterationNumber++;
            }
        }
예제 #19
0
 public PCG(IPreconditioner <double> M)
 {
     this.Preconditioner = M;
 }
예제 #20
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                                     ILogger logger,  ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            JacobiParametrs JacParametrs = solverParametrs as JacobiParametrs;

            if (JacParametrs != null)
            {
                Vector x, r, diagonal;
                int size, k;
                double relativeResidual, w, rightPartNorm;
                Vector Db, Dx, Lx, Ux, DULx;

                size = initialSolution.Size;
                x = new Vector(size);
                r = new Vector(size);
                diagonal = new Vector(size);

                x = initialSolution;
                w = JacParametrs.Relaxation;
                diagonal = matrix.SourceMatrix.Diagonal;
                rightPartNorm = rightPart.Norm();

                Dx = Vector.Mult(diagonal, x);
                Lx = matrix.SourceMatrix.LMult(x, false);
                Ux = matrix.SourceMatrix.UMult(x, false);
                r = Lx + Dx + Ux - rightPart;
                relativeResidual = r.Norm() / rightPartNorm;

                if (System.Double.IsInfinity(relativeResidual))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by Jacobi.");
                    return x;
                }

                if (System.Double.IsNaN(relativeResidual))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by Jacobi.");
                    return x;
                }

                Db = Vector.Division(rightPart, diagonal);

                solverLogger.AddIterationInfo(0, relativeResidual);

                for (k = 1; k <= solverParametrs.MaxIterations && relativeResidual > solverParametrs.Epsilon; k++)
                {
                    DULx = Vector.Division(Ux + Lx, diagonal);

                    x = (Db - DULx) * w + x * (1 - w);

                    Dx = Vector.Mult(diagonal, x);
                    Lx = matrix.SourceMatrix.LMult(x, false);
                    Ux = matrix.SourceMatrix.UMult(x, false);
                    r = Lx + Dx + Ux - rightPart;
                    relativeResidual = r.Norm() / rightPartNorm;

                    if (System.Double.IsInfinity(relativeResidual))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by Jacobi.");
                        return x;
                    }

                    if (System.Double.IsNaN(relativeResidual))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by Jacobi.");
                        return x;
                    }

                    solverLogger.AddIterationInfo(k, relativeResidual);
                }

                return x;
            }
            else {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in Jacobi");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in Jacobi");

            }
        }
예제 #21
0
 public abstract Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                              ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs);
예제 #22
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                                     ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            GMRESParameters GMRESParameters = solverParametrs as GMRESParameters;

            if (GMRESParameters != null)
            {
                Vector[] V, H;
                Vector   residual, x, d, z, w, tmp;
                bool     continueCalculations;
                double   epsilon       = GMRESParameters.Epsilon;
                int      m             = GMRESParameters.M;
                int      maxIterations = GMRESParameters.MaxIterations;
                int      n             = rightPart.Size;

                x        = initialSolution;
                residual = rightPart - matrix.SourceMatrix.Multiply(x);
                residual = matrix.SSolve(residual);
                double rightPartNorm = matrix.SSolve(rightPart).Norm();
                double residualNorm  = residual.Norm();

                if (System.Double.IsInfinity(residualNorm / rightPartNorm))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES.");
                    return(x);
                }

                if (System.Double.IsNaN(residualNorm / rightPartNorm))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES.");
                    return(x);
                }

                x = matrix.QMultiply(initialSolution);

                V = new Vector[m];
                for (int i = 0; i < m; i++)
                {
                    V[i] = new Vector(n);
                }

                H = new Vector[m];
                for (int i = 0; i < m; i++)
                {
                    H[i] = new Vector(m + 1);
                }

                d = new Vector(m + 1);

                for (int k = 1; k <= maxIterations && residualNorm / rightPartNorm > epsilon; k++)
                {
                    d.Nullify();
                    V[0] = residual * (1.0 / residualNorm);

                    continueCalculations = true;
                    for (int j = 1; j <= m && continueCalculations; j++)
                    {
                        tmp = matrix.QSolve(V[j - 1]);
                        w   = matrix.SSolve(matrix.SourceMatrix.Multiply(tmp));

                        for (int l = 1; l <= j; l++)
                        {
                            H[j - 1][l - 1] = V[l - 1] * w;
                            w = w - V[l - 1] * H[j - 1][l - 1];
                        }

                        H[j - 1][j] = w.Norm();
                        if (Math.Abs(H[j - 1][j]) < 1e-10)
                        {
                            m = j;
                            continueCalculations = false;
                        }
                        else
                        {
                            if (j != m)
                            {
                                V[j] = w * (1.0 / H[j - 1][j]);
                            }
                        }
                    }

                    d[0] = residualNorm;
                    z    = solveMinSqrProblem(d, H, m);
                    x    = x + multiplyMatrixVector(z, V);

                    tmp          = rightPart - matrix.SourceMatrix.Multiply(matrix.QSolve(x));
                    residual     = matrix.SSolve(tmp);
                    residualNorm = residual.Norm();

                    if (System.Double.IsInfinity(residualNorm / rightPartNorm))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES.");
                        return(x);
                    }

                    if (System.Double.IsNaN(residualNorm / rightPartNorm))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES.");
                        return(x);
                    }

                    solverLogger.AddIterationInfo(k, residualNorm / rightPartNorm);
                }

                return(matrix.QSolve(x));
            }
            else
            {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GMRES");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in GMRES");
            }
        }
예제 #23
0
 /// <summary>
 /// Check the result.
 /// </summary>
 /// <param name="preconditioner">Specific preconditioner.</param>
 /// <param name="matrix">Source matrix.</param>
 /// <param name="vector">Initial vector.</param>
 /// <param name="result">Result vector.</param>
 protected abstract void CheckResult(IPreconditioner<double> preconditioner, SparseMatrix matrix, Vector<double> vector, Vector<double> result);
예제 #24
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
        /// <param name="input">The solution vector, <c>b</c></param>
        /// <param name="result">The result vector, <c>x</c></param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <float> matrix, Vector <float> input, Vector <float> result, Iterator <float> iterator, IPreconditioner <float> preconditioner)
        {
            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resource.ArgumentMatrixSquare, "matrix");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resource.ArgumentVectorsSameLength);
            }

            if (iterator == null)
            {
                iterator = new Iterator <float>();
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <float>();
            }

            // Create a copy of the solution and result vectors so we can use them
            // later on
            var internalInput  = input.Clone();
            var internalResult = result.Clone();

            foreach (var solver in _solvers)
            {
                // Store a reference to the solver so we can stop it.

                IterationStatus status;
                try
                {
                    // Reset the iterator and pass it to the solver
                    iterator.Reset();

                    // Start the solver
                    solver.Item1.Solve(matrix, internalInput, internalResult, iterator, solver.Item2 ?? preconditioner);
                    status = iterator.Status;
                }
                catch (Exception)
                {
                    // The solver broke down.
                    // Log a message about this
                    // Switch to the next preconditioner.
                    // Reset the solution vector to the previous solution
                    input.CopyTo(internalInput);
                    continue;
                }

                // There was no fatal breakdown so check the status
                if (status == IterationStatus.Converged)
                {
                    // We're done
                    internalResult.CopyTo(result);
                    break;
                }

                // We're not done
                // Either:
                // - calculation finished without convergence
                if (status == IterationStatus.StoppedWithoutConvergence)
                {
                    // Copy the internal result to the result vector and
                    // continue with the calculation.
                    internalResult.CopyTo(result);
                }
                else
                {
                    // - calculation failed --> restart with the original vector
                    // - calculation diverged --> restart with the original vector
                    // - Some unknown status occurred --> To be safe restart.
                    input.CopyTo(internalInput);
                }
            }
        }
예제 #25
0
        // Iterative Solvers: Full

        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix (this matrix), b is the solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="input">The solution vector <c>b</c>.</param>
        /// <param name="result">The result vector <c>x</c>.</param>
        /// <param name="solver">The iterative solver to use.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public IterationStatus TrySolveIterative(Vector <T> input, Vector <T> result, IIterativeSolver <T> solver, Iterator <T> iterator = null, IPreconditioner <T> preconditioner = null)
        {
            if (iterator == null)
            {
                iterator = new Iterator <T>(Build.IterativeSolverStopCriteria());
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <T>();
            }

            solver.Solve(this, input, result, iterator, preconditioner);

            return(iterator.Status);
        }
 /// <summary>
 /// Check the result.
 /// </summary>
 /// <param name="preconditioner">Specific preconditioner.</param>
 /// <param name="matrix">Source matrix.</param>
 /// <param name="vector">Initial vector.</param>
 /// <param name="result">Result vector.</param>
 protected abstract void CheckResult(IPreconditioner <Complex> preconditioner, SparseMatrix matrix, Vector <Complex> vector, Vector <Complex> result);
예제 #27
0
 public override void HandleMatrixWillBeSet()
 {
     mustUpdatePreconditioner = true;
     preconditioner           = null;
 }
예제 #28
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <Complex> matrix, Vector <Complex> input, Vector <Complex> result, Iterator <Complex> iterator, IPreconditioner <Complex> preconditioner)
        {
            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, result);
            }

            if (iterator == null)
            {
                iterator = new Iterator <Complex>();
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <Complex>();
            }

            preconditioner.Initialize(matrix);

            // Compute r_0 = b - Ax_0 for some initial guess x_0
            // In this case we take x_0 = vector
            // This is basically a SAXPY so it could be made a lot faster
            var residuals = new DenseVector(matrix.RowCount);

            CalculateTrueResidual(matrix, residuals, result, input);

            // Choose r~ (for example, r~ = r_0)
            var tempResiduals = residuals.Clone();

            // create seven temporary vectors needed to hold temporary
            // coefficients. All vectors are mangled in each iteration.
            // These are defined here to prevent stressing the garbage collector
            var vecP     = new DenseVector(residuals.Count);
            var vecPdash = new DenseVector(residuals.Count);
            var nu       = new DenseVector(residuals.Count);
            var vecS     = new DenseVector(residuals.Count);
            var vecSdash = new DenseVector(residuals.Count);
            var temp     = new DenseVector(residuals.Count);
            var temp2    = new DenseVector(residuals.Count);

            // create some temporary double variables that are needed
            // to hold values in between iterations
            Complex currentRho = 0;
            Complex alpha      = 0;
            Complex omega      = 0;

            var iterationNumber = 0;

            while (iterator.DetermineStatus(iterationNumber, result, input, residuals) == IterationStatus.Continue)
            {
                // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
                var oldRho = currentRho;
                currentRho = tempResiduals.ConjugateDotProduct(residuals);

                // if (rho_(i-1) == 0) // METHOD FAILS
                // If rho is only 1 ULP from zero then we fail.
                if (currentRho.Real.AlmostEqualNumbersBetween(0, 1) && currentRho.Imaginary.AlmostEqualNumbersBetween(0, 1))
                {
                    // Rho-type breakdown
                    throw new NumericalBreakdownException();
                }

                if (iterationNumber != 0)
                {
                    // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
                    var beta = (currentRho / oldRho) * (alpha / omega);

                    // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
                    nu.Multiply(-omega, temp);
                    vecP.Add(temp, temp2);
                    temp2.CopyTo(vecP);

                    vecP.Multiply(beta, vecP);
                    vecP.Add(residuals, temp2);
                    temp2.CopyTo(vecP);
                }
                else
                {
                    // p_i = r_(i-1)
                    residuals.CopyTo(vecP);
                }

                // SOLVE Mp~ = p_i // M = preconditioner
                preconditioner.Approximate(vecP, vecPdash);

                // nu_i = Ap~
                matrix.Multiply(vecPdash, nu);

                // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
                alpha = currentRho * 1 / tempResiduals.ConjugateDotProduct(nu);

                // s = r_(i-1) - alpha_i nu_i
                nu.Multiply(-alpha, temp);
                residuals.Add(temp, vecS);

                // Check if we're converged. If so then stop. Otherwise continue;
                // Calculate the temporary result.
                // Be careful not to change any of the temp vectors, except for
                // temp. Others will be used in the calculation later on.
                // x_i = x_(i-1) + alpha_i * p^_i + s^_i
                vecPdash.Multiply(alpha, temp);
                temp.Add(vecSdash, temp2);
                temp2.CopyTo(temp);
                temp.Add(result, temp2);
                temp2.CopyTo(temp);

                // Check convergence and stop if we are converged.
                if (iterator.DetermineStatus(iterationNumber, temp, input, vecS) != IterationStatus.Continue)
                {
                    temp.CopyTo(result);

                    // Calculate the true residual
                    CalculateTrueResidual(matrix, residuals, result, input);

                    // Now recheck the convergence
                    if (iterator.DetermineStatus(iterationNumber, result, input, residuals) != IterationStatus.Continue)
                    {
                        // We're all good now.
                        return;
                    }

                    // Continue the calculation
                    iterationNumber++;
                    continue;
                }

                // SOLVE Ms~ = s
                preconditioner.Approximate(vecS, vecSdash);

                // temp = As~
                matrix.Multiply(vecSdash, temp);

                // omega_i = temp^T s / temp^T temp
                omega = temp.ConjugateDotProduct(vecS) / temp.ConjugateDotProduct(temp);

                // x_i = x_(i-1) + alpha_i p^ + omega_i s^
                temp.Multiply(-omega, residuals);
                residuals.Add(vecS, temp2);
                temp2.CopyTo(residuals);

                vecSdash.Multiply(omega, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                vecPdash.Multiply(alpha, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                // for continuation it is necessary that omega_i != 0.0
                // If omega is only 1 ULP from zero then we fail.
                if (omega.Real.AlmostEqualNumbersBetween(0, 1) && omega.Imaginary.AlmostEqualNumbersBetween(0, 1))
                {
                    // Omega-type breakdown
                    throw new NumericalBreakdownException();
                }

                if (iterator.DetermineStatus(iterationNumber, result, input, residuals) != IterationStatus.Continue)
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    // The residual calculation based on omega_i * s can be off by a factor 10. So here
                    // we calculate the real residual (which can be expensive) but we only do it if we're
                    // sufficiently close to the finish.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                iterationNumber++;
            }
        }
예제 #29
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            BCGStabParametrs ConGradParametrs = solverParametrs as BCGStabParametrs;

            if (ConGradParametrs == null)
            {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in BSGStab");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in BSGSTab");
            }
            else
            {
                int    oIter = 0;
                double nPi, oPi, alpha, w, oNev, bNev, betta;
                oPi = alpha = w = 1;
                int    size = rightPart.Size;
                Vector x, r, rTab, s, t, z, sqt, y;
                Vector v = new Vector(size);
                Vector p = new Vector(size);
                v.Nullify();
                p.Nullify();
                x    = initialSolution;
                r    = rightPart - matrix.SourceMatrix.Multiply(x);
                rTab = r;
                bNev = rightPart.Norm();
                oNev = r.Norm() / bNev;
                solverLogger.AddIterationInfo(oIter, oNev);//logger
                if (System.Double.IsInfinity(oNev))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by BSG Stab.");
                    return(x);
                }

                if (System.Double.IsNaN(oNev))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by BSG Stab.");
                    return(x);
                }
                while (oIter < ConGradParametrs.MaxIterations && oNev > ConGradParametrs.Epsilon)
                {
                    nPi   = rTab * r;
                    betta = (nPi / oPi) * (alpha / w);
                    p     = r + (p - v * w) * betta;
                    y     = matrix.QSolve(matrix.SSolve(p));
                    v     = matrix.SourceMatrix.Multiply(y);
                    alpha = nPi / (rTab * v);
                    x     = x + y * alpha;//УТОЧНИТЬ!!!!!!!!!!!!!!!
                    s     = r - v * alpha;
                    if (s.Norm() / bNev < ConGradParametrs.Epsilon)
                    {
                        return(x);
                    }
                    z   = matrix.QSolve(matrix.SSolve(s));
                    t   = matrix.SourceMatrix.Multiply(z);
                    sqt = matrix.QSolve(matrix.SSolve(t));
                    w   = (z * sqt) / (sqt * sqt);
                    x   = x + z * w;//УТОЧНИТЬ!!!!!!!!!!!!!!!!!!!
                    r   = s - t * w;

                    oPi = nPi;
                    oIter++;
                    oNev = r.Norm() / bNev;

                    if (System.Double.IsInfinity(oNev))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by BSG Stab.");
                        return(x);
                    }

                    if (System.Double.IsNaN(oNev))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by BSG Stab.");
                        return(x);
                    }
                    solverLogger.AddIterationInfo(oIter, oNev);//logger
                }

                return(x);
            }
        }
예제 #30
0
        /// <summary>
        /// Solves the matrix equation AX = B, where A is the coefficient matrix (this matrix), B is the solution matrix and X is the unknown matrix.
        /// </summary>
        /// <param name="input">The solution matrix <c>B</c>.</param>
        /// <param name="result">The result matrix <c>X</c></param>
        /// <param name="solver">The iterative solver to use.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public IterationStatus TrySolveIterative(Matrix <T> input, Matrix <T> result, IIterativeSolver <T> solver, Iterator <T> iterator = null, IPreconditioner <T> preconditioner = null)
        {
            if (RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
            {
                throw DimensionsDontMatch <ArgumentException>(this, input, result);
            }

            if (iterator == null)
            {
                iterator = new Iterator <T>(Build.IterativeSolverStopCriteria());
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <T>();
            }

            for (var column = 0; column < input.ColumnCount; column++)
            {
                var solution = Vector <T> .Build.Dense(RowCount);

                solver.Solve(this, input.Column(column), solution, iterator, preconditioner);

                foreach (var element in solution.EnumerateIndexed(Zeros.AllowSkip))
                {
                    result.At(element.Item1, column, element.Item2);
                }
            }

            return(iterator.Status);
        }
예제 #31
0
 public abstract Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution,
                 ILogger logger,ISolverLogger solverLogger, ISolverParametrs solverParametrs);
예제 #32
0
        // Iterative Solvers: Simple

        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix (this matrix), b is the solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="input">The solution vector <c>b</c>.</param>
        /// <param name="solver">The iterative solver to use.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        /// <returns>The result vector <c>x</c>.</returns>
        public Vector <T> SolveIterative(Vector <T> input, IIterativeSolver <T> solver, Iterator <T> iterator = null, IPreconditioner <T> preconditioner = null)
        {
            var result = Vector <T> .Build.Dense(RowCount);

            TrySolveIterative(input, result, solver, iterator, preconditioner);
            return(result);
        }
예제 #33
0
 public IterativeStatistics Solve(IMatrixView matrix, IPreconditioner preconditioner, IVectorView rhs, IVector solution,
                                  bool initialGuessIsZero, Func <IVector> zeroVectorInitializer)
 {
     return(Solve(new ExplicitMatrixTransformation(matrix), preconditioner, rhs, solution, initialGuessIsZero,
                  zeroVectorInitializer));
 }
예제 #34
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix (this matrix), b is the solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="input">The solution vector <c>b</c>.</param>
        /// <param name="solver">The iterative solver to use.</param>
        /// <param name="stopCriteria">Criteria to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        /// <returns>The result vector <c>x</c>.</returns>
        public Vector <T> SolveIterative(Vector <T> input, IIterativeSolver <T> solver, IPreconditioner <T> preconditioner, params IIterationStopCriterion <T>[] stopCriteria)
        {
            var result = Vector <T> .Build.Dense(RowCount);

            TrySolveIterative(input, result, solver, preconditioner, stopCriteria);
            return(result);
        }
예제 #35
0
        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
            });
        }
예제 #36
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
        /// <param name="input">The solution vector, <c>b</c></param>
        /// <param name="result">The result vector, <c>x</c></param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <Numerics.Complex32> matrix, Vector <Numerics.Complex32> input, Vector <Numerics.Complex32> result, Iterator <Numerics.Complex32> iterator, IPreconditioner <Numerics.Complex32> preconditioner)
        {
            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, matrix);
            }

            if (iterator == null)
            {
                iterator = new Iterator <Numerics.Complex32>();
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <Numerics.Complex32>();
            }

            preconditioner.Initialize(matrix);

            // Choose an initial guess x_0
            // Take x_0 = 0
            var xtemp = new DenseVector(input.Count);

            // Choose k vectors q_1, q_2, ..., q_k
            // Build a new set if:
            // a) the stored set doesn't exist (i.e. == null)
            // b) Is of an incorrect length (i.e. too long)
            // c) The vectors are of an incorrect length (i.e. too long or too short)
            var useOld = false;

            if (_startingVectors != null)
            {
                // We don't accept collections with zero starting vectors so ...
                if (_startingVectors.Count <= NumberOfStartingVectorsToCreate(_numberOfStartingVectors, input.Count))
                {
                    // Only check the first vector for sizing. If that matches we assume the
                    // other vectors match too. If they don't the process will crash
                    if (_startingVectors[0].Count == input.Count)
                    {
                        useOld = true;
                    }
                }
            }

            _startingVectors = useOld ? _startingVectors : CreateStartingVectors(_numberOfStartingVectors, input.Count);

            // Store the number of starting vectors. Not really necessary but easier to type :)
            var k = _startingVectors.Count;

            // r_0 = b - Ax_0
            // This is basically a SAXPY so it could be made a lot faster
            var residuals = new DenseVector(matrix.RowCount);

            CalculateTrueResidual(matrix, residuals, xtemp, input);

            // Define the temporary values
            var c = new Numerics.Complex32[k];

            // Define the temporary vectors
            var gtemp = new DenseVector(residuals.Count);

            var u     = new DenseVector(residuals.Count);
            var utemp = new DenseVector(residuals.Count);
            var temp  = new DenseVector(residuals.Count);
            var temp1 = new DenseVector(residuals.Count);
            var temp2 = new DenseVector(residuals.Count);

            var zd = new DenseVector(residuals.Count);
            var zg = new DenseVector(residuals.Count);
            var zw = new DenseVector(residuals.Count);

            var d = CreateVectorArray(_startingVectors.Count, residuals.Count);

            // g_0 = r_0
            var g = CreateVectorArray(_startingVectors.Count, residuals.Count);

            residuals.CopyTo(g[k - 1]);

            var w = CreateVectorArray(_startingVectors.Count, residuals.Count);

            // FOR (j = 0, 1, 2 ....)
            var iterationNumber = 0;

            while (iterator.DetermineStatus(iterationNumber, xtemp, input, residuals) == IterationStatus.Continue)
            {
                // SOLVE M g~_((j-1)k+k) = g_((j-1)k+k)
                preconditioner.Approximate(g[k - 1], gtemp);

                // w_((j-1)k+k) = A g~_((j-1)k+k)
                matrix.Multiply(gtemp, w[k - 1]);

                // c_((j-1)k+k) = q^T_1 w_((j-1)k+k)
                c[k - 1] = _startingVectors[0].ConjugateDotProduct(w[k - 1]);
                if (c[k - 1].Real.AlmostEqualNumbersBetween(0, 1) && c[k - 1].Imaginary.AlmostEqualNumbersBetween(0, 1))
                {
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                // alpha_(jk+1) = q^T_1 r_((j-1)k+k) / c_((j-1)k+k)
                var alpha = _startingVectors[0].ConjugateDotProduct(residuals) / c[k - 1];

                // u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
                w[k - 1].Multiply(-alpha, temp);
                residuals.Add(temp, u);

                // SOLVE M u~_(jk+1) = u_(jk+1)
                preconditioner.Approximate(u, temp1);
                temp1.CopyTo(utemp);

                // rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
                matrix.Multiply(temp1, temp);
                var rho = temp.ConjugateDotProduct(temp);

                // If rho is zero then temp is a zero vector and we're probably
                // about to have zero residuals (i.e. an exact solution).
                // So set rho to 1.0 because in the next step it will turn to zero.
                if (rho.Real.AlmostEqualNumbersBetween(0, 1) && rho.Imaginary.AlmostEqualNumbersBetween(0, 1))
                {
                    rho = 1.0f;
                }

                rho = -u.ConjugateDotProduct(temp) / rho;

                // r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
                u.CopyTo(residuals);

                // Reuse temp
                temp.Multiply(rho, temp);
                residuals.Add(temp, temp2);
                temp2.CopyTo(residuals);

                // x_(jk+1) = x_((j-1)k_k) - rho_(j+1) u~_(jk+1) + alpha_(jk+1) g~_((j-1)k+k)
                utemp.Multiply(-rho, temp);
                xtemp.Add(temp, temp2);
                temp2.CopyTo(xtemp);

                gtemp.Multiply(alpha, gtemp);
                xtemp.Add(gtemp, temp2);
                temp2.CopyTo(xtemp);

                // Check convergence and stop if we are converged.
                if (iterator.DetermineStatus(iterationNumber, xtemp, input, residuals) != IterationStatus.Continue)
                {
                    // Calculate the true residual
                    CalculateTrueResidual(matrix, residuals, xtemp, input);

                    // Now recheck the convergence
                    if (iterator.DetermineStatus(iterationNumber, xtemp, input, residuals) != IterationStatus.Continue)
                    {
                        // We're all good now.
                        // Exit from the while loop.
                        break;
                    }
                }

                // FOR (i = 1,2, ...., k)
                for (var i = 0; i < k; i++)
                {
                    // z_d = u_(jk+1)
                    u.CopyTo(zd);

                    // z_g = r_(jk+i)
                    residuals.CopyTo(zg);

                    // z_w = 0
                    zw.Clear();

                    // FOR (s = i, ...., k-1) AND j >= 1
                    Numerics.Complex32 beta;
                    if (iterationNumber >= 1)
                    {
                        for (var s = i; s < k - 1; s++)
                        {
                            // beta^(jk+i)_((j-1)k+s) = -q^t_(s+1) z_d / c_((j-1)k+s)
                            beta = -_startingVectors[s + 1].ConjugateDotProduct(zd) / c[s];

                            // z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
                            d[s].Multiply(beta, temp);
                            zd.Add(temp, temp2);
                            temp2.CopyTo(zd);

                            // z_g = z_g + beta^(jk+i)_((j-1)k+s) g_((j-1)k+s)
                            g[s].Multiply(beta, temp);
                            zg.Add(temp, temp2);
                            temp2.CopyTo(zg);

                            // z_w = z_w + beta^(jk+i)_((j-1)k+s) w_((j-1)k+s)
                            w[s].Multiply(beta, temp);
                            zw.Add(temp, temp2);
                            temp2.CopyTo(zw);
                        }
                    }

                    beta = rho * c[k - 1];
                    if (beta.Real.AlmostEqualNumbersBetween(0, 1) && beta.Imaginary.AlmostEqualNumbersBetween(0, 1))
                    {
                        throw new Exception("Iterative solver experience a numerical break down");
                    }

                    // beta^(jk+i)_((j-1)k+k) = -(q^T_1 (r_(jk+1) + rho_(j+1) z_w)) / (rho_(j+1) c_((j-1)k+k))
                    zw.Multiply(rho, temp2);
                    residuals.Add(temp2, temp);
                    beta = -_startingVectors[0].ConjugateDotProduct(temp) / beta;

                    // z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
                    g[k - 1].Multiply(beta, temp);
                    zg.Add(temp, temp2);
                    temp2.CopyTo(zg);

                    // z_w = rho_(j+1) (z_w + beta^(jk+i)_((j-1)k+k) w_((j-1)k+k))
                    w[k - 1].Multiply(beta, temp);
                    zw.Add(temp, temp2);
                    temp2.CopyTo(zw);
                    zw.Multiply(rho, zw);

                    // z_d = r_(jk+i) + z_w
                    residuals.Add(zw, zd);

                    // FOR (s = 1, ... i - 1)
                    for (var s = 0; s < i - 1; s++)
                    {
                        // beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+s)
                        beta = -_startingVectors[s + 1].ConjugateDotProduct(zd) / c[s];

                        // z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
                        d[s].Multiply(beta, temp);
                        zd.Add(temp, temp2);
                        temp2.CopyTo(zd);

                        // z_g = z_g + beta^(jk+i)_(jk+s) * g_(jk+s)
                        g[s].Multiply(beta, temp);
                        zg.Add(temp, temp2);
                        temp2.CopyTo(zg);
                    }

                    // d_(jk+i) = z_d - u_(jk+i)
                    zd.Subtract(u, d[i]);

                    // g_(jk+i) = z_g + z_w
                    zg.Add(zw, g[i]);

                    // IF (i < k - 1)
                    if (i < k - 1)
                    {
                        // c_(jk+1) = q^T_i+1 d_(jk+i)
                        c[i] = _startingVectors[i + 1].ConjugateDotProduct(d[i]);
                        if (c[i].Real.AlmostEqualNumbersBetween(0, 1) && c[i].Imaginary.AlmostEqualNumbersBetween(0, 1))
                        {
                            throw new Exception("Iterative solver experience a numerical break down");
                        }

                        // alpha_(jk+i+1) = q^T_(i+1) u_(jk+i) / c_(jk+i)
                        alpha = _startingVectors[i + 1].ConjugateDotProduct(u) / c[i];

                        // u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
                        d[i].Multiply(-alpha, temp);
                        u.Add(temp, temp2);
                        temp2.CopyTo(u);

                        // SOLVE M g~_(jk+i) = g_(jk+i)
                        preconditioner.Approximate(g[i], gtemp);

                        // x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i)
                        gtemp.Multiply(rho * alpha, temp);
                        xtemp.Add(temp, temp2);
                        temp2.CopyTo(xtemp);

                        // w_(jk+i) = A g~_(jk+i)
                        matrix.Multiply(gtemp, w[i]);

                        // r_(jk+i+1) = r_(jk+i) - rho_(j+1) alpha_(jk+i+1) w_(jk+i)
                        w[i].Multiply(-rho * alpha, temp);
                        residuals.Add(temp, temp2);
                        temp2.CopyTo(residuals);

                        // We can check the residuals here if they're close
                        if (iterator.DetermineStatus(iterationNumber, xtemp, input, residuals) != IterationStatus.Continue)
                        {
                            // Recalculate the residuals and go round again. This is done to ensure that
                            // we have the proper residuals.
                            CalculateTrueResidual(matrix, residuals, xtemp, input);
                        }
                    }
                } // END ITERATION OVER i

                iterationNumber++;
            }

            // copy the temporary result to the real result vector
            xtemp.CopyTo(result);
        }
예제 #37
0
 /// <summary> Sets left preconditioner</summary>
 public virtual void setM1(IPreconditioner preconditioner)
 {
     M1 = preconditioner;
 }
예제 #38
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
        /// <param name="input">The solution vector, <c>b</c></param>
        /// <param name="result">The result vector, <c>x</c></param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <double> matrix, Vector <double> input, Vector <double> result, Iterator <double> iterator, IPreconditioner <double> preconditioner)
        {
            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, nameof(matrix));
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, matrix);
            }

            if (iterator == null)
            {
                iterator = new Iterator <double>();
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <double>();
            }

            preconditioner.Initialize(matrix);

            // x_0 is initial guess
            // Take x_0 = 0
            var xtemp = new DenseVector(input.Count);

            // r_0 = b - Ax_0
            // This is basically a SAXPY so it could be made a lot faster
            var residuals = new DenseVector(matrix.RowCount);

            CalculateTrueResidual(matrix, residuals, xtemp, input);

            // Define the temporary scalars
            double beta = 0;

            // Define the temporary vectors
            // rDash_0 = r_0
            var rdash = DenseVector.OfVector(residuals);

            // t_-1 = 0
            var t  = new DenseVector(residuals.Count);
            var t0 = new DenseVector(residuals.Count);

            // w_-1 = 0
            var w = new DenseVector(residuals.Count);

            // Define the remaining temporary vectors
            var c = new DenseVector(residuals.Count);
            var p = new DenseVector(residuals.Count);
            var s = new DenseVector(residuals.Count);
            var u = new DenseVector(residuals.Count);
            var y = new DenseVector(residuals.Count);
            var z = new DenseVector(residuals.Count);

            var temp  = new DenseVector(residuals.Count);
            var temp2 = new DenseVector(residuals.Count);
            var temp3 = new DenseVector(residuals.Count);

            // for (k = 0, 1, .... )
            var iterationNumber = 0;

            while (iterator.DetermineStatus(iterationNumber, xtemp, input, residuals) == IterationStatus.Continue)
            {
                // p_k = r_k + beta_(k-1) * (p_(k-1) - u_(k-1))
                p.Subtract(u, temp);

                temp.Multiply(beta, temp2);
                residuals.Add(temp2, p);

                // Solve M b_k = p_k
                preconditioner.Approximate(p, temp);

                // s_k = A b_k
                matrix.Multiply(temp, s);

                // alpha_k = (r*_0 * r_k) / (r*_0 * s_k)
                var alpha = rdash.DotProduct(residuals) / rdash.DotProduct(s);

                // y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
                s.Subtract(w, temp);
                t.Subtract(residuals, y);

                temp.Multiply(alpha, temp2);
                y.Add(temp2, temp3);
                temp3.CopyTo(y);

                // Store the old value of t in t0
                t.CopyTo(t0);

                // t_k = r_k - alpha_k s_k
                s.Multiply(-alpha, temp2);
                residuals.Add(temp2, t);

                // Solve M d_k = t_k
                preconditioner.Approximate(t, temp);

                // c_k = A d_k
                matrix.Multiply(temp, c);
                var cdot = c.DotProduct(c);

                // cDot can only be zero if c is a zero vector
                // We'll set cDot to 1 if it is zero to prevent NaN's
                // Note that the calculation should continue fine because
                // c.DotProduct(t) will be zero and so will c.DotProduct(y)
                if (cdot.AlmostEqualNumbersBetween(0, 1))
                {
                    cdot = 1.0;
                }

                // Even if we don't want to do any BiCGStab steps we'll still have
                // to do at least one at the start to initialize the
                // system, but we'll only have to take special measures
                // if we don't do any so ...
                var    ctdot = c.DotProduct(t);
                double eta;
                double sigma;
                if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
                {
                    // sigma_k = (c_k * t_k) / (c_k * c_k)
                    sigma = ctdot / cdot;

                    // eta_k = 0
                    eta = 0;
                }
                else
                {
                    var ydot = y.DotProduct(y);

                    // yDot can only be zero if y is a zero vector
                    // We'll set yDot to 1 if it is zero to prevent NaN's
                    // Note that the calculation should continue fine because
                    // y.DotProduct(t) will be zero and so will c.DotProduct(y)
                    if (ydot.AlmostEqualNumbersBetween(0, 1))
                    {
                        ydot = 1.0;
                    }

                    var ytdot = y.DotProduct(t);
                    var cydot = c.DotProduct(y);

                    var denom = (cdot * ydot) - (cydot * cydot);

                    // sigma_k = ((y_k * y_k)(c_k * t_k) - (y_k * t_k)(c_k * y_k)) / ((c_k * c_k)(y_k * y_k) - (y_k * c_k)(c_k * y_k))
                    sigma = ((ydot * ctdot) - (ytdot * cydot)) / denom;

                    // eta_k = ((c_k * c_k)(y_k * t_k) - (y_k * c_k)(c_k * t_k)) / ((c_k * c_k)(y_k * y_k) - (y_k * c_k)(c_k * y_k))
                    eta = ((cdot * ytdot) - (cydot * ctdot)) / denom;
                }

                // u_k = sigma_k s_k + eta_k (t_(k-1) - r_k + beta_(k-1) u_(k-1))
                u.Multiply(beta, temp2);
                t0.Add(temp2, temp);

                temp.Subtract(residuals, temp3);
                temp3.CopyTo(temp);
                temp.Multiply(eta, temp);

                s.Multiply(sigma, temp2);
                temp.Add(temp2, u);

                // z_k = sigma_k r_k +_ eta_k z_(k-1) - alpha_k u_k
                z.Multiply(eta, z);
                u.Multiply(-alpha, temp2);
                z.Add(temp2, temp3);
                temp3.CopyTo(z);

                residuals.Multiply(sigma, temp2);
                z.Add(temp2, temp3);
                temp3.CopyTo(z);

                // x_(k+1) = x_k + alpha_k p_k + z_k
                p.Multiply(alpha, temp2);
                xtemp.Add(temp2, temp3);
                temp3.CopyTo(xtemp);

                xtemp.Add(z, temp3);
                temp3.CopyTo(xtemp);

                // r_(k+1) = t_k - eta_k y_k - sigma_k c_k
                // Copy the old residuals to a temp vector because we'll
                // need those in the next step
                residuals.CopyTo(t0);

                y.Multiply(-eta, temp2);
                t.Add(temp2, residuals);

                c.Multiply(-sigma, temp2);
                residuals.Add(temp2, temp3);
                temp3.CopyTo(residuals);

                // beta_k = alpha_k / sigma_k * (r*_0 * r_(k+1)) / (r*_0 * r_k)
                // But first we check if there is a possible NaN. If so just reset beta to zero.
                beta = (!sigma.AlmostEqualNumbersBetween(0, 1)) ? alpha / sigma * rdash.DotProduct(residuals) / rdash.DotProduct(t0) : 0;

                // w_k = c_k + beta_k s_k
                s.Multiply(beta, temp2);
                c.Add(temp2, w);

                // Get the real value
                preconditioner.Approximate(xtemp, result);

                // Now check for convergence
                if (iterator.DetermineStatus(iterationNumber, result, input, residuals) != IterationStatus.Continue)
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                // Next iteration.
                iterationNumber++;
            }
        }
예제 #39
0
 /// <summary> Sets right preconditioner</summary>
 public virtual void setM2(IPreconditioner preconditioner)
 {
     M2 = preconditioner;
 }
예제 #40
0
 /// <summary>
 /// Check the result.
 /// </summary>
 /// <param name="preconditioner">Specific preconditioner.</param>
 /// <param name="matrix">Source matrix.</param>
 /// <param name="vector">Initial vector.</param>
 /// <param name="result">Result vector.</param>
 protected abstract void CheckResult(IPreconditioner<Complex> preconditioner, SparseMatrix matrix, Vector<Complex> vector, Vector<Complex> result);
예제 #41
0
 public QMRSolver() : base()
 {
     M1 = M;
     M2 = M;
 }
예제 #42
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            MSGParametrs ConGradParametrs = solverParametrs as MSGParametrs;

            if (ConGradParametrs == null)
            {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in MSG");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in MSG");
            }
            else
            {
                //prestart
                int oIter = 0;
                double alpha, beta, oNev, bNev, scalRO, scaleRN;
                Vector x = initialSolution, rNew, rOld, z, ap, p;
                rOld = rightPart - matrix.SourceMatrix.Multiply(x);
                z = matrix.QSolve(matrix.SSolve(rOld));
                p = z;
                ap = matrix.SourceMatrix.Multiply(p);
                bNev = rightPart.Norm();
                oNev = rOld.Norm() / bNev;
                scalRO = z * rOld;
                //  x = matrix.QSolve(x);
                solverLogger.AddIterationInfo(oIter, oNev);//logger
                if (System.Double.IsInfinity(oNev))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by MSG.");
                    return x;
                }

                if (System.Double.IsNaN(oNev))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by MSG.");
                    return x;
                }
                while (oIter < ConGradParametrs.MaxIterations && oNev > ConGradParametrs.Epsilon)
                {
                    alpha = scalRO / (ap * p);
                    x = x + p * alpha;
                     //if (oIter % 100 == 0)
                     //rNew = matrix.QMultiply(rightPart - matrix.SMultiply(matrix.SourceMatrix.Multiply(x)));
                     //else
                    rNew = rOld - ap * alpha;
                    z = matrix.QSolve(matrix.SSolve(rNew));
                    scaleRN = z * rNew;
                    beta = scaleRN / scalRO;
                    scalRO = scaleRN;
                    p = z + p * beta;
                    ap = matrix.SourceMatrix.Multiply(p);
                    rOld = rNew;
                    oIter++;

                    oNev = rNew.Norm() / bNev;
                    if (System.Double.IsInfinity(oNev))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by MSG.");
                        return x;
                    }

                    if (System.Double.IsNaN(oNev))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by MSG.");
                        return x;
                    }

                    solverLogger.AddIterationInfo(oIter, oNev);//logger
                }
                return x;
            }
        }
예제 #43
0
        public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs)
        {
            MSGParametrs ConGradParametrs = solverParametrs as MSGParametrs;

            if (ConGradParametrs == null)
            {
                logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in MSG");
                throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a  SolverParametrs in MSG");
            }
            else
            {
                //prestart
                int    oIter = 0;
                double alpha, beta, oNev, bNev, scalRO, scaleRN;
                Vector x = initialSolution, rNew, rOld, z, ap, p;
                rOld   = rightPart - matrix.SourceMatrix.Multiply(x);
                z      = matrix.QSolve(matrix.SSolve(rOld));
                p      = z;
                ap     = matrix.SourceMatrix.Multiply(p);
                bNev   = rightPart.Norm();
                oNev   = rOld.Norm() / bNev;
                scalRO = z * rOld;
                //  x = matrix.QSolve(x);
                solverLogger.AddIterationInfo(oIter, oNev);//logger
                if (System.Double.IsInfinity(oNev))
                {
                    logger.Error("Residual is infinity. It is impossible to solve this SLAE by MSG.");
                    return(x);
                }

                if (System.Double.IsNaN(oNev))
                {
                    logger.Error("Residual is NaN. It is impossible to solve this SLAE by MSG.");
                    return(x);
                }
                while (oIter < ConGradParametrs.MaxIterations && oNev > ConGradParametrs.Epsilon)
                {
                    alpha = scalRO / (ap * p);
                    x     = x + p * alpha;
                    //if (oIter % 100 == 0)
                    //rNew = matrix.QMultiply(rightPart - matrix.SMultiply(matrix.SourceMatrix.Multiply(x)));
                    //else
                    rNew    = rOld - ap * alpha;
                    z       = matrix.QSolve(matrix.SSolve(rNew));
                    scaleRN = z * rNew;
                    beta    = scaleRN / scalRO;
                    scalRO  = scaleRN;
                    p       = z + p * beta;
                    ap      = matrix.SourceMatrix.Multiply(p);
                    rOld    = rNew;
                    oIter++;

                    oNev = rNew.Norm() / bNev;
                    if (System.Double.IsInfinity(oNev))
                    {
                        logger.Error("Residual is infinity. It is impossible to solve this SLAE by MSG.");
                        return(x);
                    }

                    if (System.Double.IsNaN(oNev))
                    {
                        logger.Error("Residual is NaN. It is impossible to solve this SLAE by MSG.");
                        return(x);
                    }

                    solverLogger.AddIterationInfo(oIter, oNev);//logger
                }
                return(x);
            }
        }