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
GaussianCouplingMessagePassingRulesThe 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:
outandin, the two coupled scalar variables, anda, the coupling coefficient, aPointMass. - Algorithm:
DefaultAlgorithm; a model names none. - Rules: the messages towards
outandin, the joint marginalq(out, in)and the average energy, all under the structured factorisationq(out, in) q(a), which a constantagives 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)
trueThe 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]isNormalWeightedMeanPrecision(b[i], A[i, i]); - one pairwise potential per non-zero
A[i, j]withi < j: aGaussianCouplingnode with coefficienta = -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)| interface | aliases | |
|---|---|---|
out | ||
in | ||
a |
| default algorithm | MessagePassingRulesBase.DefaultAlgorithm() |
|---|---|
| static inputs | none |
| defined | src/GaussianCouplingMessagePassingRules.jl:120 |
| name | aliases | meaning | messages and marginals its rules take |
|---|---|---|---|
out | none | the first coupled variable | univariate normal messages |
in | none | the second coupled variable | univariate normal messages |
a | none | the 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)| 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
outreads the message oninand the marginalq(a), and the message towardsinreads the message onoutandq(a); - the joint marginal
q(out, in)reads both messages andq(a); - the average energy
⟨-log φ⟩ = -E[a] E[out ⋅ in]readsq(out, in)andq(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),),
)Result
| value | ExponentialFamily.NormalWeightedMeanPrecision{Float64}(xi=-1.0, w=-0.75) |
|---|---|
| type | ExponentialFamily.NormalWeightedMeanPrecision{Float64} |
| log scale | undefined: the message rule for GaussianCoupling towards :in under MessagePassingRulesBase.DefaultAlgorithm declares no `logscale` |
Inputs
| edge | value | |
|---|---|---|
| a | q | PointMass{Float64}(-0.5) |
Rule
| declared inputs | m[:out]::Union{ExponentialFamily.UnivariateNormalDistributionsFamily{T}, ExponentialFamily.UnivariateGaussianDistributionsFamily{T}} where T, q[:a]::BayesBase.PointMass |
|---|---|
| algorithm | DefaultAlgorithm() |
| log scale | none |
| defined | src/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])
trueSolving 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
amust be aPointMass; 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 whenw_out ⋅ w_in > a²,wbeing 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 whenAis strictly diagonally dominant.
API
The node, with its interfaces, factorisation, rules and the conditions under which GaBP is exact:
GaussianCouplingMessagePassingRules.GaussianCoupling — Type
GaussianCouplingThe 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
out: the first coupled variable, scalar; its rules take univariate normal messages.in: the second coupled variable, scalar; its rules take univariate normal messages.a: the coupling coefficient, aPointMass.
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, fromm(out)andq(a), and towardsout, fromm(in)andq(a):NormalWeightedMeanPrecision(a ⋅ mean(m), -a² ⋅ var(m)); - the joint marginal
q(out, in), fromm(out),m(in)andq(a):MvNormalWeightedMeanPrecision([ξ_out, ξ_in], [w_out -a; -a w_in]); - the average energy
⟨-log φ⟩ = -E[a] E[out ⋅ in], fromq(out, in)andq(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
outandinare 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
Ais 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.