/// <summary>
        /// Calculates the inverse of the original matrix and returns it in a new <see cref="SymmetricMatrix"/> instance.
        /// WARNING: If <paramref name="inPlace"/> is set to true, this object must not be used again, otherwise a
        /// <see cref="InvalidOperationException"/> will be thrown.
        /// </summary>
        /// <param name="inPlace">False, to copy the internal factorization data before inversion. True, to overwrite it with
        ///     the inverse matrix, thus saving memory and time. However, that will make this object unusable, so you MUST NOT
        ///     call any other members afterwards.</param>
        public SymmetricMatrix Invert(bool inPlace)
        {
            CheckOverwritten();

            // Call LAPACK
            double[] inverse; // if A is posdef, so is inv(A)
            if (inPlace)
            {
                inverse       = data;
                IsOverwritten = true;
            }
            else
            {
                inverse = new double[data.Length];
                Array.Copy(data, inverse, data.Length);
            }
            int indefiniteMinorIdx = LapackLinearEquations.Dpptri(StoredTriangle.Upper, Order, inverse, 0);

            // Check LAPACK execution
            if (indefiniteMinorIdx < 0)
            {
                return(SymmetricMatrix.CreateFromPackedColumnMajorArray(inverse, Order, DefiniteProperty.PositiveDefinite));
            }
            else  // this should not have happened
            {
                throw new IndefiniteMatrixException($"The entry ({indefiniteMinorIdx}, {indefiniteMinorIdx}) of the factor U"
                                                    + " is 0 and the inverse could not be computed.");
            }
        }
Example #2
0
        /// <summary>
        /// Calculates the inverse of the original matrix and returns it in a new <see cref="Matrix"/> instance.
        /// WARNING: If <paramref name="inPlace"/> is set to true, this object must not be used again, otherwise a
        /// <see cref="InvalidOperationException"/> will be thrown.
        /// </summary>
        /// <param name="inPlace">False, to copy the internal factorization data before inversion. True, to overwrite it with
        ///     the inverse matrix, thus saving memory and time. However, that will make this object unusable, so you MUST NOT
        ///     call any other members afterwards.</param>
        public Matrix Invert(bool inPlace)
        {
            CheckOverwritten();

            // Call LAPACK
            double[] inverse;
            if (inPlace)
            {
                inverse       = data;
                IsOverwritten = true;
            }
            else
            {
                inverse = new double[data.Length];
                Array.Copy(data, inverse, data.Length);
            }
            int indefiniteMinorIdx = LapackLinearEquations.Dpotri(StoredTriangle.Upper, Order, inverse, 0, Order);

            Conversions.CopyUpperToLowerColMajor(inverse, Order); //So far the lower triangle was the same as the original matrix

            // Check LAPACK execution
            if (indefiniteMinorIdx < 0)
            {
                return(Matrix.CreateFromArray(inverse, Order, Order, false));
            }
            else  // this should not have happened
            {
                throw new IndefiniteMatrixException($"The entry ({indefiniteMinorIdx}, {indefiniteMinorIdx}) of the factor U"
                                                    + " is 0 and the inverse could not be computed.");
            }
        }
        /// <summary>
        /// Calculates the inverse of the original square matrix and returns it in a new <see cref="Matrix"/> instance. This
        /// only works if the original matrix is not singular, which can be checked through <see cref="IsSingular"/>.
        /// WARNING: If <paramref name="inPlace"/> is set to true, this object must not be used again, otherwise a
        /// <see cref="InvalidOperationException"/> will be thrown.
        /// </summary>
        /// <param name="inPlace">False, to copy the internal factorization data before inversion. True, to overwrite it with
        ///     the inverse matrix, thus saving memory and time. However, that will make this object unusable, so you MUST NOT
        ///     call any other members afterwards.</param>
        /// <exception cref="SingularMatrixException">Thrown if the original matrix is not invertible.</exception>
        public Matrix Invert(bool inPlace)
        {
            // Check if the matrix is suitable for inversion
            CheckOverwritten();
            if (IsSingular)
            {
                throw new SingularMatrixException("The factorization has been completed, but U is singular."
                                                  + $" The first zero pivot is U[{firstZeroPivot}, {firstZeroPivot}] = 0.");
            }

            // Copy if the matrix if the inversion will be in place.
            double[] inverse;
            if (inPlace)
            {
                inverse       = lowerUpper;
                IsOverwritten = true;
            }
            else
            {
                inverse = new double[lowerUpper.Length];
                Array.Copy(lowerUpper, inverse, lowerUpper.Length);
            }

            // Call LAPACK
            int firstZeroDiagonal = LapackLinearEquations.Dgetri(Order, inverse, 0, Order, rowExchanges, 0, pivotTolerance);

            if (firstZeroDiagonal > 0) // This should not have happened though
            {
                throw new SingularMatrixException($"The ({firstZeroDiagonal}, {firstZeroDiagonal}) element of factor U is zero,"
                                                  + " U is singular and the inversion could not be completed.");
            }

            return(Matrix.CreateFromArray(inverse, Order, Order, false));
        }
 /// <summary>Initializes a new instance of the <see cref="LapackNativeWrapper" /> class.
 /// </summary>
 internal LapackNativeWrapper()
 {
     Name              = LongName = new IdentifierString("LAPACK");
     LinearEquations   = new LapackLinearEquations(this);
     EigenValues       = new LapackEigenvalues(this);
     AuxiliaryRoutines = new LapackAuxiliaryUtilityRoutines(this);
 }
        /// <summary>
        /// Calculates the LUP factorization of a square matrix, such that A = P * L * U. Requires an extra O(n) available
        /// memory, where n is the <paramref name="order"/>.
        /// </summary>
        /// <param name="order">The number of rows/columns of the square matrix.</param>
        /// <param name="matrix">The internal buffer stroring the matrix entries in column major order. It will
        ///     be overwritten.</param>
        /// <param name="pivotTolerance">If a diagonal entry (called pivot) is &lt;= <paramref name="pivotTolerance"/> it will be
        ///     considered as zero and a permutation will be used to find a non-zero pivot (the process is called pivoting).
        ///     </param>
        public static LUFactorization Factorize(int order, double[] matrix,
                                                double pivotTolerance = LUFactorization.PivotTolerance)
        {
            int[] rowExchanges   = new int[order];
            int   firstZeroPivot = LapackLinearEquations.Dgetrf(order, order, matrix, 0, order, rowExchanges, 0, pivotTolerance);

            return(new LUFactorization(order, matrix, rowExchanges, firstZeroPivot, firstZeroPivot > 0, pivotTolerance));
        }
        /// <summary>
        /// See <see cref="ITriangulation.SolveLinearSystem(Vector, Vector)"/>.
        /// </summary>
        /// <exception cref="LapackException">Thrown if the call to LAPACK fails due to invalid arguments.</exception>
        public void SolveLinearSystem(Vector rhs, Vector solution)
        {
            CheckOverwritten();
            Preconditions.CheckSystemSolutionDimensions(Order, rhs.Length);
            Preconditions.CheckMultiplicationDimensions(Order, solution.Length);

            // Call LAPACK
            solution.CopyFrom(rhs);
            int numRhs      = 1;     // rhs is a n x nRhs matrix, stored in b
            int leadingDimB = Order; // column major ordering: leading dimension of b is n

            LapackLinearEquations.Dpptrs(StoredTriangle.Upper, Order, numRhs, data, 0, solution.RawData, 0, leadingDimB);
        }
