Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
cd1c46d
added ConditionContext and ContextualModel
torfjelde Jul 15, 2021
b877656
Merge branch 'master' into tor/conditioning
torfjelde Jul 15, 2021
b1106ee
removed redundant definition
torfjelde Jul 15, 2021
0f00771
return condition model by default
torfjelde Jul 15, 2021
c754291
formatting
torfjelde Jul 15, 2021
2d3f94c
forgot to include contextual model in previous commit
torfjelde Jul 15, 2021
3e5a79f
fixed typos
torfjelde Jul 15, 2021
d4e4238
added some niceties to ConditionContext
torfjelde Jul 15, 2021
85a47eb
added support for vectors of VarName
torfjelde Jul 16, 2021
c7dae8d
Update src/contexts.jl
torfjelde Jul 16, 2021
14f5f57
Merge branch 'master' into tor/conditioning
yebai Jul 16, 2021
d3b6485
Merge branch 'master' into tor/conditioning
yebai Jul 18, 2021
75680b3
upper-bound Distributions.jl in tests
torfjelde Jul 19, 2021
1692c03
Merge branch 'master' into tor/conditioning
torfjelde Jul 19, 2021
262c86b
Merge branch 'tor/conditioning' of github.com:TuringLang/DynamicPPL.j…
torfjelde Jul 19, 2021
f0ae744
make the isassumption check using context extensible and nicer
torfjelde Jul 19, 2021
22fcae8
Merge branch 'tor/upper-bound-distributions' into tor/conditioning
torfjelde Jul 19, 2021
b990bb0
renamed type-parameter for ConditionContext
torfjelde Jul 19, 2021
8994cd7
Update src/contexts.jl
torfjelde Jul 19, 2021
8da41c8
Merge branch 'master' into tor/conditioning
torfjelde Jul 21, 2021
94da453
introduced convenient _getvalue method
torfjelde Jul 21, 2021
4e74cf8
overload tilde_assume rather than tilde_assume! and others for Condit…
torfjelde Jul 21, 2021
f9cdfa9
added contextual_isassumption for PrefixContext
torfjelde Jul 21, 2021
835a41e
implemented contextual_isassumption for all contexts
torfjelde Jul 21, 2021
5d110d5
improved the way ConditionContext works signficantly
torfjelde Jul 21, 2021
560ca83
forgot impl of dot_tilde_observe for ConditionContext
torfjelde Jul 21, 2021
5635c3b
Apply suggestions from code review
torfjelde Jul 21, 2021
e78dc65
overload _evaluate rather than the model-call directly
torfjelde Jul 22, 2021
5f0e4a8
Merge branch 'tor/conditioning' of github.com:TuringLang/DynamicPPL.j…
torfjelde Jul 22, 2021
f9e753a
initial work
torfjelde Jul 23, 2021
f090ff5
added some missing implementations
torfjelde Jul 24, 2021
4e36c55
formatting
torfjelde Jul 24, 2021
3a408cf
Merge branch 'tor/context-traits' into tor/conditioning-with-traits
torfjelde Jul 24, 2021
1d3b11e
drop now unneceesary impls for tilds for ConditionContext
torfjelde Jul 24, 2021
e1a7d38
formatting
torfjelde Jul 24, 2021
b42c34f
address issues using traits
torfjelde Jul 24, 2021
c7c60e6
added rewrap for contexts
torfjelde Jul 24, 2021
be67807
do decondition properly
torfjelde Jul 24, 2021
0468297
added some examples and decondition now removes ConditionContext
torfjelde Jul 24, 2021
80e3d5f
improved condition and decondition a bit further
torfjelde Jul 24, 2021
9419e76
use rewrap in _evaluate for ContextualModel
torfjelde Jul 24, 2021
4e566f7
remove the drop_missing as it is no longer needed
torfjelde Jul 24, 2021
d035c23
Merge branch 'tor/conditioning' into tor/conditioning-with-traits
torfjelde Jul 24, 2021
5c1f18e
Merge branch 'master' into tor/conditioning
torfjelde Jul 24, 2021
d6cd4ff
Merge branch 'tor/conditioning' into tor/conditioning-with-traits
torfjelde Jul 24, 2021
b27228a
rename rewrap to setchildcontet
torfjelde Jul 24, 2021
4935d5c
formatting
torfjelde Jul 24, 2021
6196083
made show a bit nicer for ConditionContext
torfjelde Jul 24, 2021
65048fc
use print instead of println in show
torfjelde Jul 24, 2021
48dda72
Merge branch 'tor/conditioning' into tor/conditioning-with-traits
torfjelde Jul 24, 2021
649af29
formatting
torfjelde Jul 24, 2021
ffdee05
Merge branch 'tor/conditioning' into tor/conditioning-with-traits
torfjelde Jul 25, 2021
4010ab8
make Model a contextual model
torfjelde Jul 25, 2021
5b26300
Merge branch 'master' into tor/conditioning
torfjelde Jul 28, 2021
bf39000
Merge branch 'tor/conditioning' into tor/conditioning-with-traits
torfjelde Jul 28, 2021
798798b
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 28, 2021
df5478f
Merge branch 'master' into tor/context-traits
torfjelde Jul 28, 2021
ee035cb
added some more functionality for context traits
torfjelde Jul 28, 2021
93184cc
Merge branch 'tor/context-traits' into tor/conditioning-with-traits
torfjelde Jul 28, 2021
21c08e5
dont overload haskey and improved contextual_isassumption check
torfjelde Jul 28, 2021
f52ccdd
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 28, 2021
35fad36
remove the now unnecessary ContextualModel and AbstractModel
torfjelde Jul 28, 2021
9297e61
removed some leftovers
torfjelde Jul 28, 2021
65f8094
removed now gone include
torfjelde Jul 28, 2021
b201ef3
removed leftovers
torfjelde Jul 28, 2021
9ebdd0e
formatting
torfjelde Jul 29, 2021
274ad23
fixed typo
torfjelde Jul 29, 2021
a02f7b8
Merge branch 'tor/conditioning-with-traits-in-model' of github.com:Tu…
torfjelde Jul 29, 2021
b7998bc
fixed PointwiseLikelihood
torfjelde Jul 29, 2021
cf9d168
Merge branch 'tor/context-traits' into tor/conditioning-with-traits
torfjelde Jul 29, 2021
589507f
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 29, 2021
8cc3193
improved condition and fixed isassumption
torfjelde Jul 29, 2021
f3698cf
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 29, 2021
26edb2c
added BangBang as dep
torfjelde Jul 29, 2021
eb31a4a
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 29, 2021
be61ef1
fixed the _evaluate
torfjelde Jul 29, 2021
4e3e08f
fixed a doctest
torfjelde Jul 29, 2021
1a40c9c
Merge branch 'tor/context-traits' into tor/conditioning-with-traits
torfjelde Jul 29, 2021
bdf3fb4
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 29, 2021
9e23d4d
formatting
torfjelde Jul 29, 2021
ffe896a
Merge branch 'tor/context-traits' into tor/conditioning-with-traits
torfjelde Jul 29, 2021
e2f6fc5
formatting
torfjelde Jul 29, 2021
987e4e4
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 29, 2021
a361a5e
formatting
torfjelde Jul 29, 2021
ce160d6
fixed condition without arguments
torfjelde Jul 29, 2021
41cc734
Merge branch 'tor/conditioning-with-traits' into tor/conditioning-wit…
torfjelde Jul 29, 2021
b492041
had forgotten a return
torfjelde Aug 1, 2021
7ae9e3e
added methods for extracting the conditioned/observed variables and v…
torfjelde Aug 1, 2021
3b31d35
fixed a couple of tilde statements
torfjelde Aug 1, 2021
cefb443
added docstring to observations
torfjelde Aug 1, 2021
51209fd
Merge branch 'master' into tor/context-traits
yebai Aug 2, 2021
6086734
Apply suggestions from code review
yebai Aug 2, 2021
e579020
Apply suggestions from code review
torfjelde Aug 2, 2021
7c9dc5e
make NodeTrait an abstract type
torfjelde Aug 4, 2021
e67089f
make matchingvalue work nicely with contexts
torfjelde Aug 4, 2021
9479ce4
added a bunch of tests for the new trait system for contexts
torfjelde Aug 4, 2021
1315d88
formatting
torfjelde Aug 4, 2021
2af625c
Merge branch 'tor/context-traits' into tor/conditioning-with-traits-i…
torfjelde Aug 4, 2021
1d3fa2b
dont export contextualize, observations and conditioned
torfjelde Aug 4, 2021
da34dff
added getvalue_nested and hasvalue_nested to be more explicit
torfjelde Aug 4, 2021
5e15b25
added a substantial amount of testing for ConditionContext
torfjelde Aug 4, 2021
386e985
removed some debugging code
torfjelde Aug 4, 2021
52c9f04
use maybe_view in isassumption check
torfjelde Aug 4, 2021
65e7f71
added more extensive docstring for getvalue_nested and hasvalue_nested
torfjelde Aug 4, 2021
3822da2
Merge branch 'master' into tor/conditioning-with-traits-in-model
torfjelde Aug 12, 2021
0054ffb
some minor style changes
torfjelde Aug 12, 2021
14a94f0
added docs and doctests for condition and decondition for model
torfjelde Aug 12, 2021
6e563cf
rephrased a comment
torfjelde Aug 12, 2021
8011381
improvement to remove_prefix in tests
torfjelde Aug 12, 2021
ac5c291
formatting
torfjelde Aug 12, 2021
297bf92
fixing some tests
torfjelde Aug 12, 2021
bab9e19
fixed bug in tilde_observe for prefix context
torfjelde Aug 12, 2021
2d1985b
attempted fix for doctests
torfjelde Aug 12, 2021
67dd45a
fixed doctests
torfjelde Aug 13, 2021
2735784
formatting
torfjelde Aug 13, 2021
f641c8a
Merge branch 'master' into tor/conditioning-with-traits-in-model
torfjelde Aug 13, 2021
ed7aa8b
fixed doctests
torfjelde Aug 13, 2021
333fec7
fixed doctests on 1.3
torfjelde Aug 13, 2021
73736ef
bump of minor version
torfjelde Aug 14, 2021
264e22b
bump version of integration tests
torfjelde Aug 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name = "DynamicPPL"
uuid = "366bfd00-2699-11ea-058f-f148b4cae6d8"
version = "0.13.2"
version = "0.14.0"

