Migrating old VarInfo code

Please get in touch if you have some old code you're unsure how to migrate, and we will be happy to add it to this list.

using DynamicPPL, Distributions, Random

@model function f()
    x ~ Normal()
    y ~ LogNormal()
    return 1.0 ~ Normal(x + y)
end

model = f()
Model{typeof(Main.f), (), (), (), Tuple{}, Tuple{}, DefaultContext, false}(Main.f, NamedTuple(), NamedTuple(), DefaultContext())

Sampling from the prior

Old:

vi = VarInfo(Xoshiro(468), model)
VarInfo
 ├─ transform_strategy: UnlinkAll()
 ├─ values
 │  VarNamedTuple
 │  ├─ x => VectorValue{Vector{Float64}, DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}}([0.07200886749732076], DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}((1,)))
 │  └─ y => VectorValue{Vector{Float64}, DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}}([0.9286310592520649], DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}((1,)))
 └─ accs
    AccumulatorTuple with 3 accumulators
    ├─ LogPrior => LogPriorAccumulator(-1.769167187291674)
    ├─ LogJacobian => LogJacobianAccumulator(0.0)
    └─ LogLikelihood => LogLikelihoodAccumulator(-0.918938737957795)

New:

accs = OnlyAccsVarInfo()
_, vi = init!!(Xoshiro(468), model, accs, InitFromPrior(), UnlinkAll())
vi
OnlyAccsVarInfo
 └─ AccumulatorTuple with 3 accumulators
    ├─ LogPrior => LogPriorAccumulator(-1.769167187291674)
    ├─ LogJacobian => LogJacobianAccumulator(0.0)
    └─ LogLikelihood => LogLikelihoodAccumulator(-0.918938737957795)

Getting parameter values

Old:

vi = VarInfo(Xoshiro(468), model)
vi[@varname(x)], vi[@varname(y)]
(0.07200886749732076, 0.9286310592520649)

New:

# Set to true if you want to include results of `:=` statements.
accs = OnlyAccsVarInfo(RawValueAccumulator(false))
_, vi = init!!(Xoshiro(468), model, accs, InitFromPrior(), UnlinkAll())
get_raw_values(vi)
VarNamedTuple
├─ x => 0.07200886749732076
└─ y => 0.9286310592520649

Generating vectorised parameters from linked VarInfo

Old:

vi = VarInfo(Xoshiro(468), model)
vi = DynamicPPL.link!!(vi, model)
vi[:]
2-element Vector{Float64}:
  0.07200886749732076
 -0.07404375655951738

The new pattern recognises that in practice you are likely using vi[:] in conjunction with a LogDensityFunction. So we make one first:

accs = OnlyAccsVarInfo(VectorValueAccumulator())
_, vi = init!!(Xoshiro(468), model, accs, InitFromPrior(), LinkAll())
ldf = LogDensityFunction(model, getlogjoint_internal, vi)

Then you can do:

vec = to_vector_params(get_vector_values(vi), ldf)
2-element Vector{Float64}:
  0.07200886749732076
 -0.07404375655951738

(Note that to generate unlinked parameters, just replace LinkAll() with UnlinkAll() in the call to init!! above.)

Re-evaluating log density at new parameters

Old:

vi = VarInfo(Xoshiro(468), model)

vals = [1.0, 1.0]
# Note this was `unflatten` (no exclamation mark) in the old code
vi = DynamicPPL.unflatten!!(vi, vals)
_, vi = DynamicPPL.evaluate!!(model, vi)
vi
VarInfo
 ├─ transform_strategy: UnlinkAll()
 ├─ values
 │  VarNamedTuple
 │  ├─ x => VectorValue{SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}}([1.0], DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}((1,)))
 │  └─ y => VectorValue{SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}}([1.0], DynamicPPL.UnwrapSingletonTransform{Tuple{Int64}}((1,)))
 └─ accs
    AccumulatorTuple with 3 accumulators
    ├─ LogPrior => LogPriorAccumulator(-2.3378770664093453)
    ├─ LogJacobian => LogJacobianAccumulator(0.0)
    └─ LogLikelihood => LogLikelihoodAccumulator(-1.4189385332046727)

The new path also assumes that you are using a LogDensityFunction:

ldf = LogDensityFunction(model, getlogjoint_internal, vi)
LogDensityFunction{Model{typeof(Main.f), (), (), (), Tuple{}, Tuple{}, DefaultContext, false}, Nothing, UnlinkAll, typeof(getlogjoint_internal), VarNamedTuple{(:x, :y), Tuple{DynamicPPL.RangeAndLinked, DynamicPPL.RangeAndLinked}}, Nothing, Vector{Float64}, DynamicPPL.AccumulatorTuple{3, @NamedTuple{LogPrior::LogPriorAccumulator{Float64}, LogJacobian::LogJacobianAccumulator{Float64}, LogLikelihood::LogLikelihoodAccumulator{Float64}}}}(Model{typeof(Main.f), (), (), (), Tuple{}, Tuple{}, DefaultContext, false}(Main.f, NamedTuple(), NamedTuple(), DefaultContext()), nothing, UnlinkAll(), DynamicPPL.getlogjoint_internal, VarNamedTuple(x = DynamicPPL.RangeAndLinked(1:1, false), y = DynamicPPL.RangeAndLinked(2:2, false)), nothing, 2, DynamicPPL.AccumulatorTuple{3, @NamedTuple{LogPrior::LogPriorAccumulator{Float64}, LogJacobian::LogJacobianAccumulator{Float64}, LogLikelihood::LogLikelihoodAccumulator{Float64}}}((LogPrior = LogPriorAccumulator(0.0), LogJacobian = LogJacobianAccumulator(0.0), LogLikelihood = LogLikelihoodAccumulator(0.0))))

Then you can do:

init_strategy = InitFromVector(vals, ldf)

vi = OnlyAccsVarInfo()
_, vi = init!!(Xoshiro(468), model, vi, init_strategy, ldf.transform_strategy)
vi
OnlyAccsVarInfo
 └─ AccumulatorTuple with 3 accumulators
    ├─ LogPrior => LogPriorAccumulator(-2.3378770664093453)
    ├─ LogJacobian => LogJacobianAccumulator(0.0)
    └─ LogLikelihood => LogLikelihoodAccumulator(-1.4189385332046727)