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}, Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}}([0.07200886749732076], Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}(Bijectors.VectorBijectors.TypedIdentity()))
 │  └─ y => VectorValue{Vector{Float64}, Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}}([0.9286310592520649], Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}(Bijectors.VectorBijectors.TypedIdentity()))
 └─ 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:

ldf = LogDensityFunction(model, getlogjoint_internal, LinkAll())

Then you can do:

rand(Xoshiro(468), ldf)
2-element Vector{Float64}:
  0.07200886749732076
 -0.07404375655951738

This gives you a set of parameters, but if you want to also obtain the log-density at the new parameters, you can do this in a single call to init!!; please see the documentation on LogDensityFunction for more details on how to do this.

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}, Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}}([1.0], Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}(Bijectors.VectorBijectors.TypedIdentity()))
 │  └─ y => VectorValue{SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}}([1.0], Bijectors.VectorBijectors.OnlyWrap{Bijectors.VectorBijectors.TypedIdentity}(Bijectors.VectorBijectors.TypedIdentity()))
 └─ 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:

# Note that we use `UnlinkAll()` here to match the VarInfo above.
# If your VarInfo was linked, you should use `LinkAll()` instead.

ldf = LogDensityFunction(model, getlogjoint_internal, UnlinkAll())
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)