[deps]
AbstractMCMC = "80f14c24-f653-4e6a-9b94-39d6b0f70001"
AbstractPPL = "7a57a42e-76ec-4ea3-a279-07e840d6d9cf"
BangBang = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
Bijectors = "76274a88-744f-5084-9051-94815aaf08c4"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Expand All @@ -15,6 +16,7 @@ ZygoteRules = "700de1a5-db45-46bc-99cf-38207098b444"
[compat]
AbstractMCMC = "2, 3.0"
AbstractPPL = "0.2"
BangBang = "0.3"
Bijectors = "0.5.2, 0.6, 0.7, 0.8, 0.9"
ChainRulesCore = "0.9.7, 0.10"
Distributions = "0.23.8, 0.24, 0.25"
Expand Down
4 changes: 4 additions & 0 deletions src/DynamicPPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ using AbstractMCMC: AbstractMCMC
using ChainRulesCore: ChainRulesCore
using MacroTools: MacroTools
using ZygoteRules: ZygoteRules
using BangBang: BangBang

using Random: Random

Expand Down Expand Up @@ -81,6 +82,7 @@ export AbstractVarInfo,
PriorContext,
MiniBatchContext,
PrefixContext,
ConditionContext,
assume,
dot_assume,
observe,
Expand All @@ -99,6 +101,8 @@ export AbstractVarInfo,
logprior,
logjoint,
pointwise_loglikelihoods,
condition,
decondition,
# Convenience macros
@addlogprob!,
@submodel
Expand Down
73 changes: 65 additions & 8 deletions src/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,66 @@ function isassumption(expr::Union{Symbol,Expr})

