Skip to content

Commit

Permalink
Deprecate dim (#170)
Browse files Browse the repository at this point in the history
* Deprecate `dim`

* Update README.md
  • Loading branch information
devmotion authored Jun 25, 2022
1 parent 8d88c15 commit a1bf9fb
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 63 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "PDMats"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.13"
version = "0.11.14"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
12 changes: 2 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,10 @@ PDSparseMat(chol) # with the Cholesky factorization

## Common interface

All subtypes of `AbstractPDMat` share the same API, *i.e.* with the same set of methods to operate on their instances. These methods are introduced below, where `a` is an instance of a subtype of `AbstractPDMat` to represent a positive definite matrix, `x` be a column vector or a matrix with `size(x,1) == dim(a)`, and `c` be a positive real value.
All subtypes of `AbstractPDMat` share the same API, *i.e.* with the same set of methods to operate on their instances. These methods are introduced below, where `a` is an instance of a subtype of `AbstractPDMat` to represent a positive definite matrix, `x` be a column vector or a matrix with `size(x,1) == size(a, 1) == size(a, 2)`, and `c` be a positive real value.

```julia

dim(a) # return the dimension of `a`.
# Let `a` represent a d x d matrix, then `dim(a)` returns d.

size(a) # return the size tuple of `a`, i.e. `(dim(a), dim(a))`.
size(a) # return the size of `a`.

size(a, i) # return the i-th dimension of `a`.

Expand Down Expand Up @@ -214,7 +210,6 @@ For ease of composability, some of these functions have generic fallbacks define
These fallbacks may not be as fast as the methods specializaed for `AbstractPDMat`s, but they let you more easily swap out types.
While in theory all of them can be defined, at present only the following subset has:

- `dim`
- `whiten`, `whiten!`
- `unwhiten`, `unwhiten!`
- `quad`, `quad!`
Expand All @@ -227,12 +222,9 @@ PRs to implement more generic fallbacks are welcome.
In some situation, it is useful to define a customized subtype of `AbstractPDMat` to capture positive definite matrices with special structures. For this purpose, one has to define a subset of methods (as listed below), and other methods will be automatically provided.

```julia

# Let `M` be the name of the subtype, then the following methods need
# to be implemented for `M`:

dim(a::M) # return the dimension of `a`

Matrix(a::M) # return a copy of the matrix in full form, of type
# `Matrix{eltype(M)}`.

Expand Down
4 changes: 2 additions & 2 deletions src/addition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ end

# between pdmat and uniformscaling (multiple of identity)

+(a::AbstractPDMat, b::UniformScaling) = a + ScalMat(dim(a), b.λ)
+(a::UniformScaling, b::AbstractPDMat) = ScalMat(dim(b), a.λ) + b
+(a::AbstractPDMat, b::UniformScaling) = a + ScalMat(a.dim, b.λ)
+(a::UniformScaling, b::AbstractPDMat) = ScalMat(b.dim, a.λ) + b

pdadd(a::PDMat, b::AbstractPDMat, c::Real) = PDMat(a.mat + Matrix(b * c))
pdadd(a::PDiagMat, b::AbstractPDMat, c::Real) = PDMat(_adddiag!(Matrix(b * c), a.diag, one(c)))
Expand Down
2 changes: 2 additions & 0 deletions src/deprecates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ using Base: @deprecate

@deprecate ScalMat(d::Int, x::Real, inv_x::Real) ScalMat(d, x)
@deprecate PDiagMat(v::AbstractVector, inv_v::AbstractVector) PDiagMat(v)

@deprecate dim(a::AbstractMatrix) LinearAlgebra.checksquare(a)
15 changes: 3 additions & 12 deletions src/generics.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
# Generic functions (on top of the type-specific implementations)

## Basic functions
Base.size(a::AbstractPDMat) = (dim(a), dim(a))
Base.size(a::AbstractPDMat, i::Integer) = 1 <= i <= 2 ? dim(a) : 1
Base.length(a::AbstractPDMat) = abs2(dim(a))

function dim(a::AbstractMatrix)
@check_argdims size(a, 1) == size(a, 2)
return size(a, 1)
end

## arithmetics

pdadd!(r::Matrix, a::Matrix, b::AbstractPDMat{T}) where {T<:Real} = pdadd!(r, a, b, one(T))
Expand All @@ -31,6 +21,7 @@ Base.kron(A::AbstractPDMat, B::AbstractPDMat) = PDMat(kron(Matrix(A), Matrix(B))
# LinearAlgebra
LinearAlgebra.isposdef(::AbstractPDMat) = true
LinearAlgebra.ishermitian(::AbstractPDMat) = true
LinearAlgebra.checksquare(a::AbstractPDMat) = size(a, 1)

## whiten and unwhiten

Expand Down Expand Up @@ -96,7 +87,7 @@ If `x` is a vector the quadratic form is `x' * a * x`. If `x` is a matrix
the quadratic form is applied column-wise.
"""
function quad(a::AbstractMatrix{T}, x::AbstractMatrix{S}) where {T<:Real, S<:Real}
@check_argdims dim(a) == size(x, 1)
@check_argdims LinearAlgebra.checksquare(a) == size(x, 1)
quad!(Array{promote_type(T, S)}(undef, size(x,2)), a, x)
end

Expand All @@ -123,7 +114,7 @@ the quadratic form is applied column-wise.
"""
invquad(a::AbstractMatrix, x::AbstractVecOrMat) = x' / a * x
function invquad(a::AbstractMatrix{T}, x::AbstractMatrix{S}) where {T<:Real, S<:Real}
@check_argdims dim(a) == size(x, 1)
@check_argdims LinearAlgebra.checksquare(a) == size(x, 1)
invquad!(Array{promote_type(T, S)}(undef, size(x,2)), a, x)
end

Expand Down
22 changes: 11 additions & 11 deletions src/pdiagmat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Base.convert(::Type{AbstractArray{T}}, a::PDiagMat) where {T<:Real} = convert(PD

### Basics

dim(a::PDiagMat) = a.dim
Base.size(a::PDiagMat) = (a.dim, a.dim)
Base.Matrix(a::PDiagMat) = Matrix(Diagonal(a.diag))
LinearAlgebra.diag(a::PDiagMat) = copy(a.diag)
LinearAlgebra.cholesky(a::PDiagMat) = cholesky(Diagonal(a.diag))
Expand All @@ -41,19 +41,19 @@ end

*(a::PDiagMat, c::Real) = PDiagMat(a.diag * c)
function *(a::PDiagMat, x::AbstractVector)
@check_argdims dim(a) == length(x)
@check_argdims a.dim == length(x)
return a.diag .* x
end
function *(a::PDiagMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
return a.diag .* x
end
function \(a::PDiagMat, x::AbstractVecOrMat)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
return x ./ a.diag
end
function /(x::AbstractVecOrMat, a::PDiagMat)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
# return matrix for 1-element vectors `x`, consistent with LinearAlgebra
return reshape(x, Val(2)) ./ permutedims(a.diag) # = (a' \ x')'
end
Expand All @@ -75,7 +75,7 @@ LinearAlgebra.sqrt(a::PDiagMat) = PDiagMat(map(sqrt, a.diag))
### whiten and unwhiten

function whiten!(r::StridedVector, a::PDiagMat, x::StridedVector)
n = dim(a)
n = a.dim
@check_argdims length(r) == length(x) == n
v = a.diag
for i = 1:n
Expand All @@ -85,7 +85,7 @@ function whiten!(r::StridedVector, a::PDiagMat, x::StridedVector)
end

function unwhiten!(r::StridedVector, a::PDiagMat, x::StridedVector)
n = dim(a)
n = a.dim
@check_argdims length(r) == length(x) == n
v = a.diag
for i = 1:n
Expand Down Expand Up @@ -142,25 +142,25 @@ end
### tri products

function X_A_Xt(a::PDiagMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
z = x .* sqrt.(permutedims(a.diag))
z * transpose(z)
end

function Xt_A_X(a::PDiagMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
z = x .* sqrt.(a.diag)
transpose(z) * z
end

function X_invA_Xt(a::PDiagMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
z = x ./ sqrt.(permutedims(a.diag))
z * transpose(z)
end

function Xt_invA_X(a::PDiagMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
z = x ./ sqrt.(a.diag)
transpose(z) * z
end
10 changes: 5 additions & 5 deletions src/pdmat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Base.convert(::Type{AbstractArray{T}}, a::PDMat{T}) where {T<:Real} = a

### Basics

dim(a::PDMat) = a.dim
Base.size(a::PDMat) = (a.dim, a.dim)
Base.Matrix(a::PDMat) = copy(a.mat)
LinearAlgebra.diag(a::PDMat) = diag(a.mat)
LinearAlgebra.cholesky(a::PDMat) = a.chol
Expand Down Expand Up @@ -63,25 +63,25 @@ LinearAlgebra.sqrt(A::PDMat) = PDMat(sqrt(Hermitian(A.mat)))
### tri products

function X_A_Xt(a::PDMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
z = x * chol_lower(a.chol)
return z * transpose(z)
end

function Xt_A_X(a::PDMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
z = chol_upper(a.chol) * x
return transpose(z) * z
end

function X_invA_Xt(a::PDMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
z = x / chol_upper(a.chol)
return z * transpose(z)
end

function Xt_invA_X(a::PDMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
z = chol_lower(a.chol) \ x
return transpose(z) * z
end
2 changes: 1 addition & 1 deletion src/pdsparsemat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Base.convert(::Type{PDSparseMat{T}}, a::PDSparseMat) where {T<:Real} = PDSparseM

### Basics

dim(a::PDSparseMat) = a.dim
Base.size(a::PDSparseMat) = (a.dim, a.dim)
Base.Matrix(a::PDSparseMat) = Matrix(a.mat)
LinearAlgebra.diag(a::PDSparseMat) = diag(a.mat)
LinearAlgebra.cholesky(a::PDSparseMat) = a.chol
Expand Down
24 changes: 12 additions & 12 deletions src/scalmat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Base.convert(::Type{AbstractArray{T}}, a::ScalMat) where {T<:Real} = convert(Sca

### Basics

dim(a::ScalMat) = a.dim
Base.size(a::ScalMat) = (a.dim, a.dim)
Base.Matrix(a::ScalMat) = Matrix(Diagonal(fill(a.value, a.dim)))
LinearAlgebra.diag(a::ScalMat) = fill(a.value, a.dim)
LinearAlgebra.cholesky(a::ScalMat) = cholesky(Diagonal(fill(a.value, a.dim)))
Expand Down Expand Up @@ -40,23 +40,23 @@ end
*(a::ScalMat, c::Real) = ScalMat(a.dim, a.value * c)
/(a::ScalMat, c::Real) = ScalMat(a.dim, a.value / c)
function *(a::ScalMat, x::AbstractVector)
@check_argdims dim(a) == length(x)
@check_argdims a.dim == length(x)
return a.value * x
end
function *(a::ScalMat, x::AbstractMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
return a.value * x
end
function \(a::ScalMat, x::AbstractVecOrMat)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
return x / a.value
end
function /(x::AbstractVecOrMat, a::ScalMat)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
# return matrix for 1-element vectors `x`, consistent with LinearAlgebra
return reshape(x, Val(2)) / a.value
end
Base.kron(A::ScalMat, B::ScalMat) = ScalMat( dim(A) * dim(B), A.value * B.value )
Base.kron(A::ScalMat, B::ScalMat) = ScalMat(A.dim * B.dim, A.value * B.value )

### Algebra

Expand All @@ -71,12 +71,12 @@ LinearAlgebra.sqrt(a::ScalMat) = ScalMat(a.dim, sqrt(a.value))
### whiten and unwhiten

function whiten!(r::StridedVecOrMat, a::ScalMat, x::StridedVecOrMat)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
_ldiv!(r, sqrt(a.value), x)
end

function unwhiten!(r::StridedVecOrMat, a::ScalMat, x::StridedVecOrMat)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
mul!(r, x, sqrt(a.value))
end

Expand All @@ -93,21 +93,21 @@ invquad!(r::AbstractArray, a::ScalMat, x::StridedMatrix) = colwise_sumsqinv!(r,
### tri products

function X_A_Xt(a::ScalMat, x::StridedMatrix)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
lmul!(a.value, x * transpose(x))
end

function Xt_A_X(a::ScalMat, x::StridedMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
lmul!(a.value, transpose(x) * x)
end

function X_invA_Xt(a::ScalMat, x::StridedMatrix)
@check_argdims dim(a) == size(x, 2)
@check_argdims a.dim == size(x, 2)
_rdiv!(x * transpose(x), a.value)
end

function Xt_invA_X(a::ScalMat, x::StridedMatrix)
@check_argdims dim(a) == size(x, 1)
@check_argdims a.dim == size(x, 1)
_rdiv!(transpose(x) * x, a.value)
end
2 changes: 1 addition & 1 deletion test/pdmtypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ using Test
@test d.diag === v
end

@testset "division of vectors (dim = 1)" begin
@testset "division of vectors (size (1, 1))" begin
A = rand(1, 1)
x = randn(1)
y = x / A
Expand Down
16 changes: 8 additions & 8 deletions test/testutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function test_pdmat(C, Cmat::Matrix;
)

d = size(Cmat, 1)
verbose >= 1 && printstyled("Testing $(typeof(C)) with dim = $d\n", color=:blue)
verbose >= 1 && printstyled("Testing $(typeof(C)) of size ($d, $d)\n", color=:blue)

pdtest_basics(C, Cmat, d, verbose)
pdtest_cmat(C, Cmat, cmat_eq, verbose)
Expand Down Expand Up @@ -64,7 +64,7 @@ _pdt(vb::Int, s) = (vb >= 2 && printstyled(" .. testing $s\n", color=:green))

function pdtest_basics(C, Cmat::Matrix, d::Int, verbose::Int)
_pdt(verbose, "dim")
@test dim(C) == d
@test @test_deprecated(dim(C)) == d

_pdt(verbose, "size")
@test size(C) == (d, d)
Expand Down Expand Up @@ -188,15 +188,15 @@ end

function pdtest_mul(C, Cmat::Matrix, verbose::Int)
n = 5
X = rand(eltype(C), dim(C), n)
X = rand(eltype(C), size(C, 1), n)
pdtest_mul(C, Cmat, X, verbose)
end


function pdtest_mul(C, Cmat::Matrix, X::Matrix, verbose::Int)
_pdt(verbose, "multiply")
d, n = size(X)
@assert d == dim(C)
@assert d == size(C, 1) == size(C, 2)
@assert size(Cmat) == size(C)
@test C * X Cmat * X

Expand All @@ -220,7 +220,7 @@ end
function pdtest_div(C, Imat::Matrix, X::Matrix, verbose::Int)
_pdt(verbose, "divide")
d, n = size(X)
@assert d == dim(C)
@assert d == size(C, 1) == size(C, 2)
@assert size(Imat) == size(C)
@test C \ X Imat * X
# Right division with Choleskyrequires https://github.com/JuliaLang/julia/pull/32594
Expand Down Expand Up @@ -273,7 +273,7 @@ end

function pdtest_triprod(C, Cmat::Matrix, Imat::Matrix, X::Matrix, verbose::Int)
d, n = size(X)
@assert d == dim(C)
@assert d == size(C, 1) == size(C, 2)
Xt = copy(transpose(X))

_pdt(verbose, "X_A_Xt")
Expand Down Expand Up @@ -303,7 +303,7 @@ function pdtest_whiten(C, Cmat::Matrix, verbose::Int)
Q = qr(convert(Array{eltype(C),2},randn(size(Cmat)))).Q
Y = Y * Q' # generate a matrix Y such that Y * Y' = C
@test Y * Y' Cmat
d = dim(C)
d = size(C, 1)

_pdt(verbose, "whiten")
Z = whiten(C, Y)
Expand Down Expand Up @@ -343,7 +343,7 @@ _randScalMat(T, n) = ScalMat(n, rand(T))
_randPDSparseMat(T, n) = (X = T.(sprand(n, 1, 0.5)); PDSparseMat(X * X' + LinearAlgebra.I))

function _pd_compare(A::AbstractPDMat, B::AbstractPDMat)
@test dim(A) == dim(B)
@test size(A) == size(B)
@test Matrix(A) Matrix(B)
@test cholesky(A).L cholesky(B).L
@test cholesky(A).U cholesky(B).U
Expand Down

2 comments on commit a1bf9fb

@devmotion
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/63117

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.11.14 -m "<description of version>" a1bf9fb2b3611d0c9b6cd9fc8d800a5412e430fb
git push origin v0.11.14

Please sign in to comment.