/// <summary>
        /// Returns the inverse of this lower triangular matrix
        /// </summary>
        /// <returns></returns>
        public new LowerTriangularMatrix Inverse()
        {
            LowerTriangularMatrix L = new LowerTriangularMatrix(rows, cols);

            L.SetToInverse(this);
            return(L);
        }
        /// <summary>
        /// Creates a full clone of this instance (including the data)
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            LowerTriangularMatrix result = new LowerTriangularMatrix(rows, cols);

            result.SetTo(this);
            return(result);
        }
        /// <summary>
        /// Return the transpose of this upper triangular matrix
        /// </summary>
        /// <returns></returns>
        public new LowerTriangularMatrix Transpose()
        {
            LowerTriangularMatrix L = new LowerTriangularMatrix(cols, rows);

            L.SetToTranspose(this);
            return(L);
        }
        /// <summary>
        /// Gets the Cholesky decomposition of the matrix (L*L' = A), replacing its contents.
        /// </summary>
        /// <param name="isPosDef">True if <c>this</c> is positive definite, otherwise false.</param>
        /// <returns>The Cholesky decomposition L.  If <c>this</c> is positive semidefinite,
        /// then L will satisfy L*L' = A.
        /// Otherwise, L will only approximately satisfy L*L' = A.</returns>
        /// <remarks>
        /// <c>this</c> must be symmetric, but need not be positive definite.
        /// </remarks>
        public LowerTriangularMatrix CholeskyInPlace(out bool isPosDef)
        {
            LowerTriangularMatrix L = new LowerTriangularMatrix(rows, cols, data);

#if LAPACK
            isPosDef = Lapack.CholeskyInPlace(this);
#else
            isPosDef = L.SetToCholesky(this);
#endif
            return(L);
        }
Exemple #5
0
        public static void Normal(Vector mean, PositiveDefiniteMatrix variance, Vector result)
        {
            LowerTriangularMatrix L = new LowerTriangularMatrix(variance.Rows, variance.Rows);
            bool isPosDef           = L.SetToCholesky(variance);

            if (!isPosDef)
            {
                throw new ArgumentException("PROB.Random.Normal(Vector,Matrix,Vector): variance must be positive definite", nameof(variance));
            }

            NormalChol(mean, L, result);
        }
Exemple #6
0
 public static void Wishart(double a, LowerTriangularMatrix result)
 {
     Assert.IsTrue(result.Rows == result.Cols);
     for (int i = 0; i < result.Rows; ++i)
     {
         for (int j = 0; j < i; ++j)
         {
             result[i, j] = Normal() * MMath.SqrtHalf;
             result[j, i] = 0;
         }
         result[i, i] = System.Math.Sqrt(Gamma(a - i * 0.5));
     }
 }
Exemple #7
0
 /// <summary>
 /// Sets b to inv(A)*b.
 /// </summary>
 /// <param name="b"></param>
 /// <param name="A"></param>
 public static void PredivideBy(DenseVector b, LowerTriangularMatrix A)
 {
     Assert.IsTrue(A.Rows == A.Cols);
     Assert.IsTrue(A.Rows == b.Count);
     // Lapack is column-major, so we tell it that A is upper triangular and transposed
     char side = 'L', uplo = 'U', trans = 'T', diag = 'N';
     double alpha = 1;
     ptrdiff_t m = b.Count, n = 1;
     fixed (double* sA = A.SourceArray, sB = b.SourceArray) {
         double* pA = sA, pB = sB;
         dtrsm(&side, &uplo, &trans, &diag, &m, &n, &alpha, pA, &m, pB, &m);
     }
 }
Exemple #8
0
        public static void NormalP(Vector mean, PositiveDefiniteMatrix precision, Vector result)
        {
            LowerTriangularMatrix L = new LowerTriangularMatrix(precision.Rows, precision.Rows);
            bool isPosDef           = L.SetToCholesky(precision);

            if (!isPosDef)
            {
                throw new ArgumentException("PROB.Random.NormalP(Vector,Matrix,Vector): precision must be positive definite", nameof(precision));
            }
            UpperTriangularMatrix U = UpperTriangularMatrix.TransposeInPlace(L);

            NormalPChol(mean, U, result);
        }
