Exemplo n.º 1
0
        private double[] makeInitialGuess(IList <double> b)
        {
            var initialGuess   = new double[NumRows];
            var initGuessValue = StarMath.SumAllElements(b) / SumAllElements();

            for (var i = 0; i < NumRows; i++)
            {
                initialGuess[i] = initGuessValue;
            }
            return(initialGuess);
        }
Exemplo n.º 2
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));
        }
Exemplo n.º 3
0
        private int[] reorderMatrixForDiagonalDominance(int length, List <int>[] potentialIndices)
        {
            var popularity = new int[length];

            for (var i = 0; i < length; i++)
            {
                popularity[i] = potentialIndices.Count(r => r.Contains(i));
            }
            var orderToAddress = StarMath.makeLinearProgression(length, 1).OrderBy(x => popularity[x]).ToList();
            var stack          = new Stack <int[]>();
            var seed           = new int[length];

            int[] candidate;
            var   solutionFound = false;

            for (var i = 0; i < length; i++)
            {
                seed[i] = -1;
            }
            stack.Push(seed);
            do
            {
                candidate = stack.Pop();
                var numToFill = candidate.Count(x => x == -1);
                if (numToFill == 0)
                {
                    solutionFound = true;
                }
                else
                {
                    var colIndex = orderToAddress[length - numToFill];
                    var possibleIndicesForRow = new List <int>();
                    for (var oldRowIndex = 0; oldRowIndex < length; oldRowIndex++)
                    {
                        if (!potentialIndices[oldRowIndex].Contains(colIndex))
                        {
                            continue;
                        }
                        if (candidate.Contains(oldRowIndex))
                        {
                            continue;
                        }
                        possibleIndicesForRow.Add(oldRowIndex);
                    }
                    if (possibleIndicesForRow.Count == 1)
                    {
                        candidate[colIndex] = possibleIndicesForRow[0];
                        stack.Push(candidate);
                    }
                    else
                    {
                        possibleIndicesForRow = possibleIndicesForRow.OrderBy(r => Math.Abs(this[r, colIndex])).ToList();
                        foreach (var i in possibleIndicesForRow)
                        {
                            var child = (int[])candidate.Clone();
                            child[colIndex] = i;
                            stack.Push(child);
                        }
                    }
                }
            } while (!solutionFound && stack.Any());
            if (solutionFound)
            {
                return(candidate);
            }
            return(null);
        }
Exemplo n.º 4
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);
        }