diff --git a/src/MeasureTheory.jl b/src/MeasureTheory.jl index 7b9a7a02..3f8c29e9 100644 --- a/src/MeasureTheory.jl +++ b/src/MeasureTheory.jl @@ -30,6 +30,8 @@ export basemeasure export as +export mass, logmass, is_probability_measure, normalize + abstract type AbstractMeasure end sampletype(μ::AbstractMeasure) = typeof(testvalue(μ)) @@ -54,6 +56,7 @@ include("absolutecontinuity.jl") include("parameterized.jl") include("macros.jl") include("resettablerng.jl") +include("mass.jl") include("primitive.jl") include("primitives/counting.jl") diff --git a/src/combinators/weighted.jl b/src/combinators/weighted.jl index 03858fdc..d7301b0e 100644 --- a/src/combinators/weighted.jl +++ b/src/combinators/weighted.jl @@ -20,6 +20,8 @@ function logdensity(sm::AbstractWeightedMeasure, x) logdensity(sm.base, x) + sm.logweight end +logmass(d::AbstractWeightedMeasure) = logmass(d.base) + d.logweight + ############################################################################### struct WeightedMeasure{R,M} <: AbstractWeightedMeasure diff --git a/src/distributions.jl b/src/distributions.jl index 0aea45d4..5b1db049 100644 --- a/src/distributions.jl +++ b/src/distributions.jl @@ -35,6 +35,10 @@ end ∫(::typeof(identity), ::Dists.Distribution) = 1.0 +# all Distributions distributions are probability measures +logmass(μ::DistributionMeasure) = true +is_probability_measure(μ::DistributionMeasure; kwargs...) = true + logdensity(μ::Dists.Distribution, x) = Dists.logpdf(μ,x) Dists.logpdf(d::AbstractMeasure, x) = logdensity(d,x) diff --git a/src/mass.jl b/src/mass.jl new file mode 100644 index 00000000..43f63c1e --- /dev/null +++ b/src/mass.jl @@ -0,0 +1,40 @@ +using LinearAlgebra: LinearAlgebra + +""" + logmass(μ::AbstractMeasure) + +Compute the logarithm of the [`mass`](@ref) of the measure ``μ``. +""" +function logmass end + +""" + mass(μ::AbstractMeasure) + +Compute the mass of the measure ``μ``. + +That is, given a set ``S`` with elements ``x ∈ S``, compute +``μ(S) = ∫_S dμ(x)``. + +!!! note + This function should not be directly modified. Instead, developers should + overload [`logmass`](@ref). +""" +mass(μ) = Exp(logmass(μ)) + +""" + normalize(μ::AbstractMeasure) + +Convert the measure ``μ`` to a probability measure, that is, a measure whose +total mass is 1. +""" +LinearAlgebra.normalize(μ::AbstractMeasure) = μ * inv(mass(μ)) + +""" + is_probability_measure(μ::AbstractMeasure; kwargs...) -> Bool + +Return `true` if ``μ`` is a probability measure, that is, a measure whose +total [`mass`](@ref) is 1. + +`kwargs` are forwarded to `isapprox`. +""" +is_probability_measure(μ; kwargs...) = isapprox(mass(μ), true; kwargs...) diff --git a/src/primitives/dirac.jl b/src/primitives/dirac.jl index 08a53fe2..3978fbb8 100644 --- a/src/primitives/dirac.jl +++ b/src/primitives/dirac.jl @@ -32,3 +32,5 @@ function logdensity(μ::Dirac{M}, ν::Dirac{M}, x) where {M} return -Inf end end + +logmass(μ::Dirac) = false