Normal distributions

A normal node ties a variable out to a mean and a spread: a variance, a precision, a covariance matrix or a precision matrix. The page covers the univariate and multivariate normals in each of their parametrisations, and the half-normal.

With the spread known, the rules towards out and the mean are exact belief propagation: a normal message on the mean, convolved with the noise, gives a normal message on out, and the same holds the other way. With the spread unknown, belief propagation towards it gives no closed-form message for NormalMeanVariance, and the other normals have no such rule at all. The rules towards the spread are therefore variational: they take marginals and return a Gamma, a Wishart or their inverses. In practice, you choose a factorisation that puts an unknown spread in a cluster of its own, such as q(out, μ) q(τ) or the mean field q(out) q(μ) q(τ).

The nodes are ExponentialFamily's types, declared as nodes here. They all run under DefaultAlgorithm, so a model never names an algorithm for them.

In the interface tables below, a rule takes messages from the interfaces in its target's own cluster, and it takes marginals from the interfaces in other clusters. "Normal" means any univariate or multivariate normal of ExponentialFamily in any parametrisation. "Any" means a marginal with the expectations the rule needs.

Example

The mean-field message towards the mean of a NormalMeanPrecision node takes the marginals of out and of the precision. It is a normal around E[out] with precision E[τ]:

julia> using StandardMessagePassingRules, MessagePassingRulesBase, ExponentialFamily, BayesBase

julia> message = getresult(@call_message_update_rule(
           node = NormalMeanPrecision, target = :μ,
           q = (out = PointMass(2.0), τ = GammaShapeRate(2.0, 1.0)),
       ));

julia> mean(message) ≈ 2.0 && precision(message) ≈ 2.0
true

NormalMeanVariance

\[p(\mathrm{out} \mid μ, v) = \frac{1}{\sqrt{2π v}} \exp\left(-\frac{(\mathrm{out} - μ)^2}{2v}\right)\]

MessagePassingRulesBase.nodespec(NormalMeanVariance)
NodeSpec: NormalMeanVariance
μ (mean)v (var)outNormalMeanVariancestochastic
interfacealiases
out
μmean
vvar
default algorithmMessagePassingRulesBase.DefaultAlgorithm()
static inputsnone
definednodes/normal_mean_variance.jl:1
interfacealiasesmeaningmessages and marginals its rules take
outthe variablea univariate normal or a PointMass
μmeanthe meana univariate normal or a PointMass
vvarthe variancea PointMass message, or any marginal with E[1/v]
MessagePassingRulesBase.rule_coverage(NormalMeanVariance)
Rule coverage for ExponentialFamily.NormalMeanVariance
DefaultAlgorithm
→ out✓×7
→ μ✓×7
→ v✓×5
average energy✓×2
q(out, μ)✓×3
q(out, μ, v)✓×3

The belief propagation message towards out, from a normal message on the mean and a known variance, adds the variances:

