Beispiel #1
0
        /// <summary>
        /// Solves A x = b.
        /// </summary>
        /// <param name="rhs">The right-hand side vector b.</param>
        /// <returns>The solution vector x.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="rhs"/> is <c>null</c>.</exception>
        /// <exception cref="DimensionMismatchException">The dimension of <paramref name="rhs"/> is not the same as the dimension of the matrix.</exception>
        public ColumnVector Solve(IReadOnlyList <double> rhs)
        {
            if (rhs == null)
            {
                throw new ArgumentNullException(nameof(rhs));
            }
            if (rhs.Count != dimension)
            {
                throw new DimensionMismatchException();
            }

            // copy rhs into an array, reshuffling according to permutations
            double[] x = new double[dimension];
            for (int i = 0; i < x.Length; i++)
            {
                x[i] = rhs[permutation[i]];
            }

            // solve Ly=b and Ux=y
            Blas2.dTrsv(false, true, luStore, 0, 1, dimension, x, 0, 1, dimension);
            //SquareMatrixAlgorithms.SolveLowerLeftTriangular(luStore, x, 0, dimension);
            Blas2.dTrsv(true, false, luStore, 0, 1, dimension, x, 0, 1, dimension);
            //SquareMatrixAlgorithms.SolveUpperRightTriangular(luStore, x, 0, dimension);

            return(new ColumnVector(x, dimension));
        }
Beispiel #2
0
        /// <summary>
        /// Solve the system A x = b.
        /// </summary>
        /// <param name="rhs">The right-hand-side b.</param>
        /// <returns>The column vector x for which A x is closest to b.</returns>
        public ColumnVector Solve(IReadOnlyList <double> rhs)
        {
            if (rhs == null)
            {
                throw new ArgumentNullException(nameof(rhs));
            }
            if (rhs.Count != rows)
            {
                throw new DimensionMismatchException();
            }

            // BLAS requires an array, but doesn't modify it, so if given one, use it directly
            double[] x = rhs as double[];
            if (x == null)
            {
                x = new double[rows];
                rhs.CopyTo(x, 0);
            }

            // Q^T x is a row-length vector, but we only need the first cols entries
            // so truncate Q^T to cols X rows, so that Q^T x is only of length cols
            double[] y = new double[cols];
            Blas2.dGemv(qtStore, 0, 1, rows, x, 0, 1, y, 0, 1, cols, rows);
            MatrixAlgorithms.SolveUpperRightTriangular(rStore, rows, cols, y, 0);

            return(new ColumnVector(y, cols));
        }
Beispiel #3
0
        /// <summary>
        /// Solve the system A x = b.
        /// </summary>
        /// <param name="rhs">The right-hand-side b.</param>
        /// <returns>The column vector x for which A x is closest to b.</returns>
        public ColumnVector Solve(IList <double> rhs)
        {
            if (rhs == null)
            {
                throw new ArgumentNullException(nameof(rhs));
            }
            if (rhs.Count != rows)
            {
                throw new DimensionMismatchException();
            }

            // copy rhs into an array, if necessary
            double[] x;
            if (rhs is double[])
            {
                x = (double[])rhs;
            }
            else
            {
                x = new double[rows];
                rhs.CopyTo(x, 0);
            }

            // Q^T x is a row-length vector, but we only need the first cols entries
            // so truncate Q^T to cols X rows, so that Q^T x is only of length cols
            double[] y = new double[cols];
            Blas2.dGemv(qtStore, 0, 1, rows, x, 0, 1, y, 0, 1, cols, rows);
            MatrixAlgorithms.SolveUpperRightTriangular(rStore, rows, cols, y, 0);

            return(new ColumnVector(y, cols));
        }