return quote
let $vn = $(varname(expr))
# This branch should compile nicely in all cases except for partial missing data
# For example, when `expr` is `:(x[i])` and `x isa Vector{Union{Missing, Float64}}`
if !$(DynamicPPL.inargnames)($vn, __model__) ||
$(DynamicPPL.inmissings)($vn, __model__)
true
if $(DynamicPPL.contextual_isassumption)(__context__, $vn)
# Considered an assumption by `__context__` which means either:
# 1. We hit the default implementation, e.g. using `DefaultContext`,
# which in turn means that we haven't considered if it's one of
# the model arguments, hence we need to check this.
# 2. We are working with a `ConditionContext` _and_ it's NOT in the model arguments,
# i.e. we're trying to condition one of the latent variables.
# In this case, the below will return `true` since the first branch
# will be hit.
# 3. We are working with a `ConditionContext` _and_ it's in the model arguments,
# i.e. we're trying to override the value. This is currently NOT supported.
# TODO: Support by adding context to model, and use `model.args`
# as the default conditioning. Then we no longer need to check `inargnames`
# since it will all be handled by `contextual_isassumption`.
if !($(DynamicPPL.inargnames)($vn, __model__)) ||
$(DynamicPPL.inmissings)($vn, __model__)
true
else
$(maybe_view(expr)) === missing
end
else
# Evaluate the LHS
$(maybe_view(expr)) === missing
false
end
end
end
end