@call_message_update_rule(
    node = NormalMeanVariance, target = :out,
    m = (μ = NormalMeanVariance(1.0, 1.0), v = PointMass(2.0)),
)
RuleResult: message of NormalMeanVariance towards :outbelief propagation
μvoutNormalMeanVariance
Result
valueExponentialFamily.NormalMeanVariance{Float64}(μ=1.0, v=3.0)
typeExponentialFamily.NormalMeanVariance{Float64}
log scale0 (declared)
Inputs
edgevalue
μmExponentialFamily.NormalMeanVariance{Float64}(μ=1.0, v=1.0)
vmPointMass{Float64}(2.0)
Rule
declared inputsm[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T, m[:v]::BayesBase.PointMass
algorithmDefaultAlgorithm()
log scale0
definednormal_mean_variance/out.jl:8
body
args->begin
        (μ_mean, μ_var) = mean_var(args.m[:μ])
        NormalMeanVariance(μ_mean, μ_var + mean(args.m[:v]))
    end
Other rules for this target (6)
normal_mean_variance/out.jl:1
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass got ExponentialFamily.NormalMeanVariance{Float64}
✓m[:v]::BayesBase.PointMass got BayesBase.PointMass{Float64}
normal_mean_variance/out.jl:18
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:μ]::BayesBase.PointMass not provided
✗q[:v]::BayesBase.PointMass not provided
✗m[:v]::BayesBase.PointMass{Float64} provided but not consumed
✗m[:μ]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed
normal_mean_variance/out.jl:25
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:μ]::Any not provided
✗q[:v]::Any not provided
✗m[:v]::BayesBase.PointMass{Float64} provided but not consumed
✗m[:μ]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed
normal_mean_variance/out.jl:31
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass got ExponentialFamily.NormalMeanVariance{Float64}
✗q[:v]::Any not provided
✗m[:v]::BayesBase.PointMass{Float64} provided but not consumed
normal_mean_variance/out.jl:37
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✓m[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T got ExponentialFamily.NormalMeanVariance{Float64}
✗q[:v]::Any not provided
✗m[:v]::BayesBase.PointMass{Float64} provided but not consumed
normal_mean_variance/out.jl:46
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✓m[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T got ExponentialFamily.NormalMeanVariance{Float64}
✗q[:v]::BayesBase.PointMass not provided
✗m[:v]::BayesBase.PointMass{Float64} provided but not consumed

The variational message takes the marginals of μ and v. It keeps the mean of q(μ), ignores its variance, and uses 1/E[1/v] = 0.5 of the Gamma marginal as the variance:

@call_message_update_rule(
    node = NormalMeanVariance, target = :out,
    q = (μ = NormalMeanVariance(1.0, 1.0), v = GammaShapeRate(3.0, 4.0)),
)
RuleResult: message of NormalMeanVariance towards :outvariational
μvoutNormalMeanVariance
Result
valueExponentialFamily.NormalMeanVariance{Float64}(μ=1.0, v=0.5)
typeExponentialFamily.NormalMeanVariance{Float64}
log scaleundefined: the message rule for NormalMeanVariance towards :out under MessagePassingRulesBase.DefaultAlgorithm declares no `logscale`
Inputs
edgevalue
μqExponentialFamily.NormalMeanVariance{Float64}(μ=1.0, v=1.0)
vqExponentialFamily.GammaShapeRate{Float64}(a=3.0, b=4.0)
Rule
declared inputsq[:μ]::Any, q[:v]::Any
algorithmDefaultAlgorithm()
log scalenone
definednormal_mean_variance/out.jl:25
body
args->NormalMeanVariance(mean(args.q[:μ]), gaussian_variational_variance(args.q[:v]))
Other rules for this target (6)
normal_mean_variance/out.jl:1
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass not provided
✗m[:v]::BayesBase.PointMass not provided
✗q[:v]::ExponentialFamily.GammaShapeRate{Float64} provided but not consumed
✗q[:μ]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed
normal_mean_variance/out.jl:8
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T not provided
✗m[:v]::BayesBase.PointMass not provided
✗q[:v]::ExponentialFamily.GammaShapeRate{Float64} provided but not consumed
✗q[:μ]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed
normal_mean_variance/out.jl:18
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:μ]::BayesBase.PointMass got ExponentialFamily.NormalMeanVariance{Float64}
✗q[:v]::BayesBase.PointMass got ExponentialFamily.GammaShapeRate{Float64}
normal_mean_variance/out.jl:31
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass not provided
✓q[:v]::Any got ExponentialFamily.GammaShapeRate{Float64}
✗q[:μ]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed
normal_mean_variance/out.jl:37
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T not provided
✓q[:v]::Any got ExponentialFamily.GammaShapeRate{Float64}
✗q[:μ]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed
normal_mean_variance/out.jl:46
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T not provided
✗q[:v]::BayesBase.PointMass got ExponentialFamily.GammaShapeRate{Float64}
✗q[:μ]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed

Towards out and μ, the node has belief propagation, variational and structured rules. Towards v, belief propagation from normal or known out and μ gives a log-density on the half line, a ContinuousUnivariateLogPdf, which has no closed-form family. The variational rule towards v gives an unchecked GammaInverse with shape -1/2, which is a likelihood rather than a distribution. The average energy covers the mean field and q(out, μ) q(v).

NormalMeanPrecision

\[p(\mathrm{out} \mid μ, τ) = \sqrt{\frac{τ}{2π}} \exp\left(-\frac{τ (\mathrm{out} - μ)^2}{2}\right)\]

MessagePassingRulesBase.nodespec(NormalMeanPrecision)
NodeSpec: NormalMeanPrecision
μ (mean)τ (invcov, precision)outNormalMeanPrecisionstochastic
interfacealiases
out
μmean
τinvcov, precision
default algorithmMessagePassingRulesBase.DefaultAlgorithm()
static inputsnone
definednodes/normal_mean_precision.jl:1
interfacealiasesmeaningmessages and marginals its rules take
outthe variablea univariate normal or a PointMass
μmeanthe meana univariate normal or a PointMass
τinvcov, precisionthe precisiona PointMass message, or any marginal with E[τ]
MessagePassingRulesBase.rule_coverage(NormalMeanPrecision)
Rule coverage for ExponentialFamily.NormalMeanPrecision
DefaultAlgorithm
→ out✓×6
→ μ✓×6
→ τ✓×2
average energy✓×2
q(out, μ)✓×3
q(out, μ, τ)✓×3

With a known precision, the message towards out stays in precision form. The precisions combine as 1 / (1/1 + 1/2) = 2/3:

@call_message_update_rule(
    node = NormalMeanPrecision, target = :out,
    m = (μ = NormalMeanPrecision(1.0, 1.0), τ = PointMass(2.0)),
)
RuleResult: message of NormalMeanPrecision towards :outbelief propagation
μτoutNormalMeanPrecision
Result
valueExponentialFamily.NormalMeanPrecision{Float64}(μ=1.0, w=0.666667)
typeExponentialFamily.NormalMeanPrecision{Float64}
log scale0 (declared)
Inputs
edgevalue
μmExponentialFamily.NormalMeanPrecision{Float64}(μ=1.0, w=1.0)
τmPointMass{Float64}(2.0)
Rule
declared inputsm[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T, m[:τ]::BayesBase.PointMass
algorithmDefaultAlgorithm()
log scale0
definednormal_mean_precision/out.jl:8
body
args->begin
        (μ_mean, μ_var) = mean_var(args.m[:μ])
        NormalMeanPrecision(μ_mean, inv(μ_var + inv(mean(args.m[:τ]))))
    end
Other rules for this target (5)
normal_mean_precision/out.jl:1
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass got ExponentialFamily.NormalMeanPrecision{Float64}
✓m[:τ]::BayesBase.PointMass got BayesBase.PointMass{Float64}
normal_mean_precision/out.jl:18
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:μ]::BayesBase.PointMass not provided
✗q[:τ]::BayesBase.PointMass not provided
✗m[:μ]::ExponentialFamily.NormalMeanPrecision{Float64} provided but not consumed
✗m[:τ]::BayesBase.PointMass{Float64} provided but not consumed
normal_mean_precision/out.jl:25
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:μ]::Any not provided
✗q[:τ]::Any not provided
✗m[:μ]::ExponentialFamily.NormalMeanPrecision{Float64} provided but not consumed
✗m[:τ]::BayesBase.PointMass{Float64} provided but not consumed
normal_mean_precision/out.jl:31
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass got ExponentialFamily.NormalMeanPrecision{Float64}
✗q[:τ]::Any not provided
✗m[:τ]::BayesBase.PointMass{Float64} provided but not consumed
normal_mean_precision/out.jl:37
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✓m[:μ]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T got ExponentialFamily.NormalMeanPrecision{Float64}
✗q[:τ]::Any not provided
✗m[:τ]::BayesBase.PointMass{Float64} provided but not consumed

