-
Notifications
You must be signed in to change notification settings - Fork 36
Open
Description
using DynamicPPL, Distributions
for op1 in [condition, fix]
for op2 in [condition, fix]
@model g() = x ~ Normal()
g_op = op1(g(), (; x = 1.0))
@model f() = a ~ to_submodel(g_op)
f_op = op2(f(), (@varname(a.x) => 2.0))
println("$op1 $op2 => $(f_op())")
end
end
Result:
condition condition => 2.0
condition fix => 2.0
fix condition => 1.0
fix fix => 2.0
For fixfix and concon, there's no issue because the values are merged in a way that respects the outer. (it's somewhere in getconditioned
/ getfixed
I think)
For confix and fixcon, unfortunately, the logic in the codebase says that fixing always takes precedence over conditioning, because fix is in the first branch and condition is in the last branch
Lines 448 to 461 in 0b7213f
$isassumption = $(DynamicPPL.isassumption(left, vn)) | |
if $(DynamicPPL.isfixed(left, vn)) | |
$left = $(DynamicPPL.getfixed_nested)( | |
__context__, $(DynamicPPL.prefix)(__context__, $vn) | |
) | |
elseif $isassumption | |
$(generate_tilde_assume(left, dist, vn)) | |
else | |
# If `vn` is not in `argnames`, we need to make sure that the variable is defined. | |
if !$(DynamicPPL.inargnames)($vn, __model__) | |
$left = $(DynamicPPL.getconditioned_nested)( | |
__context__, $(DynamicPPL.prefix)(__context__, $vn) | |
) | |
end |
Discovered while writing tests for nested condition/fix. This was the test I had intended to add to test/submodel.jl
.
@testset "precedence for conditioning/fixing the same variable twice" begin
# Check that the outermost conditioning takes precedence. I'm not sure
# if there is a strong a priori reason for this, but it is currently
# the case and thus this test just ensures that the behaviour doesn't
# suddenly change without it being a conscious decision to do so.
@testset "$op1,$op2" for op1 in [condition, fix], op2 in [condition, fix]
@model function f()
x ~ Normal()
end
fcond = op1(f(), (; x=1.0)) # this is ignored
@model function g()
return a ~ to_submodel(fcond)
end
gcond = op2(g(), (@varname(a.x) => 2.0)) # this takes precedence
@test gcond() == 2.0
end
end
Could be solved in a multitude of ways, but IMO the only correct way to solve this is to merge fix and condition into a single thing (which will be part of #1010).
Metadata
Metadata
Assignees
Labels
No labels