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)); }
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); }