Exemple #1
0
        /// <summary>Solves system of linear equations Ax = b using Gaussian elimination with partial pivoting.</summary>
        /// <param name="A">Elements of matrix 'A'. This array is modified during solution!</param>
        /// <param name="b">Right part 'b'. This array is also modified during solution!</param>
        /// <param name="x">Vector to store the result, i.e. the solution to the problem a x = b.</param>
        public void Solve(IROMatrix <double> A, IReadOnlyList <double> b, IVector <double> x)
        {
            if (_temp_A.RowCount != A.RowCount || _temp_A.ColumnCount != A.ColumnCount)
            {
                _temp_A = new MatrixWrapperStructForLeftSpineJaggedArray <double>(A.RowCount, A.ColumnCount);
            }
            if (b.Count != _temp_b?.Length)
            {
                _temp_b = new double[b.Count];
            }
            if (b.Count != _temp_x?.Length)
            {
                _temp_x = new double[b.Count];
            }

            MatrixMath.Copy(A, _temp_A);
            VectorMath.Copy(b, _temp_b);
            SolveDestructive(_temp_A, _temp_b, _temp_x);
            VectorMath.Copy(_temp_x, x);
        }
Exemple #2
0
        /// <summary>Solves system of linear equations Ax = b using Gaussian elimination with partial pivoting.
        /// Attention! Both matrix A and vector b are destroyed (changed).</summary>
        /// <param name="A">Elements of matrix 'A'. This array is modified!</param>
        /// <param name="b">Right part 'b'. This array is also modified!</param>
        /// <param name="x">Vector to store the result, i.e. the solution to the problem a x = b.</param>
        public void SolveDestructive(MatrixWrapperStructForLeftSpineJaggedArray <double> A, double[] b, double[] x)
        {
            var a = A.Array;

            if (a == null)
            {
                throw new ArgumentNullException(nameof(A));
            }
            if (b == null)
            {
                throw new ArgumentNullException(nameof(b));
            }
            if (x == null)
            {
                throw new ArgumentException(nameof(x));
            }

            int n = A.RowCount;

            for (int j = 0; j < n; ++j)
            {
                // Find row with largest absolute value of j-st element
                int maxIdx = 0;
                for (int i = 0; i < n - j; ++i)
                {
                    if (Math.Abs(a[i][j]) > Math.Abs(a[maxIdx][j]))
                    {
                        maxIdx = i;
                    }
                }

                // Divide this row by max value
                for (int i = j + 1; i < n; ++i)
                {
                    a[maxIdx][i] /= a[maxIdx][j];
                }

                b[maxIdx]   /= a[maxIdx][j];
                a[maxIdx][j] = 1;

                // Move this row to bottom
                if (maxIdx != n - j - 1)
                {
                    //SwapRow(A, b, n - j - 1, maxIdx);

                    var temp = a[n - j - 1];
                    a[n - j - 1] = a[maxIdx];
                    a[maxIdx]    = temp;

                    var temp3 = b[n - j - 1];
                    b[n - j - 1] = b[maxIdx];
                    b[maxIdx]    = temp3;
                }

                var an = a[n - j - 1];
                // Process all other rows
                for (int i = 0; i < n - j - 1; ++i)
                {
                    var aa = a[i];
                    if (aa[j] != 0)
                    {
                        for (int k = j + 1; k < n; ++k)
                        {
                            aa[k] -= aa[j] * an[k];
                        }
                        b[i] -= aa[j] * b[n - j - 1];
                        aa[j] = 0;
                    }
                }
            }

            // Build answer
            for (int i = 0; i < n; ++i)
            {
                double s = b[i];
                for (int j = n - i; j < n; ++j)
                {
                    s -= x[j] * a[i][j];
                }
                x[n - i - 1] = s;
            }
        }
Exemple #3
0
        /// <summary>Solves a system of linear equations Ax = b with a band matrix A, using Gaussian elimination with partial pivoting.
        /// Attention! Both matrix A and vector b are destroyed (changed).</summary>
        /// <param name="A">Elements of matrix 'A'. The matrix is modified!</param>
        /// <param name="lowerBandwidth">Lower band width of the matrix. It is not checked whether the matrix contains non-zero elements outside of the band!</param>
        /// <param name="upperBandwidth">Upper band width of the matrix. It is not checked whether the matrix contains non-zero elements outside of the band!</param>
        /// <param name="b">Right part 'b'. This array is also modified!</param>
        /// <param name="x">Vector to store the result, i.e. the solution to the problem a x = b.</param>
        public void SolveDestructiveBanded(MatrixWrapperStructForLeftSpineJaggedArray <double> A, int lowerBandwidth, int upperBandwidth, double[] b, double[] x)
        {
            var a = A.Array;

            if (a == null)
            {
                throw new ArgumentNullException(nameof(A));
            }
            if (b == null)
            {
                throw new ArgumentNullException(nameof(b));
            }
            if (x == null)
            {
                throw new ArgumentException(nameof(x));
            }

            int n = A.RowCount;

            // Start of algorithm 4.81, page 184, book of Engeln-Müllges, Numerik-Algorithmen, 10th ed.
            // note ml in the book is lowerBandwidth here, mr in the book is upperBandwidth here
            for (int j = 0; j < n - 1; ++j)
            {
                // Find row with largest absolute value of j-st element
                int    maxIdx      = j;
                double max_abs_aij = Math.Abs(a[j][j]);
                int    i_end       = Math.Min(n, j + lowerBandwidth + 1);
                for (int i = j + 1; i < i_end; ++i)
                {
                    var abs_aij = Math.Abs(a[i][j]);
                    if (abs_aij > max_abs_aij)
                    {
                        maxIdx      = i;
                        max_abs_aij = abs_aij;
                    }
                }

                if (maxIdx != j) // switch rows
                {
                    var aj = a[j];
                    a[j]      = a[maxIdx];
                    a[maxIdx] = aj;

                    var bj = b[j];
                    b[j]      = b[maxIdx];
                    b[maxIdx] = bj;
                }

                var ajj = a[j][j];
                if (0 == ajj)
                {
                    throw new SingularMatrixException("Matrix is singular");
                }

                i_end = Math.Min(n, j + lowerBandwidth + 1);
                for (int i = j + 1; i < i_end; ++i)
                {
                    var aij   = (a[i][j] /= ajj); // Element of L (left matrix)
                    int k_end = Math.Min(n, j + lowerBandwidth + upperBandwidth + 1);
                    for (int k = j + 1; k < k_end; ++k)
                    {
                        a[i][k] -= a[j][k] * aij;
                    }
                    b[i] -= b[j] * aij;
                }
            }

            // now we have an L-R matrix

            // back substitution from bottom to top, using the R matrix
            // we use the fact that coefficients can not be more away from the diagonal than lowerBandwidth+upperBandwidth
            for (int i = n - 1; i >= 0; --i)
            {
                var bi    = b[i];
                int k_end = Math.Min(n, i + lowerBandwidth + upperBandwidth + 1);
                for (int k = i + 1; k < k_end; ++k)
                {
                    bi -= a[i][k] * x[k];
                }
                x[i] = bi / a[i][i];
            }
        }
Exemple #4
0
 /// <summary>
 /// Uses an already existing array for the matrix data.
 /// </summary>
 /// <param name="wrapper">Wrapper around a left spine jagged array containing the matrix data. The data are used directly (no copy)!</param>
 public LeftSpineJaggedArrayMatrix(MatrixWrapperStructForLeftSpineJaggedArray <T> wrapper)
 {
     _array   = wrapper.Array;
     _rows    = wrapper.RowCount;
     _columns = wrapper.ColumnCount;
 }