"""
contextual_isassumption(context, vn)

Return `true` if `vn` is considered an assumption by `context`.

The default implementation for `AbstractContext` always returns `true`.
"""
contextual_isassumption(::IsLeaf, context, vn) = true
function contextual_isassumption(::IsParent, context, vn)
return contextual_isassumption(childcontext(context), vn)
end
function contextual_isassumption(context::AbstractContext, vn)
return contextual_isassumption(NodeTrait(context), context, vn)
end
function contextual_isassumption(context::ConditionContext, vn)
if hasvalue(context, vn)
val = getvalue(context, vn)
# TODO: Do we even need the `>: Missing`, i.e. does it even help the compiler?
if eltype(val) >: Missing && val === missing
return true
else
return false
end
end

# We might have nested contexts, e.g. `ContextionContext{.., <:PrefixContext{..., <:ConditionContext}}`
# so we defer to `childcontext` if we haven't concluded that anything yet.
return contextual_isassumption(childcontext(context), vn)
end
function contextual_isassumption(context::PrefixContext, vn)
return contextual_isassumption(childcontext(context), prefix(context, vn))
end

# failsafe: a literal is never an assumption
isassumption(expr) = :(false)

Expand Down Expand Up @@ -93,7 +140,7 @@ variables.

# Example
```jldoctest; setup=:(using Distributions)
julia> _, _, vns = DynamicPPL.unwrap_right_left_vns(MvNormal(1, 1.0), randn(1, 2), @varname(x)); string(vns[end])
julia> _, _, vns = DynamicPPL.unwrap_right_left_vns(MvNormal([1.0, 1.0], [1.0 0.0; 0.0 1.0]), randn(2, 2), @varname(x)); string(vns[end])
"x[:,2]"

julia> _, _, vns = DynamicPPL.unwrap_right_left_vns(Normal(), randn(1, 2), @varname(x[:])); string(vns[end])
Expand Down Expand Up @@ -351,6 +398,11 @@ function generate_tilde(left, right)
__varinfo__,
)
else
# If `vn` is not in `argnames`, we need to make sure that the variable is defined.
if !$(DynamicPPL.inargnames)($vn, __model__)
$left = $(DynamicPPL.getvalue_nested)(__context__, $vn)
end

$(DynamicPPL.tilde_observe!)(
__context__,
$(DynamicPPL.check_tilde_rhs)($right),
Expand Down Expand Up @@ -395,6 +447,11 @@ function generate_dot_tilde(left, right)
__varinfo__,
)
else
# If `vn` is not in `argnames`, we need to make sure that the variable is defined.
if !$(DynamicPPL.inargnames)($vn, __model__)
$left .= $(DynamicPPL.getvalue_nested)(__context__, $vn)
end

$(DynamicPPL.dot_tilde_observe!)(
__context__,
$(DynamicPPL.check_tilde_rhs)($right),
Expand Down
20 changes: 15 additions & 5 deletions src/context_implementations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,17 @@ alg_str(spl::Sampler) = string(nameof(typeof(spl.alg)))
require_gradient(spl::Sampler) = false
require_particles(spl::Sampler) = false

_getindex(x, inds::Tuple) = _getindex(view(x, first(inds)...), Base.tail(inds))
_getindex(x, inds::Tuple) = _getindex(Base.maybeview(x, first(inds)...), Base.tail(inds))
_getindex(x, inds::Tuple{}) = x
_getvalue(x, vn::VarName{sym}) where {sym} = _getindex(getproperty(x, sym), vn.indexing)
function _getvalue(x, vns::AbstractVector{<:VarName{sym}}) where {sym}
val = getproperty(x, sym)

# This should work with both cartesian and linear indexing.
return map(vns) do vn
_getindex(val, vn)
end
end

# assume
"""
Expand Down Expand Up @@ -177,13 +186,14 @@ tilde_observe(::PriorContext, sampler, right, left, vi) = 0
function tilde_observe(context::MiniBatchContext, right, left, vi)
return context.loglike_scalar * tilde_observe(context.context, right, left, vi)
end
function tilde_observe(context::MiniBatchContext, right, left, vname, vi)
return context.loglike_scalar * tilde_observe(context.context, right, left, vname, vi)
function tilde_observe(context::MiniBatchContext, sampler, right, left, vi)
return context.loglike_scalar *
tilde_observe(context.context, sampler, right, left, vname, vi)
end

# `PrefixContext`
function tilde_observe(context::PrefixContext, right, left, vname, vi)
return tilde_observe(context.context, right, left, prefix(context, vname), vi)
function tilde_observe(context::PrefixContext, right, left, vi)
return tilde_observe(context.context, right, left, vi)
end

"""
Expand Down
173 changes: 173 additions & 0 deletions src/contexts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,176 @@ function prefix(::PrefixContext{Prefix}, vn::VarName{Sym}) where {Prefix,Sym}
VarName{Symbol(Prefix, PREFIX_SEPARATOR, Sym)}(vn.indexing)
end
end

struct ConditionContext{Names,Values,Ctx<:AbstractContext} <: AbstractContext
values::Values
context::Ctx

function ConditionContext{Values}(
values::Values, context::AbstractContext
) where {names,Values<:NamedTuple{names}}
return new{names,typeof(values),typeof(context)}(values, context)
end
end

function ConditionContext(values::NamedTuple)
return ConditionContext(values, DefaultContext())
end
function ConditionContext(values::NamedTuple, context::AbstractContext)
return ConditionContext{typeof(values)}(values, context)
end

# Try to avoid nested `ConditionContext`.
function ConditionContext(
values::NamedTuple{Names}, context::ConditionContext
) where {Names}
# Note that this potentially overrides values from `context`, thus giving
# precedence to the outmost `ConditionContext`.
return ConditionContext(merge(context.values, values), childcontext(context))
end

function Base.show(io::IO, context::ConditionContext)
return print(io, "ConditionContext($(context.values), $(childcontext(context)))")
end

NodeTrait(context::ConditionContext) = IsParent()
childcontext(context::ConditionContext) = context.context
setchildcontext(parent::ConditionContext, child) = ConditionContext(parent.values, child)

"""
hasvalue(context, vn)

Return `true` if `vn` is found in `context`.
"""
hasvalue(context, vn) = false

function hasvalue(context::ConditionContext{vars}, vn::VarName{sym}) where {vars,sym}
return sym in vars
end
function hasvalue(
context::ConditionContext{vars}, vn::AbstractArray{<:VarName{sym}}
) where {vars,sym}
return sym in vars
end

"""
getvalue(context, vn)

Return value of `vn` in `context`.
"""
function getvalue(context::AbstractContext, vn)
return error("context $(context) does not contain value for $vn")
end
Comment on lines +311 to +313
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do @nospecialize(context::AbstractContext)? Or does this mean that we also won't specialize on getvalue(::ConditionContext, ...)?

getvalue(context::ConditionContext, vn) = _getvalue(context.values, vn)

"""
hasvalue_nested(context, vn)

Return `true` if `vn` is found in `context` or any of its descendants.

This is contrast to [`hasvalue`](@ref) which only checks for `vn` in `context`,
not recursively checking if `vn` is in any of its descendants.
"""
function hasvalue_nested(context::AbstractContext, vn)
return hasvalue_nested(NodeTrait(hasvalue_nested, context), context, vn)
end
hasvalue_nested(::IsLeaf, context, vn) = hasvalue(context, vn)
function hasvalue_nested(::IsParent, context, vn)
return hasvalue(context, vn) || hasvalue_nested(childcontext(context), vn)
end
function hasvalue_nested(context::PrefixContext, vn)
return hasvalue_nested(childcontext(context), prefix(context, vn))
end

"""
getvalue_nested(context, vn)

Return the value of the parameter corresponding to `vn` from `context` or its descendants.

This is contrast to [`getvalue`](@ref) which only returns the value `vn` in `context`,
not recursively looking into its descendants.
"""
function getvalue_nested(context::AbstractContext, vn)
return getvalue_nested(NodeTrait(getvalue_nested, context), context, vn)
end
function getvalue_nested(::IsLeaf, context, vn)
return error("context $(context) does not contain value for $vn")
end
function getvalue_nested(context::PrefixContext, vn)
return getvalue_nested(childcontext(context), prefix(context, vn))
end
function getvalue_nested(::IsParent, context, vn)
return if hasvalue(context, vn)
getvalue(context, vn)
else
getvalue_nested(childcontext(context), vn)
end
end

"""
condition([context::AbstractContext,] values::NamedTuple)
condition([context::AbstractContext]; values...)

Return `ConditionContext` with `values` and `context` if `values` is non-empty,
otherwise return `context` which is [`DefaultContext`](@ref) by default.

See also: [`decondition`](@ref)
"""
condition(; values...) = condition(DefaultContext(), NamedTuple(values))
condition(values::NamedTuple) = condition(DefaultContext(), values)
condition(context::AbstractContext, values::NamedTuple{()}) = context
condition(context::AbstractContext, values::NamedTuple) = ConditionContext(values, context)
condition(context::AbstractContext; values...) = condition(context, NamedTuple(values))

"""
decondition(context::AbstractContext, syms...)

Return `context` but with `syms` no longer conditioned on.

Note that this recursively traverses contexts, deconditioning all along the way.

See also: [`condition`](@ref)
"""
decondition(::IsLeaf, context, args...) = context
function decondition(::IsParent, context, args...)
return setchildcontext(context, decondition(childcontext(context), args...))
end
decondition(context, args...) = decondition(NodeTrait(context), context, args...)
function decondition(context::ConditionContext)
return decondition(childcontext(context))
end
function decondition(context::ConditionContext, sym)
return condition(
decondition(childcontext(context), sym), BangBang.delete!!(context.values, sym)
)
end
function decondition(context::ConditionContext, sym, syms...)
return decondition(
condition(
decondition(childcontext(context), syms...),
BangBang.delete!!(context.values, sym),
),
syms...,
)
end

"""
conditioned(context::AbstractContext)

Return `NamedTuple` of values that are conditioned on under context`.

Note that this will recursively traverse the context stack and return
a merged version of the condition values.
"""
function conditioned(context::AbstractContext)
return conditioned(NodeTrait(conditioned, context), context)
end
conditioned(::IsLeaf, context) = ()
conditioned(::IsParent, context) = conditioned(childcontext(context))
function conditioned(context::ConditionContext)
# Note the order of arguments to `merge`. The behavior of the rest of DPPL
# is that the outermost `context` takes precendence, hence when resolving
# the `conditioned` variables we need to ensure that `context.values` takes
# precedence over decendants of `context`.
return merge(context.values, conditioned(childcontext(context)))
end
Loading