GaussianCouplingMessagePassingRules

The GaussianCoupling node couples two scalar variables through a bilinear potential. It is the edge potential of Gaussian belief propagation (GaBP). Use it to solve a linear system A x = b by message passing, or to find the means of a Gaussian Markov random field given in information form: every off-diagonal entry of A becomes one coupling node.

GaussianCouplingMessagePassingRules — Module
GaussianCouplingMessagePassingRules

The GaussianCoupling node and its rules. The node is the bilinear potential

\[\phi(\mathrm{out}, \mathrm{in}, a) = \exp(\mathrm{out} \cdot a \cdot \mathrm{in}),\]

the pairwise (edge) potential of Gaussian belief propagation: with NormalWeightedMeanPrecision(b[i], A[i, i]) priors on x[i] and a = -A[i, j] on each edge, message passing solves the linear system A x = b.

  • Interfaces: out and in, the two coupled scalar variables, and a, the coupling coefficient, a PointMass.
  • Algorithm: DefaultAlgorithm; a model names none.
  • Rules: the messages towards out and in, the joint marginal q(out, in) and the average energy, all under the structured factorisation q(out, in) q(a), which a constant a gives by itself.

The messages are improper normals, with negative precision, and univariate normal inputs only. There is no mean-field factorisation q(out) q(in) q(a), and the rules declare no log scale.

Examples

julia> using MessagePassingRulesBase, ExponentialFamily, BayesBase

julia> result = @call_message_update_rule(
           node = GaussianCoupling, target = :in,
           m = (out = NormalMeanVariance(2.0, 3.0),), q = (a = PointMass(-0.5),),
       );

julia> getresult(result) ≈ NormalWeightedMeanPrecision(-1.0, -0.75)
true
source
Where these rules run

The ReactiveMP engine runs these rules on a factor graph, which RxInfer builds from a model. The examples here call the rules directly.

The package holds one node, so this page is the whole site.

Overview

A symmetric positive definite matrix A and a vector b define the Gaussian density p(x) ∝ exp(-x'A x / 2 + b'x), whose mean is the solution of A x = b. Gaussian belief propagation writes this density as a product of factors on a factor graph:

  • one self-potential per variable: the prior of x[i] is NormalWeightedMeanPrecision(b[i], A[i, i]);
  • one pairwise potential per non-zero A[i, j] with i < j: a GaussianCoupling node with coefficient a = -A[i, j].

Belief propagation on this graph then computes the means and variances of the x[i]. On a tree they are exact. On a graph with cycles, when the iteration converges, the means are exact and the variances approximate.

Definition

\[\phi(\mathrm{out}, \mathrm{in}, a) = \exp(\mathrm{out} \cdot a \cdot \mathrm{in})\]

The potential rewards out and in of the same sign when a > 0, and of opposite signs when a < 0. It is not integrable, so the node is not a conditional distribution. Its messages are improper normals, with negative precision, and the model as a whole must be normalisable.

Interfaces

using GaussianCouplingMessagePassingRules, MessagePassingRulesBase, ExponentialFamily, BayesBase
MessagePassingRulesBase.nodespec(GaussianCoupling)
NodeSpec: GaussianCoupling
inaoutGaussianCouplingstochastic
interfacealiases
out
in
a
default algorithmMessagePassingRulesBase.DefaultAlgorithm()
static inputsnone
definedsrc/GaussianCouplingMessagePassingRules.jl:120
namealiasesmeaningmessages and marginals its rules take
outnonethe first coupled variableunivariate normal messages
innonethe second coupled variableunivariate normal messages
anonethe coupling coefficient, -A[i, j]a PointMass marginal

GaussianCoupling is symmetric in out and in. The coefficient arrives as a point mass, a distribution with all its mass on one value.

Algorithm

The node uses DefaultAlgorithm, which has no parameters, so a model names none. It declares no dependencies of its own: its rules take what the default scheme delivers, messages from the target's cluster and marginals of the other clusters.

Supported rules