The variational message towards τ takes the marginals of out and μ, and it is a Gamma:

@call_message_update_rule(
    node = NormalMeanPrecision, target = :τ,
    q = (out = PointMass(3.0), μ = NormalMeanPrecision(1.0, 1.0)),
)
RuleResult: message of NormalMeanPrecision towards :τvariational
outμτNormalMeanPrecision
Result
valueDistributions.Gamma{Float64}(α=1.5, θ=0.4)
typeDistributions.Gamma{Float64}
log scaleundefined: the message rule for NormalMeanPrecision towards :τ under MessagePassingRulesBase.DefaultAlgorithm declares no `logscale`
Inputs
edgevalue
outqPointMass{Float64}(3.0)
μqExponentialFamily.NormalMeanPrecision{Float64}(μ=1.0, w=1.0)
Rule
declared inputsq[:out]::Any, q[:μ]::Any
algorithmDefaultAlgorithm()
log scalenone
definednormal_mean_precision/precision.jl:1
body
args->begin
        θ = 2 / (var(args.q[:out]) + var(args.q[:μ]) + abs2(mean(args.q[:out]) - mean(args.q[:μ])))
        Gamma(convert(typeof(θ), 1.5), θ)
    end
Other rules for this target (1)
normal_mean_precision/precision.jl:10
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:out, :μ]::Any not provided
✗q[:out]::BayesBase.PointMass{Float64} provided but not consumed
✗q[:μ]::ExponentialFamily.NormalMeanPrecision{Float64} provided but not consumed

