DeltaMessagePassingRules
The Delta node, out = f(in₁, …, inₙ) for any deterministic function f, and the rules that pass messages through it. Use it for a nonlinear function in a model, z := f(x, y) in RxInfer's syntax, when no node with exact rules exists for f. The rules approximate the pushforward through f, the distribution of f(x, y), with the method the model names. The unscented transform and linearisation handle normal messages. Projection onto an exponential family handles messages of other families.
DeltaMessagePassingRules — Module
DeltaMessagePassingRulesThe Delta node, out = f(in₁, …, inₙ) for a deterministic function f, and its rules, written with MessagePassingRulesBase. The function is arbitrary, so the rules approximate: they push the messages through f by an approximation method, which the node's algorithm names.
DeltaFn: the node, with interfacesoutand the groupin;DeltaApproximation: its algorithm, which a model must give, holding the method and an optional known inverse off;- the Gaussian methods
UnscentedandLinearization, from MessagePassingRulesApproximations, for normal messages; CVIProjection, sampling and projection onto an exponential family, for messages of other families. Its rules are in a package extension, loaded withusing ExponentialFamilyProjection.
The node's function and its static inputs belong to the engine's node object: a rule reaches the function as getnodefn(ctx.node, Target(:out)), with any input connected to a constant or to data already folded in. A known inverse belongs to the algorithm, so a rule towards an input with one needs no node.
Examples
The message towards the input of out = 2in + 1 through its known inverse, by linearization:
julia> algorithm = DeltaApproximation(method = Linearization(), inverse = y -> (y - 1) / 2);
julia> result = @call_message_update_rule(
node = DeltaFn, target = (:in, 1), algorithm = algorithm,
m = (out = NormalMeanVariance(3.0, 2.0), in = (nothing,)),
);
julia> all(mean_var(getresult(result)) .≈ (1.0, 0.5))
trueThe ReactiveMP engine runs these rules on a factor graph, which RxInfer builds from a model. The examples here call the rules directly.
A first example
The message towards out of out = 2in + 1, by the unscented transform, which is exact for an affine function. A rule reaches the node's function through its node object, which an engine provides. Here a small stand-in holds it, and a RuleContext hands it to the rule.
julia> struct WithFunction{F}
f::F
end
julia> MessagePassingRulesBase.getnodefn(node::WithFunction, ::MessagePassingRulesBase.Target{:out}) = node.f
julia> ctx = MessagePassingRulesBase.RuleContext(node = WithFunction(x -> 2x + 1));
julia> result = @call_message_update_rule(
node = DeltaFn, target = :out, algorithm = DeltaApproximation(method = Unscented()),
m = (in = (NormalMeanVariance(1.0, 0.5),),), ctx = ctx,
);
julia> all(mean_var(getresult(result)) .≈ (3.0, 2.0))
trueThe site
- The Delta node: the node, its algorithm, its rules and their limitations;
- Projection:
CVIProjection, the method for messages that are not normal, and its sampling strategies; - Internals: the helpers the Gaussian rules share, for contributors.