Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add keyword constructors #823

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
f1beb6b
demonstration of keyword constructors
simonbyrne Sep 19, 2018
ff8c4f1
more keyword constructors
simonbyrne Oct 24, 2018
0676a2b
more distributions
simonbyrne Jan 28, 2019
b578ce6
a few more
simonbyrne Jan 28, 2019
f7fc221
more
simonbyrne Jan 28, 2019
62ff08c
small fixes
simonbyrne Jan 28, 2019
99f6aae
more tweaks
simonbyrne Jan 28, 2019
1be2d75
fix deprecation
simonbyrne Jan 28, 2019
18bad93
fix more deprecations
simonbyrne Jan 28, 2019
d929d8e
another deprecation fix
simonbyrne Jan 28, 2019
b642530
more fixes
simonbyrne Jan 28, 2019
0c3d062
tweak version requirements
simonbyrne Jan 28, 2019
4208984
fix check args call
simonbyrne Jan 28, 2019
82de3fa
add LogNormal mean,std constructor
simonbyrne Jan 28, 2019
e1945b1
even more
simonbyrne Jan 29, 2019
ce1cbe9
add discrete distributions
simonbyrne Jan 29, 2019
d1eedf4
MvNormal
simonbyrne Feb 5, 2019
ea9f5ea
Merge branch 'master' into sb/keyword
simonbyrne Feb 14, 2019
b43e209
update Normal with alias syntax
simonbyrne Feb 14, 2019
1559083
tweak constructor docs
simonbyrne Feb 14, 2019
0f75676
use | instead of /
simonbyrne Feb 14, 2019
611c238
update some distrs
simonbyrne Feb 17, 2019
689ac8e
Merge remote-tracking branch 'origin/master' into sb/keyword
simonbyrne Feb 17, 2019
cbdf2e0
a few more
simonbyrne Feb 18, 2019
f383f9f
two more
simonbyrne Feb 18, 2019
05aaeb5
some more
simonbyrne Feb 18, 2019
264a211
finish continuous univariates
simonbyrne Feb 18, 2019
e8c278b
fix InverseGaussian
simonbyrne Feb 18, 2019
e1015c7
start on discrete
simonbyrne Feb 19, 2019
a3bf68b
a few more
simonbyrne Feb 19, 2019
2a39c36
finish discrete dists
simonbyrne Feb 20, 2019
1d68ae6
more updates
simonbyrne Feb 20, 2019
746aeea
fix defs
simonbyrne Feb 20, 2019
9b58f24
fix variable
simonbyrne Feb 20, 2019
49bb9a2
remove deprecated call
simonbyrne Feb 21, 2019
307d48b
tweak normal and wishart defs
simonbyrne Feb 21, 2019
92cf883
Merge branch 'master' into sb/keyword
simonbyrne Feb 26, 2019
35a8f21
fix closing parenthesis
matbesancon Feb 26, 2019
0f6e2ce
fix Wishart field name
simonbyrne Feb 26, 2019
047846d
fix some tests
matbesancon Feb 26, 2019
0d53426
fix more KW tests
matbesancon Feb 26, 2019
c25c9a8
fix first tests
matbesancon Feb 26, 2019
894b2eb
fix warnings
matbesancon Feb 26, 2019
d13e32b
update docs
simonbyrne Feb 26, 2019
e0247d5
Merge branch 'master' into sb/keyword
simonbyrne Mar 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions appveyor.yml → .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
environment:
matrix:
- julia_version: 0.7
- julia_version: 1
- julia_version: 1.0
- julia_version: 1.1
- julia_version: nightly

platform:
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ os:
- linux
- osx
julia:
- 0.7
- 1.0
- 1.1
- nightly
matrix:
allow_failures:
Expand Down
3 changes: 2 additions & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
julia 0.7
julia 1.0
PDMats 0.9.0
StatsFuns 0.8
StatsBase 0.23.0
QuadGK 0.1.1
SpecialFunctions 0.6.0
KeywordDispatch 0.3.0
simonbyrne marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions src/Distributions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import StatsBase: kurtosis, skewness, entropy, mode, modes,
import PDMats: dim, PDMat, invquad

using SpecialFunctions
using KeywordDispatch

export
# re-export Statistics
Expand Down
37 changes: 37 additions & 0 deletions src/deprecates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,43 @@ function BetaBinomial(n::Real, α::Real, β::Real)
BetaBinomial(Int(n), α, β)
end

