Skip to content

Commit 289b3b9

Browse files
committed
Add measure operators in submodule MeasureOperators
Having the operators in a sub-module makes it easier for users to control whether of they want them in their namespace. Operators have a larger naming conflict potential.
1 parent d4e174b commit 289b3b9

File tree

4 files changed

+169
-0
lines changed

4 files changed

+169
-0
lines changed

src/MeasureBase.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ include("density-core.jl")
152152

153153
include("interface.jl")
154154

155+
include("measure_operators.jl")
156+
155157
using .Interface
156158

157159
end # module MeasureBase

src/measure_operators.jl

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
"""
2+
module MeasureOperators
3+
4+
Defines the following operators for measures:
5+
6+
* `f ⋄ μ == pushfwd(f, μ)`
7+
8+
* `μ ⊙ f == inverse(f) ⋄ μ`
9+
"""
10+
module MeasureOperators
11+
12+
using MeasureBase: AbstractMeasure
13+
using MeasureBase: pushfwd, pullbck, mbind, productmeasure
14+
using MeasureBase: mintegrate, mintegrate_exp, density_rel, logdensity_rel
15+
using InverseFunctions: inverse
16+
using Reexport: @reexport
17+
18+
19+
@doc raw"""
20+
⋄(f, μ::AbstractMeasure) = pushfwd(f, μ)
21+
22+
The `\\diamond` operator denotes a pushforward operation: `ν = f ⋄ μ`
23+
generates a
24+
[pushforward measure](https://en.wikipedia.org/wiki/Pushforward_measure).
25+
26+
A common mathematical notation for a pushforward is ``f_*μ``, but as
27+
there is no "subscript-star" operator in Julia, we use `⋄`.
28+
29+
See [`pushfwd(f, μ)`](@ref) for details.
30+
31+
Also see [`ν ⊙ f`](@ref), the pullback operator.
32+
"""
33+
(f, μ::AbstractMeasure) = pushfwd(f, μ)
34+
export
35+
36+
37+
@doc raw"""
38+
⊙(ν::AbstractMeasure, f) = pullbck(f, ν)
39+
40+
The `\\odot` operator denotes a pullback operation.
41+
42+
See also [`pullbck(ν, f)`](@ref) for details. Note that `pullbck` takes it's
43+
arguments in different order, in keeping with the Julia convention of
44+
passing functions as the first argument. A pullback is mathematically the
45+
precomposition of a measure `μ`` with the function `f` applied to sets. so
46+
`⊙` takes the measure as the first and the function as the second argument,
47+
as common in mathematical notation for precomposition.
48+
49+
A common mathematical notation for pullback in measure theory is
50+
``f \circ μ``, but as `∘` is used for function composition in Julia and as
51+
`f` semantically acts point-wise on sets, we use `⊙`.
52+
53+
Also see [f ⋄ μ](@ref), the pushforward operator.
54+
"""
55+
::AbstractMeasure, f) = pullbck(f, ν)
56+
export
57+
58+
59+
"""
60+
μ ▷ k = mbind(k, μ)
61+
62+
The `\\triangleright` operator denotes a measure monadic bind operation.
63+
64+
A common operator choice for a monadics bind operator is `>>=` (e.g. in
65+
the Haskell programming language), but this has a different meaning in
66+
Julia and there is no close equivalent, so we use `▷`.
67+
68+
See [`mbind(k, μ)`](@ref) for details. Note that `mbind` takes its
69+
arguments in different order, in keeping with the Julia convention of
70+
passing functions as the first argument. `▷`, on the other hand, takes
71+
its arguments in the order common for monadic binds in functional
72+
programming (like the Haskell `>>=` operator) and mathematics.
73+
"""
74+
::AbstractMeasure,k) = mbind(k, μ)
75+
export
76+
77+
78+
# ToDo: Use `⨂` instead of `⊗` for better readability?
79+
"""
80+
⊗(μs::AbstractMeasure...) = productmeasure(μs)
81+
82+
`⊗` is an operator for building product measures.
83+
84+
See [`productmeasure(μs)`](@ref) for details.
85+
"""
86+
(μs::AbstractMeasure...) = productmeasure(μs)
87+
export
88+
89+
90+
"""
91+
∫(f, μ::AbstractMeasure) = mintegrate(f, μ)
92+
93+
Denotes an indefinite integral of the function `f` with respect to the
94+
measure `μ`.
95+
96+
See [`mintegrate(f, μ)`](@ref) for details.
97+
"""
98+
(f, μ::AbstractMeasure) = mintegrate(f, μ)
99+
export
100+
101+
102+
"""
103+
∫exp(f, μ::AbstractMeasure) = mintegrate_exp(f, μ)
104+
105+
Generates a new measure that is the indefinite integral of `exp` of `f`
106+
with respect to the measure `μ`.
107+
108+
See [`mintegrate_exp(f, μ)`](@ref) for details.
109+
"""
110+
∫exp(f, μ::AbstractMeasure) = mintegrate_exp(f, μ)
111+
export ∫exp
112+
113+
114+
"""
115+
𝒹(ν, μ) = density_rel(ν, μ)
116+
117+
Compute the density, i.e. the
118+
[Radom-Nikodym derivative](https://en.wikipedia.org/wiki/Radon%E2%80%93Nikodym_theorem)
119+
of `ν`` with respect to `μ`.
120+
121+
For details, see [`density_rel(ν, μ)`}(@ref).
122+
"""
123+
𝒹(ν, μ::AbstractMeasure) = density_rel(ν, μ)
124+
export 𝒹
125+
126+
127+
128+
"""
129+
log𝒹(ν, μ) = logdensity_rel(ν, μ)
130+
131+
Compute the log-density, i.e. the logarithm of the
132+
[Radom-Nikodym derivative](https://en.wikipedia.org/wiki/Radon%E2%80%93Nikodym_theorem)
133+
of `ν`` with respect to `μ`.
134+
135+
For details, see [`logdensity_rel(ν, μ)`}(@ref).
136+
"""
137+
log𝒹(ν, μ::AbstractMeasure) = logdensity_rel(ν, μ)
138+
export log𝒹
139+
140+
141+
end # module MeasureOperators

