@@ -276,6 +276,30 @@ function prefix(::IsParent, ctx::AbstractContext, vn::VarName)
276
276
return prefix (childcontext (ctx), vn)
277
277
end
278
278
279
+ """
280
+ prefix_and_strip_contexts(ctx::PrefixContext, vn::VarName)
281
+
282
+ Same as `prefix`, but additionally returns a new context stack that has all the
283
+ PrefixContexts removed.
284
+ """
285
+ function prefix_and_strip_contexts (ctx:: PrefixContext{Prefix} , vn:: VarName ) where {Prefix}
286
+ child_context = childcontext (ctx)
287
+ # vn_prefixed contains the prefixes from all lower levels
288
+ vn_prefixed, child_context_without_prefixes = prefix_and_strip_contexts (
289
+ child_context, vn
290
+ )
291
+ return AbstractPPL. prefix (vn_prefixed, VarName {Prefix} ()),
292
+ child_context_without_prefixes
293
+ end
294
+ function prefix_and_strip_contexts (ctx:: AbstractContext , vn:: VarName )
295
+ return prefix_and_strip_contexts (NodeTrait (ctx), ctx, vn)
296
+ end
297
+ prefix_and_strip_contexts (:: IsLeaf , ctx:: AbstractContext , vn:: VarName ) = (vn, ctx)
298
+ function prefix_and_strip_contexts (:: IsParent , ctx:: AbstractContext , vn:: VarName )
299
+ vn, new_ctx = prefix_and_strip_contexts (childcontext (ctx), vn)
300
+ return vn, setchildcontext (ctx, new_ctx)
301
+ end
302
+
279
303
"""
280
304
prefix(model::Model, x)
281
305
@@ -351,6 +375,29 @@ NodeTrait(::ConditionContext) = IsParent()
351
375
childcontext (context:: ConditionContext ) = context. context
352
376
setchildcontext (parent:: ConditionContext , child) = ConditionContext (parent. values, child)
353
377
378
+ """
379
+ collapse_prefix_and_condition(context::AbstractContext)
380
+
381
+ Apply `PrefixContext`s to any conditioned values inside them, and remove
382
+ the `PrefixContext`s from the context stack.
383
+
384
+ ```jldoctest
385
+ julia> using DynamicPPL: collapse_prefix_and_condition
386
+
387
+ julia> c1 = PrefixContext({:a}(ConditionContext((x=1, )))
388
+ ```
389
+ """
390
+ function collapse_prefix_and_condition (context:: PrefixContext{Prefix} ) where {Prefix}
391
+ # Collapse the child context (thus applying any inner prefixes first)
392
+ collapsed = collapse_prefix_and_condition (childcontext (context))
393
+ # Prefix any conditioned variables with the current prefix
394
+ # Note: prefix_conditioned_variables is O(N) in the depth of the context stack.
395
+ # So is this function. In the worst case scenario, this is O(N^2) in the
396
+ # depth of the context stack.
397
+ return prefix_conditioned_variables (collapsed, VarName {Prefix} ())
398
+ end
399
+ collapse_prefix_and_condition (context:: AbstractContext ) = context
400
+
354
401
"""
355
402
prefix_conditioned_variables(context::AbstractContext, prefix::VarName)
356
403
@@ -427,9 +474,7 @@ function hasconditioned_nested(::IsParent, context, vn)
427
474
return hasconditioned (context, vn) || hasconditioned_nested (childcontext (context), vn)
428
475
end
429
476
function hasconditioned_nested (context:: PrefixContext{Prefix} , vn) where {Prefix}
430
- return hasconditioned_nested (
431
- prefix_conditioned_variables (childcontext (context), VarName {Prefix} ()), vn
432
- )
477
+ return hasconditioned_nested (collapse_prefix_and_condition (context), vn)
433
478
end
434
479
435
480
"""
@@ -447,9 +492,7 @@ function getconditioned_nested(::IsLeaf, context, vn)
447
492
return error (" context $(context) does not contain value for $vn " )
448
493
end
449
494
function getconditioned_nested (context:: PrefixContext{Prefix} , vn) where {Prefix}
450
- return getconditioned_nested (
451
- prefix_conditioned_variables (childcontext (context), VarName {Prefix} ()), vn
452
- )
495
+ return getconditioned_nested (collapse_prefix_and_condition (context), vn)
453
496
end
454
497
function getconditioned_nested (:: IsParent , context, vn)
455
498
return if hasconditioned (context, vn)
0 commit comments