Example #7
0
        /// <summary>
        /// Solves a series of linear systems L * L^T * x = b (or L * D * L^T * x = b), where L is the lower triangular factor
        /// (and D the diagonal factor) of the Cholesky factorization: A = L * L^T (or A = L * D * L^T).
        /// </summary>
        /// <param name="rhsVectors">
        /// A matrix whose columns are the right hand side vectors b of the linear systems. Constraints:
        /// <paramref name="rhsVectors"/>.<see cref="IIndexable2D.NumRows"/> == this.<see cref="Order"/>.
        /// </param>
        /// <exception cref="NonMatchingDimensionsException">
        /// Thrown if <paramref name="rhsVectors"/> violates the described constraints.
        /// </exception>
        /// <exception cref="AccessViolationException">
        /// Thrown if the unmanaged memory that holds the factorization data has been released.
        /// </exception>
        /// <exception cref="SuiteSparseException">Thrown if the call to SuiteSparse library fails.</exception>
        public Matrix SolveLinearSystems(Matrix rhs)
        {
            CheckOverwritten();
            Preconditions.CheckSystemSolutionDimensions(Order, rhs.NumRows);
            //Preconditions.CheckMultiplicationDimensions(Order, solution.NumColumns);

            // Back & forward substitution using LAPACK
            Matrix solution    = rhs.Copy();
            int    numRhs      = rhs.NumColumns; // rhs is a n x nRhs matrix, stored in b
            int    leadingDimB = Order;          // column major ordering: leading dimension of b is n

            LapackLinearEquations.Dpotrs(StoredTriangle.Upper, Order, numRhs, data, 0, Order, solution.RawData, 0,
                                         leadingDimB);
            return(solution);
        }