test/measure_operators.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Test
2+
3+
using MeasureBase: AbstractMeasure
4+
using MeasureBase: StdExponential, StdLogistic, StdUniform
5+
using MeasureBase: pushfwd, pullbck, mbind, productmeasure
6+
using MeasureBase: mintegrate, mintegrate_exp, density_rel, logdensity_rel
7+
using MeasureBase.MeasureOperators: , , , , ∫, ∫exp, 𝒹, log𝒹
8+
9+
@testset "MeasureOperators" begin
10+
μ = StdExponential()
11+
ν = StdUniform()
12+
k(σ) = pushfwd(x -> σ * x, StdNormal())
13+
μs = (StdExponential(), StdLogistic(), StdUniform())
14+
f = sqrt
15+
16+
@test @inferred(f μ) == pushfwd(f, μ)
17+
@test @inferred f) == pullbck(f, ν)
18+
@test @inferred k) == mbind(k, μ)
19+
@test @inferred((μs...)) == productmeasure(μs)
20+
@test @inferred((f, μ)) == mintegrate(f, μ)
21+
@test @inferred(∫exp(f, μ)) == mintegrate_exp(f, μ)
22+
@test @inferred(𝒹(ν, μ)) == density_rel(ν, μ)
23+
@test @inferred(log𝒹(ν, μ)) == logdensity_rel(ν, μ)
24+
end

test/runtests.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,5 @@ include("smf.jl")
251251

252252
include("combinators/weighted.jl")
253253
include("combinators/transformedmeasure.jl")
254+
255+
include("measure_operators.jl")

0 commit comments

Comments
 (0)