Beispiel #4
0
 /// <summary>
 /// Computes the product of a rectangular matrix and a column vector.
 /// </summary>
 /// <param name="A">The matrix.</param>
 /// <param name="v">The column vector.</param>
 /// <returns>The column vector Av.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="A"/> or <paramref name="v"/> is null.</exception>
 /// <exception cref="DimensionMismatchException">The column count of <paramref name="A"/> is not the same as the dimension of <paramref name="v"/>.</exception>
 public static ColumnVector operator *(RectangularMatrix A, ColumnVector v)
 {
     if (A == null)
     {
         throw new ArgumentNullException(nameof(A));
     }
     if (v == null)
     {
         throw new ArgumentNullException(nameof(v));
     }
     if (A.cols != v.dimension)
     {
         throw new DimensionMismatchException();
     }
     double[] avStore = new double[A.rows];
     Blas2.dGemv(A.store, A.offset, A.rowStride, A.colStride, v.store, v.offset, v.stride, avStore, 0, 1, A.rows, A.cols);
     return(new ColumnVector(avStore, A.rows));
 }
Beispiel #5
0
        // mixed arithmetic

        /// <summary>
        /// Computes the product of a square matrix and a column vector.
        /// </summary>
        /// <param name="A">The matrix.</param>
        /// <param name="v">The column vector.</param>
        /// <returns>The column vector Av.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="A"/> or <paramref name="v"/> is null.</exception>
        /// <exception cref="DimensionMismatchException">The dimension of <paramref name="A"/> is not the same as the dimension of <paramref name="v"/>.</exception>
        public static ColumnVector operator *(SquareMatrix A, ColumnVector v)
        {
            if (A == null)
            {
                throw new ArgumentNullException("A");
            }
            if (v == null)
            {
                throw new ArgumentNullException("v");
            }
            if (A.dimension != v.dimension)
            {
                throw new DimensionMismatchException();
            }
            double[] avStore = new double[A.dimension];
            Blas2.dGemv(A.store, 0, 1, A.dimension, v.store, v.offset, v.stride, avStore, 0, 1, A.dimension, A.dimension);
            return(new ColumnVector(avStore, A.dimension));
        }
        /// <summary>
        /// Solves the system of equations Ax = b, where A is the original, square matrix.
        /// </summary>
        /// <param name="rhs">The right-hand-side vector b.</param>
        /// <returns>The solution vector x.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="rhs"/> is null.</exception>
        /// <exception cref="DimensionMismatchException"><paramref name="rhs"/> does not have the same dimension as the original matrix.</exception>
        /// <exception cref="InvalidOperationException">The original matrix is not square.</exception>
        /// <remarks>
        /// <para>For singular and nearly-singular matrices, this method operates differently than other solution methods like
        /// <see cref="SquareQRDecomposition.Solve(IReadOnlyList{double})"/> and <see cref="LUDecomposition.Solve(IReadOnlyList{double})"/>.
        /// For singular and nearly-singular matrices, those methods
        /// tend to produce very large or even infinite solution components that delicately cancel to produce the required right-hand-side,
        /// but have little significance to the problem being modeled because they arise from inverting very small singular values
        /// of the original matrix that are dominated by floating point rounding errors. The SVD solution discards those singular
        /// values to obtain a solution vector driven by the dominant, non-singular parts of A. While this solution does not have
        /// the minimum achievable |Ax - b|, it is often more representative of the desired solution to the problem being modeled.
        /// </para>
        /// <para>For original matrices that are not singular or nearly-singular, this method will compute the same solution
        /// as other methods.</para>
        /// <para>This method is only available for square original matrices.</para>
        /// </remarks>
        public ColumnVector Solve(IReadOnlyList <double> rhs)
        {
            if (rows != cols)
            {
                throw new InvalidOperationException();
            }
            if (rhs == null)
            {
                throw new ArgumentNullException(nameof(rhs));
            }
            if (rhs.Count != cols)
            {
                throw new DimensionMismatchException();
            }

            double[] x = new double[rows];
            double[] y = new double[rows];

            rhs.CopyTo(x, 0);

            Blas2.dGemv(utStore, 0, 1, rows, x, 0, 1, y, 0, 1, rows, rows);

            double minValue = tolerance * wStore[0];

            for (int i = 0; i < wStore.Length; i++)
            {
                double w = wStore[i];
                if (w > minValue)
                {
                    y[i] /= w;
                }
                else
                {
                    y[i] = 0.0;
                }
            }

            Array.Clear(x, 0, rows);
            Blas2.dGemv(vStore, 0, 1, rows, y, 0, 1, x, 0, 1, rows, rows);

            return(new ColumnVector(x, rows));
        }