Skip to content

invenia/PDMatsExtras.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PDMatsExtras

Build Status Code Style: Blue ColPrac: Contributor's Guide on Collaborative Practices for Community Packages

This is a package for extra Positive (Semi-) Definated Matrix types. It is an extension to PDMats.jl.

It probably wouldn't exist, except Distributions.jl is currently very tied to the idea that the type of a covariance matrix should subtype AbstractPDMat. There is an issue open to change that. When that is resolve the matrix defined here may well move elsewhere, or cease to be required.

The Matrixes

PSDMat

A Positive Semi-Definite Matrix. It still subtypes AbstractPDMat. It's not quite as nice to work with as a truely positive definite matrix, since the math doesn't work out so well. But this is able to represent all covariences -- which must be positive semi-definate. You might not like the consequences,

julia> using LinearAlgebra, PDMatsExtras

julia> X = Float64[
               10   -9   2   4
               -9    8  -1  -4
                2   -1   1   1
                4   -4   1   6
           ];

julia> isposdef(X)
false

julia> PSDMat(X)
4×4 PSDMat{Float64, Matrix{Float64}}:
 10.0  -9.0   2.0   4.0
 -9.0   8.0  -1.0  -4.0
  2.0  -1.0   1.0   1.0
  4.0  -4.0   1.0   6.0


julia> # can also construct from a pivoted cholesky, even one of a rank deficient matrix (like this one)

julia> PSDMat(cholesky(X, Val(true); check=false))
4×4 PSDMat{Float64, Matrix{Float64}}:
 10.0  -9.0       2.0   4.0
 -9.0   9.26923  -1.0  -4.0
  2.0  -1.0       1.0   1.0
  4.0  -4.0       1.0   6.0

WoodburyPDMat

It is a positive definite Woodbury matrix. This is a special case of the Symmetric Woodbury Matrix (see WoodburyMatrices.jl's SymWoodbury type) which is given by A*D*A' + S for S and D being diagonal, which has the additional requirement that the diagonal matrices are also non-negative.

julia> using LinearAlgebra, PDMatsExtras

julia> A = Float64[
         2.0  2.0  -8.0   5.0  -1.0   2.0   6.0
         2.0  7.0  -1.0  -5.0  -4.0   8.0   7.0
        -2.0  9.0  -9.0  -5.0   9.0  -5.0  -3.0
         3.0  4.0  -6.0  -4.0   3.0  -3.0  -3.0
       ];

julia> D = Diagonal(Float64[1, 2, 3, 2, 2, 1, 5]);

julia> S = Diagonal(Float64[4, 2, 3, 6]);

julia> W = WoodburyPDMat(A, D, S)
4×4 WoodburyPDMat{Float64,Array{Float64,2},Diagonal{Float64,Array{Float64,1}},Diagonal{Float64,Array{Float64,1}}}:
 444.0  240.0   80.0   24.0
 240.0  498.0  -18.0  -33.0
  80.0  -18.0  694.0  382.0
  24.0  -33.0  382.0  259.0

julia> A*D*A' + S
4×4 Array{Float64,2}:
 444.0  240.0   80.0   24.0
 240.0  498.0  -18.0  -33.0
  80.0  -18.0  694.0  382.0
  24.0  -33.0  382.0  259.0