diff --git a/Project.toml b/Project.toml index dd120c59..204fbe47 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MeasureTheory" uuid = "eadaa1a4-d27c-401d-8699-e962e1bbc33b" authors = ["Chad Scherrer and contributors"] -version = "0.11.4" +version = "0.12.0" [deps] Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" diff --git a/src/MeasureTheory.jl b/src/MeasureTheory.jl index 9a0280bc..dd6f700a 100644 --- a/src/MeasureTheory.jl +++ b/src/MeasureTheory.jl @@ -76,7 +76,7 @@ function logpdf(d::AbstractMeasure, x) _logpdf(d, x, logdensity(d,x)) end -function _logpdf(d::AbstractMeasure, x, acc::Float64) +function _logpdf(d::AbstractMeasure, x, acc::Real) β = basemeasure(d) d === β && return acc @@ -104,6 +104,7 @@ include("combinators/weighted.jl") include("combinators/product.jl") include("combinators/transforms.jl") include("combinators/chain.jl") +# include("combinators/basemeasure.jl") include("distributions.jl") diff --git a/src/parameterized/exponential.jl b/src/parameterized/exponential.jl index 3a742d0e..b28c28c5 100644 --- a/src/parameterized/exponential.jl +++ b/src/parameterized/exponential.jl @@ -3,9 +3,9 @@ export Exponential -@parameterized Exponential(λ) ≃ Lebesgue(ℝ₊) +@parameterized Exponential(β) ≃ Lebesgue(ℝ₊) + -@kwstruct Exponential(λ) @kwstruct Exponential() function logdensity(d::Exponential{()} , x) @@ -14,21 +14,82 @@ end Base.rand(rng::AbstractRNG, T::Type, μ::Exponential{()}) = randexp(rng,T) +TV.as(::Exponential) = asℝ₊ + + +########################## +# Scale β + +@kwstruct Exponential(β) + +function Base.rand(rng::AbstractRNG, T::Type, d::Exponential{(:β,)}) + randexp(rng, T) * d.β +end + +function logdensity(d::Exponential{(:β,)}, x) + z = x / d.β + return logdensity(Exponential(), z) - log(d.β) +end + +distproxy(d::Exponential{(:β,)}) = Dists.Exponential(d.β) + +asparams(::Type{<:Exponential}, ::Val{:β}) = asℝ₊ + +########################## +# Log-Scale logβ + + +@kwstruct Exponential(logβ) + +function Base.rand(rng::AbstractRNG, T::Type, d::Exponential{(:logβ,)}) + randexp(rng, T) * exp(d.logβ) +end + +function logdensity(d::Exponential{(:logβ,)}, x) + z = x * exp(-d.logβ) + return logdensity(Exponential(), z) - d.logβ +end + +distproxy(d::Exponential{(:logβ,)}) = Dists.Exponential(exp(d.logβ)) + +asparams(::Type{<:Exponential}, ::Val{:logβ}) = asℝ + + + ########################## +# Rate λ + +@kwstruct Exponential(λ) function Base.rand(rng::AbstractRNG, T::Type, d::Exponential{(:λ,)}) randexp(rng, T) / d.λ end -TV.as(::Exponential) = asℝ₊ - function logdensity(d::Exponential{(:λ,)}, x) z = x * d.λ return logdensity(Exponential(), z) + log(d.λ) end -distproxy(d::Exponential{(:λ,)}) = Dists.Exponential(d.λ) +distproxy(d::Exponential{(:λ,)}) = Dists.Exponential(1/d.λ) asparams(::Type{<:Exponential}, ::Val{:λ}) = asℝ₊ + +########################## +# Log-Rate logλ + + +@kwstruct Exponential(logλ) + +function Base.rand(rng::AbstractRNG, T::Type, d::Exponential{(:logλ,)}) + randexp(rng, T) * exp(-d.logλ) +end + +function logdensity(d::Exponential{(:logλ,)}, x) + z = x * exp(d.logλ) + return logdensity(Exponential(), z) + d.logλ +end + +distproxy(d::Exponential{(:logλ,)}) = Dists.Exponential(exp(-d.logλ)) + asparams(::Type{<:Exponential}, ::Val{:logλ}) = asℝ diff --git a/test/runtests.jl b/test/runtests.jl index 1390114b..361f045e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -94,6 +94,20 @@ end @test_broken logdensity(Binomial(n,p), CountingMeasure(ℤ[0:n]), x) ≈ binomlogpdf(n,p,x) end + @testset "Exponential" begin + r = rand(MersenneTwister(123), Exponential(2)) + @test r ≈ rand(MersenneTwister(123), Exponential(β=2)) + @test r ≈ rand(MersenneTwister(123), Exponential(λ=0.5)) + @test r ≈ rand(MersenneTwister(123), Exponential(logβ=log(2))) + @test r ≈ rand(MersenneTwister(123), Exponential(logλ=log(0.5))) + + ℓ = logdensity(Exponential(2), r) + @test ℓ ≈ logdensity(Exponential(β=2), r) + @test ℓ ≈ logdensity(Exponential(λ=0.5), r) + @test ℓ ≈ logdensity(Exponential(logβ=log(2)), r) + @test ℓ ≈ logdensity(Exponential(logλ=log(0.5)), r) + end + @testset "NegativeBinomial" begin D = NegativeBinomial{(:r, :p)} par = transform(asparams(D), randn(2))