The rules towards τ take q(out) q(μ) or q(out, μ). There is no belief propagation rule towards τ, so an unknown precision needs a factorisation that separates it from out and μ. Asking for one throws a RuleNotFoundError, which lists the rules that do exist:

try
    @call_message_update_rule(
        node = NormalMeanPrecision, target = :τ,
        m = (out = PointMass(3.0), μ = NormalMeanPrecision(1.0, 1.0)),
    )
catch err
    showerror(stdout, err)
end
RuleNotFoundError: no message rule for NormalMeanPrecision towards :τ under MessagePassingRulesBase.DefaultAlgorithm() takes the inputs (m[:out]::BayesBase.PointMass{Float64}, m[:μ]::ExponentialFamily.NormalMeanPrecision{Float64})
  no rule consumes this set of inputs under this algorithm (no rule of this shape)
  what to try: the factorisation decides which inputs a rule receives (messages from the target's cluster, marginals of the other clusters): choose one that delivers the inputs a rule below takes (in RxInfer, `@constraints`), or define a rule for these inputs
  near misses:
    rule at ~/work/StandardMessagePassingRules.jl/StandardMessagePassingRules.jl/src/rules/normal_mean_precision/precision.jl:1
      ✓ algorithm MessagePassingRulesBase.DefaultAlgorithm
      ✗ q[:out]::Any  not provided
      ✗ q[:μ]::Any  not provided
      ✗ m[:out]::BayesBase.PointMass{Float64}  provided but not consumed
      ✗ m[:μ]::ExponentialFamily.NormalMeanPrecision{Float64}  provided but not consumed
    rule at ~/work/StandardMessagePassingRules.jl/StandardMessagePassingRules.jl/src/rules/normal_mean_precision/precision.jl:10
      ✓ algorithm MessagePassingRulesBase.DefaultAlgorithm
      ✗ q[:out, :μ]::Any  not provided
      ✗ m[:out]::BayesBase.PointMass{Float64}  provided but not consumed
      ✗ m[:μ]::ExponentialFamily.NormalMeanPrecision{Float64}  provided but not consumed

MvNormalMeanCovariance

\[p(\mathrm{out} \mid μ, Σ) = |2π Σ|^{-1/2} \exp\left(-\tfrac{1}{2} (\mathrm{out} - μ)^\top Σ^{-1} (\mathrm{out} - μ)\right)\]

MessagePassingRulesBase.nodespec(MvNormalMeanCovariance)
NodeSpec: MvNormalMeanCovariance
μ (mean)Σ (cov)outMvNormalMeanCovariancestochastic
interfacealiases
out
μmean
Σcov
default algorithmMessagePassingRulesBase.DefaultAlgorithm()
static inputsnone
definednodes/mv_normal_mean_covariance.jl:1
interfacealiasesmeaningmessages and marginals its rules take
outthe variablea multivariate normal or a PointMass
μmeanthe meana multivariate normal or a PointMass
Σcovthe covariancea PointMass message, or any marginal with E[Σ⁻¹]
MessagePassingRulesBase.rule_coverage(MvNormalMeanCovariance)
Rule coverage for ExponentialFamily.MvNormalMeanCovariance
DefaultAlgorithm
→ out✓×6
→ μ✓×6
→ Σ✓×2
average energy✓×2
q(out, μ)✓×3
q(out, μ, Σ)✓×3

As in the univariate case, the belief propagation message towards out adds the covariances:

@call_message_update_rule(
    node = MvNormalMeanCovariance, target = :out,
    m = (μ = MvNormalMeanCovariance([1.0, 2.0], diageye(2)), Σ = PointMass([2.0 0.0; 0.0 2.0])),
)
RuleResult: message of MvNormalMeanCovariance towards :outbelief propagation
μΣoutMvNormalMeanCovariance
Result
valueMvNormalMeanCovariance( μ: [1.0, 2.0] Σ: [3.0 0.0; 0.0 3.0] )
typeExponentialFamily.MvNormalMeanCovariance{Float64, Vector{Float64}, Matrix{Float64}}
log scale0 (declared)
Inputs
edgevalue
μmMvNormalMeanCovariance( μ: [1.0, 2.0] Σ: [1.0 0.0; 0.0 1.0] )
ΣmPointMass{Matrix{Float64}}([2.0 0.0; 0.0 2.0])
Rule
declared inputsm[:μ]::Union{ExponentialFamily.MultivariateNormalDistributionsFamily{T}, ExponentialFamily.MultivariateGaussianDistributionsFamily{T}} where T, m[:Σ]::BayesBase.PointMass
algorithmDefaultAlgorithm()
log scale0
definedmv_normal_mean_covariance/out.jl:10
body
args->begin
        (μ, V) = mean_cov(args.m[:μ])
        MvNormalMeanCovariance(μ, V + mean(args.m[:Σ]))
    end
Other rules for this target (5)
mv_normal_mean_covariance/out.jl:3
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass got ExponentialFamily.MvNormalMeanCovariance{Float64, Vector{Float64}, Matrix{Float64}}
✓m[:Σ]::BayesBase.PointMass got BayesBase.PointMass{Matrix{Float64}}
mv_normal_mean_covariance/out.jl:22
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:μ]::BayesBase.PointMass not provided
✗q[:Σ]::BayesBase.PointMass not provided
✗m[:Σ]::BayesBase.PointMass{Matrix{Float64}} provided but not consumed
✗m[:μ]::ExponentialFamily.MvNormalMeanCovariance{Float64, Vector{Float64}, Matrix{Float64}} provided but not consumed
mv_normal_mean_covariance/out.jl:29
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗q[:μ]::Any not provided
✗q[:Σ]::Any not provided
✗m[:Σ]::BayesBase.PointMass{Matrix{Float64}} provided but not consumed
✗m[:μ]::ExponentialFamily.MvNormalMeanCovariance{Float64, Vector{Float64}, Matrix{Float64}} provided but not consumed
mv_normal_mean_covariance/out.jl:35
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✗m[:μ]::BayesBase.PointMass got ExponentialFamily.MvNormalMeanCovariance{Float64, Vector{Float64}, Matrix{Float64}}
✗q[:Σ]::Any not provided
✗m[:Σ]::BayesBase.PointMass{Matrix{Float64}} provided but not consumed
mv_normal_mean_covariance/out.jl:41
✓algorithm MessagePassingRulesBase.DefaultAlgorithm
✓m[:μ]::Union{ExponentialFamily.MultivariateNormalDistributionsFamily{T}, ExponentialFamily.MultivariateGaussianDistributionsFamily{T}} where T got ExponentialFamily.MvNormalMeanCovariance{Float64, Vector{Float64}, Matrix{Float64}}
✗q[:Σ]::Any not provided
✗m[:Σ]::BayesBase.PointMass{Matrix{Float64}} provided but not consumed

