API
VarNames
AbstractPPL.VarName
— TypeVarName{sym}(optic=identity)
A variable identifier for a symbol sym
and optic optic
.
The Julia variable in the model corresponding to sym
can refer to a single value or to a hierarchical array structure of univariate, multivariate or matrix variables. The field lens
stores the indices requires to access the random variable from the Julia variable indicated by sym
as a tuple of tuples. Each element of the tuple thereby contains the indices of one optic operation.
VarName
s can be manually constructed using the VarName{sym}(optic)
constructor, or from an optic expression through the @varname
convenience macro.
Examples
julia> vn = VarName{:x}(Accessors.IndexLens((Colon(), 1)) ⨟ Accessors.IndexLens((2, )))
x[:, 1][2]
julia> getoptic(vn)
(@o _[Colon(), 1][2])
julia> @varname x[:, 1][1+1]
x[:, 1][2]
AbstractPPL.getsym
— Functiongetsym(vn::VarName)
Return the symbol of the Julia variable used to generate vn
.
Examples
julia> getsym(@varname(x[1][2:3]))
:x
julia> getsym(@varname(y))
:y
AbstractPPL.getoptic
— Functiongetoptic(vn::VarName)
Return the optic of the Julia variable used to generate vn
.
Examples
julia> getoptic(@varname(x[1][2:3]))
(@o _[1][2:3])
julia> getoptic(@varname(y))
identity (generic function with 1 method)
AbstractPPL.inspace
— Functioninspace(vn::Union{VarName, Symbol}, space::Tuple)
Check whether vn
's variable symbol is in space
. The empty tuple counts as the "universal space" containing all variables. Subsumption (see subsumes
) is respected.
Examples
julia> inspace(@varname(x[1][2:3]), ())
true
julia> inspace(@varname(x[1][2:3]), (:x,))
true
julia> inspace(@varname(x[1][2:3]), (@varname(x),))
true
julia> inspace(@varname(x[1][2:3]), (@varname(x[1:10]), :y))
true
julia> inspace(@varname(x[1][2:3]), (@varname(x[:][2:4]), :y))
true
julia> inspace(@varname(x[1][2:3]), (@varname(x[1:10]),))
true
AbstractPPL.subsumes
— Functionsubsumes(u::VarName, v::VarName)
Check whether the variable name v
describes a sub-range of the variable u
. Supported indexing:
- Scalar:
```jldoctest julia> subsumes(@varname(x), @varname(x[1, 2])) true
julia> subsumes(@varname(x[1, 2]), @varname(x[1, 2][3])) true ```
- Array of scalar: basically everything that fulfills
issubset
.
```jldoctest julia> subsumes(@varname(x[[1, 2], 3]), @varname(x[1, 3])) true
julia> subsumes(@varname(x[1:3]), @varname(x[2][1])) true ```
- Slices:
jldoctest julia> subsumes(@varname(x[2, :]), @varname(x[2, 10][1])) true
Currently not supported are:
- Boolean indexing, literal
CartesianIndex
(these could be added, though) - Linear indexing of multidimensional arrays:
x[4]
does not subsumex[2, 2]
for a matrixx
- Trailing ones:
x[2, 1]
does not subsumex[2]
for a vectorx
AbstractPPL.subsumedby
— Functionsubsumedby(t, u)
True if t
is subsumed by u
, i.e., if subsumes(u, t)
is true.
AbstractPPL.vsym
— Functionvsym(expr)
Return name part of the @varname
-compatible expression expr
as a symbol for input of the VarName
constructor.
AbstractPPL.@varname
— Macro@varname(expr, concretize=false)
A macro that returns an instance of VarName
given a symbol or indexing expression expr
.
If concretize
is true
, the resulting expression will be wrapped in a concretize()
call.
Note that expressions involving dynamic indexing, i.e. begin
and/or end
, will always need to be concretized as VarName
only supports non-dynamic indexing as determined by is_static_optic
. See examples below.
Examples
Dynamic indexing
julia> x = (a = [1.0 2.0; 3.0 4.0; 5.0 6.0], );
julia> @varname(x.a[1:end, end][:], true)
x.a[1:3, 2][:]
julia> @varname(x.a[end], false) # disable concretization
ERROR: LoadError: Variable name `x.a[end]` is dynamic and requires concretization!
[...]
julia> @varname(x.a[end]) # concretization occurs by default if deemed necessary
x.a[6]
julia> # Note that "dynamic" here refers to usage of `begin` and/or `end`,
# _not_ "information only available at runtime", i.e. the following works.
[@varname(x.a[i]) for i = 1:length(x.a)][end]
x.a[6]
julia> # Potentially surprising behaviour, but this is equivalent to what Base does:
@varname(x[2:2:5]), 2:2:5
(x[2:2:4], 2:2:4)
General indexing
Under the hood optic
s are used for the indexing:
julia> getoptic(@varname(x))
identity (generic function with 1 method)
julia> getoptic(@varname(x[1]))
(@o _[1])
julia> getoptic(@varname(x[:, 1]))
(@o _[Colon(), 1])
julia> getoptic(@varname(x[:, 1][2]))
(@o _[Colon(), 1][2])
julia> getoptic(@varname(x[1,2][1+5][45][3]))
(@o _[1, 2][6][45][3])
This also means that we support property access:
julia> getoptic(@varname(x.a))
(@o _.a)
julia> getoptic(@varname(x.a[1]))
(@o _.a[1])
julia> x = (a = [(b = rand(2), )], ); getoptic(@varname(x.a[1].b[end], true))
(@o _.a[1].b[2])
Interpolation can be used for variable names, or array name, but not the lhs of a .
expression. Variables within indices are always evaluated in the calling scope.
julia> name, i = :a, 10;
julia> @varname(x.$name[i, i+1])
x.a[10, 11]
julia> @varname($name)
a
julia> @varname($name[1])
a[1]
julia> @varname($name.x[1])
a.x[1]
julia> @varname(b.$name.x[1])
b.a.x[1]
AbstractPPL.@vsym
— Macro@vsym(expr)
A macro that returns the variable symbol given the input variable expression expr
. For example, @vsym x[1]
returns :x
.
Examples
julia> @vsym x
:x
julia> @vsym x[1,1][2,3]
:x
julia> @vsym x[end]
:x
Abstract model functions
AbstractPPL.AbstractProbabilisticProgram
— TypeAbstractProbabilisticProgram
Common base type for models expressed as probabilistic programs.
AbstractPPL.condition
— Functioncondition(model, observations)
Condition the generative model model
on some observed data, creating a new model of the (possibly unnormalized) posterior distribution over them.
observations
can be of any supported internal trace type, or a fixed probability expression.
The invariant
m = decondition(condition(m, obs))
should hold for generative models m
and arbitrary obs
.
AbstractPPL.decondition
— Functiondecondition(conditioned_model)
Remove the conditioning (i.e., observation data) from conditioned_model
, turning it into a generative model over prior and observed variables.
The invariant
m == condition(decondition(m), obs)
should hold for models m
with conditioned variables obs
.
DensityInterface.logdensityof
— Functionlogdensityof(model, trace)
Evaluate the (possibly unnormalized) density of the model specified by the probabilistic program in model
, at specific values for the random variables given through trace
.
trace
can be of any supported internal trace type, or a fixed probability expression.
logdensityof
should interact with conditioning and deconditioning in the way required by probability theory.
AbstractPPL.AbstractContext
— TypeAbstractContext
Common base type for evaluation contexts.
AbstractPPL.evaluate!!
— Functionevaluate!!
General API for model operations, e.g. prior evaluation, log density, log joint etc.
Abstract traces
AbstractPPL.AbstractModelTrace
— TypeAbstractModelTrace
Common base class for various trace or "variable info" types.