예제 #1
0
        /// <summary>
        /// Solves the system of linear equations.
        /// </summary>
        /// <param name="b">The vector b in A * x = b.</param>
        /// <returns>The solution vector x.</returns>
        public Double[,] Solve(Double[,] b)
        {
            var k         = Restart;
            var x         = default(Double[, ]);
            var converged = false;
            var c         = new Double[k - 1];
            var s         = new Double[k - 1];
            var gamma     = new Double[k + 1];
            var iter      = 0;

            if (Guess == null)
            {
                Guess = new Double[b.GetLength(0), b.GetLength(1)];
            }

            if (Guess.GetLength(0) != b.GetLength(0) || Guess.GetLength(1) != b.GetLength(1))
            {
                throw new InvalidOperationException(ErrorMessages.DimensionMismatch);
            }

            var H = new Double[k + 1, k];
            var V = new Double[Guess.GetLength(0), k];

            do
            {
                var j = 0;
                x = (Double[, ])Guess.Clone();
                var r0   = Helpers.Subtract(b, Helpers.Multiply(Matrix, x));
                var beta = Helpers.Norm(r0);

                H.Initialize();
                V.Initialize();
                gamma.Initialize();
                c.Initialize();
                s.Initialize();

                gamma[0] = beta;

                Helpers.SetColumnVector(V, 1, Helpers.Multiply(r0, 1.0 / beta));

                if (beta < Tolerance)
                {
                    break;
                }

                do
                {
                    iter++;

                    var Avj = Helpers.Multiply(Matrix, Helpers.GetColumnVector(V, j));
                    var sum = new Double[Avj.GetLength(0), Avj.GetLength(1)];

                    for (var m = 0; m <= j; m++)
                    {
                        var w = Helpers.GetColumnVector(V, m);
                        H[m, j] = Helpers.Reduce(w, Avj);
                        sum     = Helpers.AddScaled(sum, H[m, j], w);
                    }

                    var wj = Helpers.Subtract(Avj, sum);
                    H[j + 1, j] = Helpers.Reduce(wj, wj);
                    Rotate(j, H, c, s, gamma);

                    if (Math.Abs(H[j + 1, j]) == 0.0)
                    {
                        j++;
                        converged = true;
                        break;
                    }

                    Helpers.SetColumnVector(V, j + 1, Helpers.Multiply(wj, 1.0 / H[j + 1, j]));
                    beta = Math.Abs(gamma[j]);

                    if (beta < Tolerance)
                    {
                        j++;
                        converged = true;
                        break;
                    }

                    j++;
                }while (j < k);

                var y = new Double[j];

                for (var l = j; l >= 1; l--)
                {
                    var sum = 0.0;

                    for (var m = l + 1; m <= j; m++)
                    {
                        sum += H[l, m] * y[m];
                    }

                    y[l] = (gamma[l] - sum) / H[l, l];
                }

                for (var l = 0; l < j; l++)
                {
                    x = Helpers.AddScaled(x, y[l], Helpers.GetColumnVector(V, l));
                }

                if (converged)
                {
                    break;
                }

                Guess = x;
            }while (iter < MaxIterations);

            return(x);
        }