Base.@deprecate Arcsine(b::Real) Arcsine(a=0,b=b)
Base.@deprecate Beta(α::Real) Beta(α=α, β=α)
Base.@deprecate BetaPrime(α::Real) BetaPrime(α=α, β=α)
Base.@deprecate Biweight(μ::Real) Biweight(μ=μ)
Base.@deprecate Cauchy(μ::Real) Cauchy(μ=μ)
Base.@deprecate Cosine(μ::Real) Cosine(μ=μ)
Base.@deprecate Epanechnikov(μ::Real) Epanechnikov(μ=μ)
Base.@deprecate Erlang(α::Int) Erlang(α=α)
Base.@deprecate Gamma(α::Real) Gamma(α=α)
Base.@deprecate Gumbel(μ::Real) Gumbel(μ=μ)
Base.@deprecate Frechet(α::Real) Frechet(α=α)
Base.@deprecate GeneralizedPareto(σ::Real, ξ::Real) GeneralizedPareto(σ=σ, ξ=ξ)
Base.@deprecate InverseGamma(α::Real) InverseGamma(α=α)
Base.@deprecate InverseGaussian(μ::Real) InverseGaussian(μ=μ)
Base.@deprecate Laplace(μ::Real) Laplace(μ=μ)
Base.@deprecate Levy(μ::Real) Levy(μ=μ)
Base.@deprecate Logistic(μ::Real) Logistic(μ=μ)
Base.@deprecate LogNormal(μ::Real) LogNormal(μ=μ)
Base.@deprecate Normal(μ::Real) Normal(μ=μ)
Base.@deprecate Pareto(α::Real) Pareto(α=α)
Base.@deprecate SymTriangularDist(μ::Real) SymTriangularDist(μ=μ)
Base.@deprecate TriangularDist(a,b) TriangularDist(a=a,b=b)
Base.@deprecate Triweight(μ::Real) Triweight(μ=μ)
Base.@deprecate VonMises(κ::Real) VonMises(κ=κ)
Base.@deprecate Weibull(α::Real) Weibull(α=α)
Base.@deprecate Binomial(n::Integer) Binomial(n=n)
Base.@deprecate DiscreteUniform(b::Real) DiscreteUniform(b=b)
Base.@deprecate NegativeBinomial(r::Real) NegativeBinomial(r=r)
Base.@deprecate Skellam(μ::Real) Skellam(μ=μ)


Base.@deprecate MvNormal(Σ::AbstractMatrix) MvNormal(Σ=Σ)
Base.@deprecate MvNormal(μ::AbstractVector, σ::AbstractVector) MvNormal(μ=μ,σ=σ)
Base.@deprecate MvNormal(μ::AbstractVector, σ::Real) MvNormal(μ=μ,σ=σ)
Base.@deprecate MvNormal(σ::AbstractVector) MvNormal(σ=σ)
Base.@deprecate MvNormal(n::Int, σ::Real) MvNormal(σ=σ,n=n)