The rules towards Σ are variational only, and they give an inverse-Wishart likelihood. There is no belief propagation rule towards Σ.

MvNormalMeanPrecision

\[p(\mathrm{out} \mid μ, Λ) = \left|\frac{Λ}{2π}\right|^{1/2} \exp\left(-\tfrac{1}{2} (\mathrm{out} - μ)^\top Λ (\mathrm{out} - μ)\right)\]

interfacealiasesmeaningmessages and marginals its rules take
outthe variablea multivariate normal or a PointMass
μmeanthe meana multivariate normal or a PointMass
Λinvcov, precisionthe precision matrixa PointMass message, or any marginal with E[Λ]; a Wishart marginal has rules of its own
MessagePassingRulesBase.rule_coverage(MvNormalMeanPrecision)
Rule coverage for ExponentialFamily.MvNormalMeanPrecision
DefaultAlgorithm
→ out✓×7
→ μ✓×7
→ Λ✓×2
average energy✓×2
q(out, μ)✓×3
q(out, μ, Λ)✓×3

The rules towards Λ are variational only, and they give a Wishart likelihood. They apply the context's matrix_correction to its scale, and none by default. There is no belief propagation rule towards Λ.

MvNormalWeightedMeanPrecision

\[p(\mathrm{out} \mid ξ, Λ) = \mathcal{N}(\mathrm{out} \mid Λ^{-1} ξ, Λ^{-1})\]