Exemple #9
0
 /// <summary>
 /// Sets B to A'\B.
 /// </summary>
 /// <param name="B"></param>
 /// <param name="A"></param>
 public static void PredivideByTranspose(Matrix B, LowerTriangularMatrix A)
 {
     Assert.IsTrue(A.Rows == A.Cols);
     Assert.IsTrue(A.Rows == B.Rows);
     Assert.IsTrue(!object.ReferenceEquals(B, A));
     // Lapack is column-major, so we tell it that A is upper triangular and switch sides:
     // inv(A)*B = (B'*inv(A'))'
     char side = 'R', uplo = 'U', trans = 'T', diag = 'N';
     double alpha = 1;
     ptrdiff_t m = B.Cols, n = B.Rows;
     fixed (double* sA = A.SourceArray, sB = B.SourceArray) {
         double* pA = sA, pB = sB;
         dtrsm(&side, &uplo, &trans, &diag, &m, &n, &alpha, pA, &n, pB, &m);
     }
 }
Exemple #10
0
        public static void NormalChol(Vector mean, LowerTriangularMatrix varChol, Vector result)
        {
            if (ReferenceEquals(mean, result))
            {
                throw new ArgumentException("mean and result are the same object");
            }
            Vector temp = Vector.Zero(result.Count);

            for (int i = 0; i < result.Count; i++)
            {
                temp[i] = Normal();
            }
            result.SetToProduct(varChol, temp);
            result.SetToSum(mean, result);
            // result = mean + varChol*N(0,1)
        }
        /// <summary>
        /// Sets this positive-definite matrix to inverse of a given positive-definite matrix
        /// where a lower triangular workspace is passed.
        /// </summary>
        /// <param name="A">A symmetric positive-definite matrix, same size as <c>this</c>.  Can be the same object as <c>this</c>.</param>
        /// <param name="L">A workspace, same size as <paramref name="A"/>.</param>
        /// <returns><c>this</c></returns>
        /// <exception cref="PositiveDefiniteMatrixException">If <paramref name="A"/> is not positive definite.</exception>
        public PositiveDefiniteMatrix SetToInverse(PositiveDefiniteMatrix A, LowerTriangularMatrix L)
        {
            CheckCompatible(L, nameof(L));
            // Algorithm:
            // A = L*L'
            // inv(A) = inv(L')*inv(L)
            bool isPD = L.SetToCholesky(A);

            if (!isPD)
            {
                throw new PositiveDefiniteMatrixException();
            }
            L.SetToInverse(L);
            SetToOuterTranspose(L);
            return(this);
        }
 public UpperTriangularMatrix GetsTranspose(LowerTriangularMatrix L)
 {
     if (rows != L.Cols || cols != L.Rows)
     {
         throw new ArgumentException("Output matrix is not compatible with the transpose", "that");
     }
     L.CheckLowerTriangular();
     // lower triangle of this is assumed to be zero
     for (int i = 0; i < rows; ++i)
     {
         for (int j = i; j < cols; ++j)
         {
             this[i, j] = L[j, i];
         }
     }
     CheckUpperTriangular();
     return(this);
 }
        /// <remarks>U is no longer a valid upper triangular matrix.</remarks>
        public static LowerTriangularMatrix TransposeInPlace(UpperTriangularMatrix U)
        {
            U.CheckUpperTriangular();
            LowerTriangularMatrix L = new LowerTriangularMatrix(U.Cols, U.Rows,
                                                                U.SourceArray, U.Start);

            Assert.IsTrue(L.Rows == L.Cols);
            for (int i = 0; i < L.Rows; ++i)
            {
                for (int j = 0; j < i; ++j)
                {
                    L[i, j] = L[j, i];
                    L[j, i] = 0;
                }
            }
            L.CheckLowerTriangular();
            return(L);
        }
        /// <summary>
        /// Transposes a given lower triangular matrix in place.
        /// </summary>
        /// <param name="L">Matrix to transpose.  Contents are corrupted on exit.</param>
        /// <returns>An upper triangular wrapper of L's source array.</returns>
        /// <remarks>L is no longer a valid lower triangular matrix.</remarks>
        public static UpperTriangularMatrix TransposeInPlace(LowerTriangularMatrix L)
        {
            L.CheckLowerTriangular();
            UpperTriangularMatrix U = new UpperTriangularMatrix(L.Cols, L.Rows,
                                                                L.SourceArray);

            Assert.IsTrue(U.Rows == U.Cols);
            for (int i = 0; i < U.Rows; ++i)
            {
                for (int j = i + 1; j < U.Cols; ++j)
                {
                    U[i, j] = U[j, i];
                    U[j, i] = 0;
                }
            }
            U.CheckUpperTriangular();
            return(U);
        }
        /// <summary>
        /// Modifies <c>this</c> to be the inverse of A.
        /// </summary>
        /// <param name="A">Can be the same object as <c>this</c></param>
        public void SetToInverse(LowerTriangularMatrix A)
        {
#if LAPACK
            if (object.ReferenceEquals(this, A))
            {
                A = (LowerTriangularMatrix)A.Clone();
            }
            this.SetToIdentity();
            Lapack.PredivideBy(this, A);
#else
            // Reference: Golub and van Loan (1996)
            Assert.IsTrue(A.Rows == A.Cols);
            Assert.IsTrue(A.Rows == this.Rows);
            for (int k = 0; k < rows; k++)
            {
                if (A[k, k] == 0)
                {
                    throw new MatrixSingularException(A);
                }
            }
            for (int j = 0; j < cols; j++)
            {
                int index1 = j;
                // k < j case
                for (int k = 0; k < j; k++)
                {
                    //B[k, j] = 0.0;
                    data[index1] = 0.0;
                    index1      += cols;
                }
                // k == j case
                int    index2 = j + j * cols;
                double v      = 1.0 / A.data[index2];
                data[index1] = v;
                for (int i = j + 1; i < rows; i++)
                {
                    // B[i, j] = -v * A[i, j];
                    index1      += cols;
                    index2      += cols;
                    data[index1] = -v * A.data[index2];
                }
                // k > j case
                for (int k = j + 1; k < rows; k++)
                {
                    index1 = j + k * cols;
                    index2 = k + k * cols;
                    if (data[index1] != 0)
                    {
                        //double u = B[k,j]/A[k,k];
                        //B[k, j] = u;
                        // TM: this style of indexing may look ugly but it runs much faster
                        double u = data[index1] / A.data[index2];
                        data[index1] = u;
                        for (int i = k + 1; i < rows; i++)
                        {
                            // B[i, j] -= u * A[i, k];
                            index1       += cols;
                            index2       += cols;
                            data[index1] -= u * A.data[index2];
                        }
                    }
                }
            }
#endif
        }
        public bool SetToCholesky(Matrix A)
        {
            A.CheckSymmetry("A");
#if LAPACK
            SetTo(A);
            bool isPosDef = Lapack.CholeskyInPlace(this);
#else
            CheckCompatible(A, "A");

            bool isPosDef           = true;
            LowerTriangularMatrix L = this;
            // compute the Cholesky factor
            // Reference: Golub and van Loan (1996)
            for (int i = 0; i < A.Cols; i++)
            {
                // upper triangle
                for (int j = 0; j < i; j++)
                {
                    L[j, i] = 0;
                }
                // lower triangle
                for (int j = i; j < A.Rows; j++)
                {
                    double sum    = A[i, j];
                    int    index1 = i * cols;
                    int    index2 = j * cols;
                    for (int k = 0; k < i; k++)
                    {
                        //sum -= L[i, k] * L[j, k];
                        sum -= data[index1++] * data[index2++];
                    }
                    if (i == j)
                    {
                        // diagonal entry
                        if (sum <= 0)
                        {
                            isPosDef = false;
                            L[i, i]  = 0;
                        }
                        else
                        {
                            L[i, i] = System.Math.Sqrt(sum);
                        }
                    }
                    else
                    {
                        // off-diagonal entry
                        if (L[i, i] > 0)
                        {
                            L[j, i] = sum / L[i, i];
                        }
                        else
                        {
                            L[j, i] = 0;
                        }
                    }
                }
            }
            CheckLowerTriangular();
#endif
            return(isPosDef);
        }
        /// <summary>
        /// Returns the natural logarithm of the determinant of this positive-definite matrix.
        /// </summary>
        /// <param name="ignoreInfinity">If true, +infinity on the diagonal is treated as 1.</param>
        /// <returns>The log-determinant of <c>this</c>.</returns>
        public double LogDeterminant(bool ignoreInfinity = false)
        {
            LowerTriangularMatrix L = new LowerTriangularMatrix(rows, cols);

            return(LogDeterminant(L, ignoreInfinity));
        }
 public double LogDeterminant(LowerTriangularMatrix L, bool ignoreInfinity = false)
 {
     L.SetToCholesky(this);
     return(2 * L.LogDeterminant(ignoreInfinity));
 }