Example #8
0
        /// <summary>
        /// Calculates the cholesky factorization of a symmetric positive definite matrix, such that A = transpose(U) * U.
        /// </summary>
        /// <param name="order">The number of rows/columns of the square matrix.</param>
        /// <param name="matrix">The entries of the original matrix in full column major layout.</param>
        /// <exception cref="IndefiniteMatrixException">Thrown if the matrix is not symmetric positive definite.</exception>
        public static CholeskyFull Factorize(int order, double[] matrix)
        {
            // Call LAPACK
            int indefiniteMinorIdx = LapackLinearEquations.Dpotrf(StoredTriangle.Upper, order, matrix, 0, order);

            // Check LAPACK execution
            if (indefiniteMinorIdx < 0)
            {
                return(new CholeskyFull(order, matrix));
            }
            else
            {
                string msg = $"The leading minor of order {indefiniteMinorIdx} (and therefore the matrix itself) is not"
                             + " positive-definite, and the factorization could not be completed.";
                throw new IndefiniteMatrixException(msg);
            }
        }
        /// <summary>Initializes a new instance of the <see cref="LapackNativeWrapper" /> class.
        /// </summary>
        public LapackNativeWrapper()
        {
            Name            = LongName = new IdentifierString("LAPACK");
            LinearEquations = new LapackLinearEquations(
                MatrixConditionalNumbers.Create(),
                MatrixEquilibration.Create(),
                MatrixFactorization.Create(),
                MatrixInversion.Create(),
                Solver.Create(),
                ErrorEstimationSolver.Create());

            EigenValues = new LapackEigenvalues(
                GeneralizedNonsymmetricEigenvalueProblems.Create(),
                GeneralizedSymmetricEigenvalueProblems.Create(),
                NonSymmetricEigenvalueProblems.Create(),
                SymmetricEigenvalueProblems.Create(),
                SingularValueDecomposition.Create(),
                GeneralizedSingularValueDecomposition.Create(),
                LinearLeastSquaresProblems.Create());

            AuxiliaryRoutines = new LapackAuxiliaryUtilityRoutines(AuxiliaryUtilityRoutines.Create());
        }
Example #10
0
        /// <summary>Initializes the <see cref="LAPACK"/> class.
        /// </summary>
        /// <remarks>This constructor takes into account the Managed Extensibility Framework (MEF) with respect to <see cref="LowLevelMathConfiguration"/>.</remarks>
        static LAPACK()
        {
            ILibrary lapack = null;

            try
            {
                lapack = LowLevelMathConfiguration.LAPACK.CreateFromConfigurationFile();
                if (lapack == null)
                {
                    lapack = LowLevelMathConfiguration.LAPACK.Libraries.Standard;  // can be null, i.e. fallback solution is perhaps not available
                    Logger.Stream.LogCritical(LowLevelMathConfigurationResources.LogFileMessageConfigFileUseDefaultImplementation, "LAPACK");
                }
            }
            catch (Exception e)  // thrown of Exceptions in static constructors should be avoided
            {
                Logger.Stream.LogError(e, LowLevelMathConfigurationResources.LogFileMessageCorruptConfigFile);

                lapack = LowLevelMathConfiguration.LAPACK.Libraries.Standard;
                Logger.Stream.LogError(LowLevelMathConfigurationResources.LogFileMessageConfigFileUseDefaultImplementation, "LAPACK");
            }
            EigenValues       = lapack.EigenValues;
            LinearEquations   = lapack.LinearEquations;
            AuxiliaryRoutines = lapack.AuxiliaryRoutines;
        }
        /// <summary>
        /// See <see cref="ITriangulation.SolveLinearSystem(Vector, Vector)"/>.
        /// </summary>
        /// <remarks>
        /// This method is not garanteed to succeed. A singular matrix can be factorized as A=P*L*U, but not all linear systems
        /// with a singular matrix can be solved.
        /// </remarks>
        /// <exception cref="SingularMatrixException">Thrown if the original matrix is not invertible.</exception>
        /// <exception cref="LapackException">Thrown if the call to LAPACK fails due to invalid arguments.</exception>
        public void SolveLinearSystem(Vector rhs, Vector solution)
        {
            CheckOverwritten();
            Preconditions.CheckSystemSolutionDimensions(Order, rhs.Length);
            Preconditions.CheckMultiplicationDimensions(Order, solution.Length);

            // Check if the matrix is singular first
            if (IsSingular)
            {
                string msg = "The factorization has been completed, but U is singular."
                             + $" The first zero pivot is U[{firstZeroPivot}, {firstZeroPivot}] = 0.";
                throw new SingularMatrixException(msg);
            }

            // Back & forward substitution using LAPACK
            int n = Order;

            solution.CopyFrom(rhs); //double[] solution = rhs.CopyToArray();
            int numRhs      = 1;    // rhs is a n x nRhs matrix, stored in b
            int leadingDimB = n;    // column major ordering: leading dimension of b is n

            LapackLinearEquations.Dgetrs(TransposeMatrix.NoTranspose, n, numRhs, lowerUpper, 0, n, rowExchanges, 0,
                                         solution.RawData, 0, leadingDimB);
        }