# vectorized versions
for fun in [:pdf, :logpdf,
Expand Down
2 changes: 1 addition & 1 deletion src/multivariate/dirichlet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function _rand!(d::Union{Dirichlet,DirichletCanon}, x::AbstractVector{T}) where
n = length(x)
α = d.alpha
for i in 1:n
Copy link
Member

Choose a reason for hiding this comment

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

for i in eachindex(x) would be faster and more concise

Copy link
Member Author

Choose a reason for hiding this comment

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

true, but i'm trying not to change too much non-constructor code as part of this PR.

Care to make a fix as a new PR?

@inbounds s += (x[i] = rand(Gamma(α[i])))
@inbounds s += (x[i] = rand(Gamma(α[i])))
end
multiply!(x, inv(s)) # this returns x
end
Expand Down
37 changes: 14 additions & 23 deletions src/multivariate/mvnormal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -200,32 +200,23 @@ function MvNormal(μ::Union{Vector{T}, ZeroVector{T}}, Σ::Cov) where {T<:Real,
MvNormal(convert(AbstractArray{R}, μ), convert(AbstractArray{R}, Σ))
end

function MvNormal(Σ::Cov) where Cov<:AbstractPDMat
T = eltype(Σ)
MvNormal{T,Cov,ZeroVector{T}}(ZeroVector(T, dim(Σ)), Σ)
end
MvNormal(μ::AbstractVector, Σ::Matrix) = MvNormal(μ, PDMat(Σ))
MvNormal(μ::AbstractVector, Σ::Union{Symmetric, Hermitian}) = MvNormal(μ, PDMat(Σ))
MvNormal(μ::AbstractVector, Σ::Diagonal) = MvNormal(μ, PDiagMat(diag(Σ)))
MvNormal(μ::AbstractVector, Σ::UniformScaling) = MvNormal(μ, ScalMat(length(μ), I.λ))

MvNormal(μ::Vector{T}, Σ::Matrix{T}) where {T<:Real} = MvNormal(μ, PDMat(Σ))
MvNormal(μ::Vector{T}, Σ::Union{Symmetric{T}, Hermitian{T}}) where {T<:Real} = MvNormal(μ, PDMat(Σ))
MvNormal(μ::Vector{T}, Σ::Diagonal{T}) where {T<:Real} = MvNormal(μ, PDiagMat(diag(Σ)))
MvNormal(μ::Vector{T}, σ::Vector{T}) where {T<:Real} = MvNormal(μ, PDiagMat(abs2.(σ)))
MvNormal(μ::Vector{T}, σ::T) where {T<:Real} = MvNormal(μ, ScalMat(length(μ), abs2(σ)))
@kwdispatch (::Type{D})(;mu=>μ, mean=>μ, Sigma=>Σ, cov=>Σ, sigma=>σ, std=>σ) where {D<:MvNormal} begin
(μ::AbstractVector, Σ) -> D(μ, Σ)
(Σ) -> D(ZeroVector(eltype(Σ), size(Σ,1)), Σ)

function MvNormal(μ::Vector{T}, Σ::VecOrMat{S}) where {T<:Real,S<:Real}
R = Base.promote_eltype(μ, Σ)
MvNormal(convert(AbstractArray{R}, μ), convert(AbstractArray{R}, Σ))
end
function MvNormal(μ::Vector{T}, σ::Real) where T<:Real
R = Base.promote_eltype(μ, σ)
MvNormal(convert(AbstractArray{R}, μ), R(σ))
end
function MvNormal(μ::Vector{T}, σ::UniformScaling{S}) where {T<:Real,S<:Real}
R = Base.promote_eltype(μ, σ.λ)
MvNormal(convert(AbstractArray{R}, μ), R(σ.λ))
(μ::AbstractVector, σ::AbstractVector) -> D(μ, PDiagMat(abs2.(σ)))
(σ::AbstractVector,) -> D(ZeroVector(eltype(σ), length(σ)), PDiagMat(abs2.(σ)))

(μ::AbstractVector, σ::Real) -> D(μ, ScalMat(length(μ), abs2(σ)))
(σ::Real, n::Integer) -> D(ZeroVector(typeof(σ), n), ScalMat(n, abs2(σ)))

(n::Integer,) -> D(ZeroVector(Float64, n), ScalMat(n, 1.0))
end
MvNormal(Σ::Matrix{T}) where {T<:Real} = MvNormal(PDMat(Σ))
MvNormal(σ::Vector{T}) where {T<:Real} = MvNormal(PDiagMat(abs2.(σ)))
MvNormal(d::Int, σ::Real) = MvNormal(ScalMat(d, abs2(σ)))

### Conversion
function convert(::Type{MvNormal{T}}, d::MvNormal) where T<:Real
Expand Down
40 changes: 25 additions & 15 deletions src/univariate/continuous/arcsine.jl
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
"""
Arcsine(a,b)
Arcsine <: ContinuousUnivariatDistribution

The *Arcsine distribution* has probability density function
The *arcsine* probability distribution

# Constructors

Arcsine(a=,b=)

Construct an `Arcsine` distribution object with minimum `a` and maximum `b`.

Arcsine()

Construct an `Arcsine` distribution object with minimum `0` and maximum `1`.

# Details
The arcsine distribution has probability density function

```math
f(x) = \\frac{1}{\\pi \\sqrt{(x - a) (b - x)}}, \\quad x \\in [a, b]
```

# Examples
```julia
Arcsine() # Arcsine distribution with support [0, 1]
Arcsine(b) # Arcsine distribution with support [0, b]
Arcsine(a, b) # Arcsine distribution with support [a, b]

params(d) # Get the parameters, i.e. (a, b)
minimum(d) # Get the lower bound, i.e. a
maximum(d) # Get the upper bound, i.e. b
location(d) # Get the left bound, i.e. a
scale(d) # Get the span of the support, i.e. b - a
Arcsine()
Arcsine(a=2, b=2)
```

External links
# External links

* [Arcsine distribution on Wikipedia](http://en.wikipedia.org/wiki/Arcsine_distribution)

Expand All @@ -33,9 +40,12 @@ end

Arcsine(a::T, b::T) where {T<:Real} = Arcsine{T}(a, b)
Copy link
Contributor

Choose a reason for hiding this comment

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

While redeclaring everything can we drop the excessiive type constraints?
Let numbers be numbers

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe that should be its own PR.

Copy link
Member

Choose a reason for hiding this comment

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

what's the rationale for dropping the type constraint (these are also useful as type signatures)

Copy link
Contributor

Choose a reason for hiding this comment

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

It breaks the the abiility to use weirder number types.
In general Real is not a bad one.
Worse is the Arrays, (it is just this occured first)

where something is decleared as taking an Array,
rather than an AbstractArray.
Because it breaks GPUs, Flux, and any of cool lazy array types.

Copy link
Member

Choose a reason for hiding this comment

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

Probably better do this in another PR, this one is already big enough.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, after I get this done I want to loosen up the array types.

Are there any non-Real number types that would be useful? The only one I can think of are Unitful ones, but even those wouldn't really work correctly (e.g. for a gamma distribution, it makes sense for the scale parameter to have a unit, but the shape one should still be unitless).

Arcsine(a::Real, b::Real) = Arcsine(promote(a, b)...)
Arcsine(a::Integer, b::Integer) = Arcsine(Float64(a), Float64(b))
Arcsine(b::Real) = Arcsine(0.0, b)
Arcsine() = Arcsine(0.0, 1.0)
Arcsine(a::Integer, b::Integer) = Arcsine(float(a), float(b))

@kwdispatch (::Type{D})() where {D<:Arcsine} begin
() -> D(0,1)
(a,b) -> D(a,b)
end

@distr_support Arcsine d.a d.b

Expand Down
54 changes: 43 additions & 11 deletions src/univariate/continuous/beta.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
"""
Beta(α,β)
Beta <: ContinuousUnivariateDistribution

The *Beta distribution* has probability density function
The *beta* probability distribution.

# Constructors

Beta(α|alpha=1, β|beta=1)

Construct a `Beta` distribution object with parameters `α` and `β`.

Beta(mean=,var=)
Beta(mean=,std=)

Construct a `Beta` distribution object matching the relevant moments.

# Details

The beta distribution has probability density function

```math
f(x; \\alpha, \\beta) = \\frac{1}{B(\\alpha, \\beta)}
Expand All @@ -12,16 +27,15 @@ The Beta distribution is related to the [`Gamma`](@ref) distribution via the
property that if ``X \\sim \\operatorname{Gamma}(\\alpha)`` and ``Y \\sim \\operatorname{Gamma}(\\beta)``
independently, then ``X / (X + Y) \\sim Beta(\\alpha, \\beta)``.

# Examples

```julia
Beta() # equivalent to Beta(1, 1)
Beta(a) # equivalent to Beta(a, a)
Beta(a, b) # Beta distribution with shape parameters a and b

params(d) # Get the parameters, i.e. (a, b)
Beta()
Beta(α=3, β=4)
Beta(mean=0.2, std=0.1)
```

External links
# External links

* [Beta distribution on Wikipedia](http://en.wikipedia.org/wiki/Beta_distribution)

Expand All @@ -38,9 +52,27 @@ end

Beta(α::T, β::T) where {T<:Real} = Beta{T}(α, β)
Copy link
Contributor

@oxinabox oxinabox Feb 10, 2019

Choose a reason for hiding this comment

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

Suggested change
Beta::T, β::T) where {T<:Real} = Beta{T}(α, β)
Beta::T, β::T) where T= Beta{T}(α, β)

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

should be Beta(α::T, β::T) where {T} = Beta{T}(α, β) ?

Beta(α::Real, β::Real) = Beta(promote(α, β)...)
Beta(α::Integer, β::Integer) = Beta(Float64(α), Float64(β))
Beta(α::Real) = Beta(α, α)
Beta() = Beta(1, 1)
Beta(α::Integer, β::Integer) = Beta(float(α), float(β))

@kwdispatch (::Type{D})(;alpha=>α, beta=>β) where {D<:Beta} begin
() -> D(1,1)
(β) -> D(1,β)
(α) -> D(α,1)
(α,β) -> D(α,β)

function (mean, var)
Copy link
Member

Choose a reason for hiding this comment

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

is this creating an anonymous function?

Copy link
Member Author

Choose a reason for hiding this comment

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

ordinarily, yes.

@check_args(Beta, 0 < mean < 1)
@check_args(Beta, 0 < var < mean*(1-mean))
U = (mean*(1-mean))/var - 1
α = mean*U
β = U-α
D(α,β)
end

function (mean, std)
D(mean=mean,var=sqrt(std))
end
end

@distr_support Beta 0.0 1.0

Expand Down
41 changes: 27 additions & 14 deletions src/univariate/continuous/betaprime.jl
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
"""
BetaPrime(α,β)
BetaPrime <: ContinuousUnivariateDistribution

The *Beta prime distribution* has probability density function
The *beta prime* probability distribution.

# Constructors

BetaPrime(α|alpha=1, β|beta=1)

Construct a `BetaPrime` distribution object with parameters `α` and `β`.

# Details

The beta prime distribution has probability density function

```math
f(x; \\alpha, \\beta) = \\frac{1}{B(\\alpha, \\beta)}
x^{\\alpha - 1} (1 + x)^{- (\\alpha + \\beta)}, \\quad x > 0
```


The Beta prime distribution is related to the [`Beta`](@ref) distribution via the
The beta prime distribution is related to the [`Beta`](@ref) distribution via the
relation ship that if ``X \\sim \\operatorname{Beta}(\\alpha, \\beta)`` then ``\\frac{X}{1 - X}
\\sim \\operatorname{BetaPrime}(\\alpha, \\beta)``

```julia
BetaPrime() # equivalent to BetaPrime(1, 1)
BetaPrime(a) # equivalent to BetaPrime(a, a)
BetaPrime(a, b) # Beta prime distribution with shape parameters a and b
# Examples

params(d) # Get the parameters, i.e. (a, b)
```julia
BetaPrime()
BetaPrime(α=3, β=4)
```

External links
# External links

* [Beta prime distribution on Wikipedia](http://en.wikipedia.org/wiki/Beta_prime_distribution)

Expand All @@ -38,9 +46,14 @@ end

BetaPrime(α::T, β::T) where {T<:Real} = BetaPrime{T}(α, β)
BetaPrime(α::Real, β::Real) = BetaPrime(promote(α, β)...)
BetaPrime(α::Integer, β::Integer) = BetaPrime(Float64(α), Float64(β))
BetaPrime(α::Real) = BetaPrime(α, α)
BetaPrime() = BetaPrime(1.0, 1.0)
BetaPrime(α::Integer, β::Integer) = BetaPrime(float(α), float(β))

@kwdispatch (::Type{D})(;alpha=>α, beta=>β) where {D<:BetaPrime} begin
() -> D(1,1)
(β) -> D(1,β)
(α) -> D(α,1)
(α,β) -> D(α,β)
end

@distr_support BetaPrime 0.0 Inf

Expand Down Expand Up @@ -111,5 +124,5 @@ invlogccdf(d::BetaPrime, p::Real) = (x = betainvlogccdf(d.α, d.β, p); x / (1 -

function rand(d::BetaPrime)
(α, β) = params(d)
rand(Gamma(α)) / rand(Gamma(β))
rand(Gamma(α)) / rand(Gamma(α=β))
end
11 changes: 8 additions & 3 deletions src/univariate/continuous/biweight.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ end

Biweight(μ::T, σ::T) where {T<:Real} = Biweight{T}(μ, σ)
Biweight(μ::Real, σ::Real) = Biweight(promote(μ, σ)...)
Biweight(μ::Integer, σ::Integer) = Biweight(Float64(μ), Float64(σ))
Biweight(μ::Real) = Biweight(μ, 1.0)
Biweight() = Biweight(0.0, 1.0)
Biweight(μ::Integer, σ::Integer) = Biweight(float(μ), float(σ))

@kwdispatch (::Type{D})(;mu=>μ, sigma=>σ) where {D<:Biweight} begin
() -> D(0,1)
(μ) -> D(μ,1)
(σ) -> D(0,σ)
(μ,σ) -> D(μ,σ)
end

@distr_support Biweight d.μ - d.σ d.μ + d.σ

Expand Down
Loading