MessagePassingRulesBase.rule_coverage(GaussianCoupling)
Rule coverage for GaussianCoupling
DefaultAlgorithm
→ out✓
→ in✓
→ a
average energy✓
q(out, in)✓

The rules of GaussianCoupling assume the factorisation q(out, in) q(a), which puts out and in in one cluster and a in another. Within it, the rules are belief propagation:

  • the message towards out reads the message on in and the marginal q(a), and the message towards in reads the message on out and q(a);
  • the joint marginal q(out, in) reads both messages and q(a);
  • the average energy ⟨-log φ⟩ = -E[a] E[out ⋅ in] reads q(out, in) and q(a).

A constant a puts a model in this factorisation without a constraint.

Example

The message towards in, from a message N(2, 3) on out and the coefficient a = -0.5:

@call_message_update_rule(
    node = GaussianCoupling, target = :in,
    m = (out = NormalMeanVariance(2.0, 3.0),), q = (a = PointMass(-0.5),),
)
RuleResult: message of GaussianCoupling towards :inmessages and marginals
outainGaussianCoupling
Result
valueExponentialFamily.NormalWeightedMeanPrecision{Float64}(xi=-1.0, w=-0.75)
typeExponentialFamily.NormalWeightedMeanPrecision{Float64}
log scaleundefined: the message rule for GaussianCoupling towards :in under MessagePassingRulesBase.DefaultAlgorithm declares no `logscale`
Inputs
edgevalue
outmExponentialFamily.NormalMeanVariance{Float64}(μ=2.0, v=3.0)
aqPointMass{Float64}(-0.5)
Rule
declared inputsm[:out]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T, q[:a]::BayesBase.PointMass
algorithmDefaultAlgorithm()
log scalenone
definedsrc/GaussianCouplingMessagePassingRules.jl:135
body
args->coupled_message(mean(args.q[:a]), args.m[:out])

The card draws the message on out and the marginal of a as the inputs. The result is NormalWeightedMeanPrecision(a ⋅ 2, -a² ⋅ 3), with a negative precision. The joint marginal adds the cross term -a to the two incoming precisions:

julia> using GaussianCouplingMessagePassingRules, MessagePassingRulesBase, ExponentialFamily, BayesBase

julia> result = @call_message_update_rule(
           node = GaussianCoupling, target = :in,
           m = (out = NormalMeanVariance(2.0, 3.0),), q = (a = PointMass(-0.5),),
       );

julia> getresult(result) ≈ NormalWeightedMeanPrecision(-1.0, -0.75)
true

julia> joint = @call_marginal_update_rule(
           node = GaussianCoupling, target = (:out, :in),
           m = (out = NormalMeanVariance(1.0, 0.5), in = NormalMeanVariance(-2.0, 0.25)),
           q = (a = PointMass(-1.5),),
       );

julia> getresult(joint) ≈ MvNormalWeightedMeanPrecision([2.0, -8.0], [2.0 1.5; 1.5 4.0])
true

Solving a two-variable system

For A = [2 1; 1 3] and b = [1, 2], the graph has two priors and one coupling with a = -A[1, 2] = -1. It is a tree, so one message gives the exact marginal of x[2]:

A, b = [2.0 1.0; 1.0 3.0], [1.0, 2.0]
prior_1 = NormalWeightedMeanPrecision(b[1], A[1, 1])
prior_2 = NormalWeightedMeanPrecision(b[2], A[2, 2])

message = @call_message_update_rule(
    node = GaussianCoupling, target = :in,
    m = (out = prior_1,), q = (a = PointMass(-A[1, 2]),),
)
marginal_2 = prod(GenericProd(), prior_2, getresult(message))

mean_var(marginal_2), (A \ b)[2], inv(A)[2, 2]
((0.6000000000000001, 0.4), 0.6, 0.4)

The marginal's mean is the second entry of the solution A \ b, and its variance is the second diagonal entry of A⁻¹.

