예제 #1
0
        private bool isGaussSeidelAppropriate(IList <double> b, out List <int>[] potentialDiagonals,
                                              ref IList <double> initialGuess)
        {
            potentialDiagonals = null;
            if (NumRows < StarMath.GaussSeidelMinimumMatrixSize)
            {
                return(false);
            }
            if (initialGuess == null)
            {
                initialGuess = makeInitialGuess(b);
            }
            var error = StarMath.norm1(StarMath.subtract(b, multiply(initialGuess))) / b.norm1();

            if (error > StarMath.MaxErrorForUsingGaussSeidel)
            {
                return(false);
            }
            return(findPotentialDiagonals(out potentialDiagonals, StarMath.GaussSeidelDiagonalDominanceRatio));
        }
예제 #2
0
        public double[] SolveIteratively(IList <double> b,
                                         IList <double> initialGuess = null, List <int>[] potentialDiagonals = null)
        {
            double[] x;
            if (initialGuess == null)
            {
                x = makeInitialGuess(b);
            }
            else
            {
                x = initialGuess.ToArray();
            }

            if (potentialDiagonals == null &&
                !findPotentialDiagonals(out potentialDiagonals, StarMath.GaussSeidelDiagonalDominanceRatio))
            {
                return(null);
            }
            var order = Enumerable.Range(0, NumRows).ToArray();

            if (!order.All(rowIndex => potentialDiagonals[rowIndex].Contains(rowIndex)))
            {
                order = reorderMatrixForDiagonalDominance(NumRows, potentialDiagonals);
            }
            if (order == null)
            {
                return(null);
            }
            var bNorm1    = StarMath.norm1(b);
            var error     = StarMath.norm1(StarMath.subtract(b, multiply(x))) / bNorm1;
            var success   = error <= StarMath.GaussSeidelMaxError;
            var xWentNaN  = false;
            var iteration = NumRows * StarMath.GaussSeidelMaxIterationFactor;

            while (!xWentNaN && !success && iteration-- > 0)
            {
                for (var i = 0; i < NumRows; i++)
                {
                    var rowI     = order[i];
                    var diagCell = Diagonals[i];
                    var adjust   = b[rowI];
                    var cell     = RowFirsts[rowI];
                    do
                    {
                        if (cell != diagCell)
                        {
                            adjust -= cell.Value * x[cell.ColIndex];
                        }
                        cell = cell.Right;
                    } while (cell != null);
                    x[rowI] = (1 - StarMath.GaussSeidelRelaxationOmega) * x[rowI] +
                              StarMath.GaussSeidelRelaxationOmega * adjust / this[rowI, i];
                }
                xWentNaN = x.Any(double.IsNaN);
                error    = StarMath.norm1(StarMath.subtract(b, multiply(x))) / bNorm1;
                success  = error <= StarMath.GaussSeidelMaxError;
            }
            if (!success)
            {
                return(null);
            }

            return(x);
        }