Skip to content

Commit 5e8f1a3

Browse files
authored
Adopt DensityInterface.jl (#41)
1 parent d730194 commit 5e8f1a3

File tree

5 files changed

+44
-23
lines changed

5 files changed

+44
-23
lines changed

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ uuid = "7a57a42e-76ec-4ea3-a279-07e840d6d9cf"
33
keywords = ["probablistic programming"]
44
license = "MIT"
55
desc = "Common interfaces for probabilistic programming"
6-
version = "0.3.1"
6+
version = "0.4"
77

88
[deps]
99
AbstractMCMC = "80f14c24-f653-4e6a-9b94-39d6b0f70001"
10+
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
1011
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
1112

1213
[compat]
1314
AbstractMCMC = "2, 3"
15+
DensityInterface = "0.4"
1416
Setfield = "0.7.1, 0.8"
1517
julia = "1"

interface.md

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ There are three interrelating aspects that this interface intends to standardize
2424
- Sampling
2525
- “Conversions” between different conditionings of models
2626

27-
Therefore, the interface consists of:
27+
Therefore, the interface consists of an `AbstractProbabilisticProgram` supertype, together with
28+
functions
2829

2930
- `condition(::Model, ::Trace) -> ConditionedModel`
3031
- `decondition(::ConditionedModel) -> GenerativeModel`
3132
- `sample(::Model, ::Sampler = Exact(), [Int])` (from `AbstractMCMC.sample`)
32-
- `logdensity(::Model, ::Trace)`
33+
- `logdensityof(::Model, ::Trace)` and `densityof(::Model, ::Trace)` (from
34+
[DensityInterface.jl](https://github.com/JuliaMath/DensityInterface.jl))
3335

3436

3537
### Traces & probability expressions
@@ -198,32 +200,46 @@ Not all variants need to be supported – for example, a posterior model might n
198200
model.
199201

200202

201-
### Density Calculation
203+
### Density Evaluation
202204

203205
Since the different “versions” of how a model is to be understood as generative or conditioned are
204206
to be expressed in the type or dispatch they support, there should be no need for separate functions
205-
`logjoint`, `loglikelihood`, etc., which force these semantic distinctions on the implementor; one
206-
`logdensity` should suffice for all, with the distinction being made by the capabilities of the
207-
concrete model instance.
207+
`logjoint`, `loglikelihood`, etc., which force these semantic distinctions on the implementor; we
208+
therefore adapt the interface of
209+
[DensityInterface.jl](https://github.com/JuliaMath/DensityInterface.jl). Its main function
210+
`logdensityof` should suffice for variants, with the distinction being made by the capabilities of
211+
the concrete model instance.
208212

209-
Note that this generalizes `logpdf`, too, since the posterior density will of course in general be
210-
unnormalized and hence not a probability density.
213+
DensityInterface.jl also requires the trait function `DensityKind`, which is set to `HasDensity()`
214+
for the `AbstractProbabilisticProgram` type. Additional functions
211215

212-
The evaluation will usually work with the internal, concrete trace type, like `VarInfo` in Turing.jl:
216+
```
217+
DensityInterface.densityof(d, x) = exp(logdensityof(d, x))
218+
DensityInterface.logdensityof(d) = Base.Fix1(logdensityof, d)
219+
DensityInterface.densityof(d) = Base.Fix1(densityof, d)
220+
```
221+
222+
are provided automatically (repeated here for clarity).
223+
224+
Note that `logdensityof` strictly generalizes `logpdf`, since the posterior density will of course
225+
in general be unnormalized and hence not a probability density.
226+
227+
The evaluation will usually work with the internal, concrete trace type, like `VarInfo` in
228+
Turing.jl:
213229

214230
```julia
215-
logdensity(m, vi)
231+
logdensityof(m, vi)
216232
```
217233

218234
But the user will more likely work on the interface using probability expressions:
219235

220236
```julia
221-
logdensity(m, @T(X = ...))
237+
logdensityof(m, @T(X = ))
222238
```
223239

224240
(Note that this would replace the current `prob` string macro in Turing.jl.)
225241

226-
Densities need not be normalized.
242+
Densities need (and usually, will) not be normalized.
227243

228244

229245
#### Implementation notes
@@ -232,15 +248,15 @@ It should be able to make this fall back on the internal method with the right d
232248
implementation of `maketrace`:
233249

234250
```julia
235-
logdensity(m, t::ProbabilityExpression) = logdensity(m, maketrace(m, t))
251+
logdensityof(m, t::ProbabilityExpression) = logdensityof(m, maketrace(m, t))
236252
```
237253

238254
There is one open question – should normalized and unnormalized densities be able to be
239255
distinguished? This could be done by dispatch as well, e.g., if the caller wants to make sure
240256
normalization:
241257

242258
```
243-
logdensity(g, @T(X = ..., Y = ..., Z = ...); normalized=Val{true})
259+
logdensityof(g, @T(X = , Y = , Z = ); normalized=Val{true})
244260
```
245261

246262
Although there is proably a better way through traits; maybe like for arrays, with

src/AbstractPPL.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
module AbstractPPL
22

33
# VarName
4-
export VarName, getsym, getindexing, getlens, inspace, subsumes, varname, vsym, @varname, @vsym
4+
export VarName, getsym, getlens, inspace, subsumes, varname, vsym, @varname, @vsym
55

66

77
# Abstract model functions
8-
export AbstractProbabilisticProgram, condition, decondition, logdensity
8+
export AbstractProbabilisticProgram, condition, decondition, logdensityof, densityof
99

1010

1111
# Abstract traces
1212
export AbstractModelTrace
1313

14+
1415
include("varname.jl")
15-
include("abstractprobprog.jl")
1616
include("abstractmodeltrace.jl")
17+
include("abstractprobprog.jl")
1718
include("deprecations.jl")
1819

1920
end # module

src/abstractprobprog.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using AbstractMCMC
2+
using DensityInterface
23

34

45
"""
@@ -8,19 +9,21 @@ Common base type for models expressed as probabilistic programs.
89
"""
910
abstract type AbstractProbabilisticProgram <: AbstractMCMC.AbstractModel end
1011

12+
DensityInterface.DensityKind(::AbstractProbabilisticProgram) = HasDensity()
13+
1114

1215
"""
13-
logdensity(model, trace)
16+
logdensityof(model, trace)
1417
1518
Evaluate the (possibly unnormalized) density of the model specified by the probabilistic program
1619
in `model`, at specific values for the random variables given through `trace`.
1720
1821
`trace` can be of any supported internal trace type, or a fixed probability expression.
1922
20-
`logdensity` should interact with conditioning and deconditioning in the way required by probability
21-
theory.
23+
`logdensityof` should interact with conditioning and deconditioning in the way required by
24+
probability theory.
2225
"""
23-
function logdensity end
26+
DensityInterface.logdensityof(::AbstractProbabilisticProgram, ::AbstractModelTrace)
2427

2528

2629
"""

src/varname.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ julia> getlens(@varname(y))
120120
"""
121121
getlens(vn::VarName) = vn.lens
122122

123-
@deprecate getindexing(vn::VarName) getlens(vn)
124123

125124
"""
126125
get(obj, vn::VarName{sym})

0 commit comments

Comments
 (0)