Limitations

  • Scalar variables only: the rules take univariate normal messages, and no multivariate version exists.
  • The coefficient a must be a PointMass; a random coefficient has no rules.
  • Only the structured factorisation q(out, in) q(a): there are no mean-field rules and no mean-field average energy.
  • The messages are improper by design, and the joint q(out, in) is proper only when w_out ⋅ w_in > a², w being the incoming precisions.
  • The rules declare no log scale.
  • On graphs with cycles the variances are approximations of diag(A⁻¹), not the exact marginal variances. The means are exact when GaBP converges, for example when A is strictly diagonally dominant.

API

The node, with its interfaces, factorisation, rules and the conditions under which GaBP is exact:

GaussianCouplingMessagePassingRules.GaussianCoupling — Type
GaussianCoupling

The pairwise Gaussian coupling, a stochastic factor node with the bilinear potential

\[\phi(\mathrm{out}, \mathrm{in}, a) = \exp(\mathrm{out} \cdot a \cdot \mathrm{in})\]

This is the pairwise (edge) potential of Gaussian belief propagation (GaBP) as formulated by Shental et al., Gaussian Belief Propagation for Solving Systems of Linear Equations (arXiv:0810.1119), whose edge potential $\psi_{ij}(x_i, x_j) = \exp(-x_i A_{ij} x_j)$ corresponds to $a = -A_{ij}$. Combined with NormalWeightedMeanPrecision(b_i, A_{ii}) self-potentials it turns the solution of $A x = b$ into message passing on a graph.

Interfaces

  1. out: the first coupled variable, scalar; its rules take univariate normal messages.
  2. in: the second coupled variable, scalar; its rules take univariate normal messages.
  3. a: the coupling coefficient, a PointMass.

Factorisation

Only the structured factorisation q(out, in) q(a) is supported:

((:out, :in), (:a,)) in factornode, as RxInfer's @constraints begin q(out, in, a) = q(out, in)q(a) end.

When a is supplied as a constant — the intended usage, as in x[j] ~ GaussianCoupling(x[i], -A[i, j]) — this factorisation is applied automatically, because constant interfaces are always factorised out of the local cluster. MeanField() is not supported: there are no q(out)q(in) message rules and no mean-field average energy.

Rules

  • towards in, from m(out) and q(a), and towards out, from m(in) and q(a): NormalWeightedMeanPrecision(a ⋅ mean(m), -a² ⋅ var(m));
  • the joint marginal q(out, in), from m(out), m(in) and q(a): MvNormalWeightedMeanPrecision([ξ_out, ξ_in], [w_out -a; -a w_in]);
  • the average energy ⟨-log φ⟩ = -E[a] E[out ⋅ in], from q(out, in) and q(a).

The rules declare no log scale.

Improperness

The potential is not integrable on its own, so it is not a conditional distribution:

  • the messages towards out and in are improper Gaussians with negative precision. This is inherent to the factor and reproduces the GaBP message $P_{ij} = -A_{ij}^2 / P_{i \setminus j}$;
  • the joint marginal q(out, in) is proper only when the incoming precisions dominate the coupling, $w_{\mathrm{out}} w_{\mathrm{in}} > a^2$. This is a local condition on a single factor and must not be confused with the convergence conditions below.

The Bethe free energy is still meaningful whenever the product of all factors in the model is normalisable. Since $\langle -\log \phi \rangle = -\mathbb{E}[a]\, \mathbb{E}[\mathrm{out} \cdot \mathrm{in}]$ carries no normaliser term, the accumulated score equals $-\log Z + \mathrm{KL}(q \Vert p)$.

Accuracy

Per Shental et al.:

  • if A is strictly diagonally dominant, or the diagonally normalised system satisfies $\rho(|I - A|) < 1$, GaBP converges and the inferred means are exact, that is, they solve $A x = b$;
  • the inferred variances are exact only on acyclic graphs. On graphs with cycles they are walk-sum approximations of $\mathrm{diag}(A^{-1})$ and must not be reported as the marginal variances of the exact solution.

See also GaussianCouplingMessagePassingRules.

source