interfacealiasesmeaningmessages and marginals its rules take
outthe variablea multivariate normal
ξxi, weightedmeanthe weighted mean Λ μa PointMass message, or any marginal
Λinvcov, precisionthe precision matrixa PointMass message, or any marginal
MessagePassingRulesBase.rule_coverage(MvNormalWeightedMeanPrecision)
Rule coverage for ExponentialFamily.MvNormalWeightedMeanPrecision
DefaultAlgorithm
→ out✓×2
→ ξ
→ Λ
average energy✓
q(out, ξ, Λ)✓

Limitations. The node has the message towards out and the joint marginal with known parameters only. There is no rule towards ξ or Λ: they must be known, or have their marginals from elsewhere.

MvNormalMeanScalePrecision

\[p(\mathrm{out} \mid μ, γ) = \mathcal{N}(\mathrm{out} \mid μ, (γ I)^{-1})\]

interfacealiasesmeaningmessages and marginals its rules take
outthe variablea multivariate normal message, or any marginal
μmeanthe meana multivariate normal message, or any marginal
γprecisionthe scalar precisionany marginal with E[γ]
MessagePassingRulesBase.rule_coverage(MvNormalMeanScalePrecision)
Rule coverage for ExponentialFamily.MvNormalMeanScalePrecision
DefaultAlgorithm
→ out✓×3
→ μ✓×3
→ γ✓×2
average energy✓×2
q(out, μ)✓×3
q(out, μ, γ)✓×3

Every message rule takes γ as a marginal, so γ is always in a cluster of its own. The rules towards γ are variational, and they give a GammaShapeRate.

MvNormalMeanScaleMatrixPrecision

\[p(\mathrm{out} \mid μ, γ, G) = \mathcal{N}(\mathrm{out} \mid μ, (γ G)^{-1})\]

interfacealiasesmeaningmessages and marginals its rules take
outthe variablea multivariate normal message, or any marginal
μmeanthe meana multivariate normal message, or any marginal
γscalethe scalar factor of the precisionany marginal with E[γ]
Gmatrixthe matrix factor of the precisionany marginal with E[G]
MessagePassingRulesBase.rule_coverage(MvNormalMeanScaleMatrixPrecision)
Rule coverage for ExponentialFamily.MvNormalMeanScaleMatrixPrecision
DefaultAlgorithm
→ out✓×2
→ μ✓×2
→ γ✓×2
→ G✓×2
average energy✓×2
q(out, μ)✓×3
q(out, μ, γ, G)✓×3

As for MvNormalMeanScalePrecision, every message rule takes γ and G as marginals. The rules towards them are variational.

HalfNormal

\[p(\mathrm{out} \mid v) = \frac{2}{\sqrt{2π v}} \exp\left(-\frac{\mathrm{out}^2}{2v}\right), \quad \mathrm{out} \ge 0\]

interfacealiasesmeaningmessages and marginals its rules take
outthe variableany marginal (average energy)
vvar, σ²the variancea PointMass marginal (message towards out), any marginal (average energy)
MessagePassingRulesBase.rule_coverage(HalfNormal)
Rule coverage for HalfNormal
DefaultAlgorithm
→ out✓
→ v
average energy✓

Limitations. HalfNormal has one message, a truncated normal towards out from a known variance. There is no rule towards v, and no marginal rule.

StandardMessagePassingRules.HalfNormal — Type
HalfNormal

The half-normal node: out is the absolute value of a zero-mean normal with variance v,

\[p(\mathrm{out} \mid v) = \frac{2}{\sqrt{2π v}} \exp\left(-\frac{\mathrm{out}^2}{2v}\right), \quad \mathrm{out} \ge 0.\]

Its interfaces are out and v, with the aliases var and σ²; it runs under DefaultAlgorithm.

Rules. Only the message towards out, from a known variance (a PointMass marginal of v): a Normal(0, √v) truncated to [0, ∞). There is no rule towards v, so v must be known, and no marginal rule. The average energy takes any marginals q_out with a mean and a var, and q_v with mean(log, ·) and mean(inv, ·).

Examples

The average energy of a known out = 1 under a known variance v = 1, -log p(1 | 1):

julia> energy = getresult(@call_average_energy(node = HalfNormal, q = (out = PointMass(1.0), v = PointMass(1.0))));

julia> energy ≈ (log(π / 2) + 1) / 2
true
source