Messages implementation

In our message passing framework one of the most important concepts is the message (wow!). Messages flow along edges of a factor graph and hold information about the part of the graph that it originates from. Usually this information is in a form of a probability distribution. Two common messages are belief propagation messages and variational messages, with are computed differently as shown below.

Abstract message type

Both belief propagation and variational messages are subtypes of a AbstractMessage supertype.

Belief-Propagation (or Sum-Product) message

message Belief propagation message

Variational message

message Variational message with structured factorisation q(x, y)q(z) assumption

Message type

All messages are encoded with the type Message.

ReactiveMP.MessageType
Message{D, A} <: AbstractMessage

Message structure encodes a Belief Propagation message, which holds some data that usually a probability distribution, but can also be an arbitrary object. Message acts as a proxy structure to data object and proxies most of the statistical functions, e.g. mean, mode, cov etc.

Arguments

  • data::D: message always holds some data object associated with it
  • is_clamped::Bool, specifies if this message is clamped
  • is_initial::Bool, specifies if this message is initial
  • addons::A, specifies the addons of the message

Example

julia> distribution = Gamma(10.0, 2.0)
Gamma{Float64}(α=10.0, θ=2.0)

julia> message = Message(distribution, false, true, nothing)
Message(Gamma{Float64}(α=10.0, θ=2.0))

julia> mean(message) 
20.0

julia> getdata(message)
Gamma{Float64}(α=10.0, θ=2.0)

julia> is_clamped(message)
false

julia> is_initial(message)
true

See also: AbstractMessage, ReactiveMP.materialize!

source

From an implementation point a view the Message structure does nothing but hold some data object and redirects most of the statistical related functions to that data object. However, this object is used extensively in Julia's multiple dispatch. Our implementation also uses extra is_initial and is_clamped fields to determine if product of two messages results in is_initial or is_clamped posterior marginal. The final field contains the addons. These contain additional information on top of the functional form of the distribution, such as its scaling or computation history.

distribution = NormalMeanPrecision(0.0, 1.0)
message      = Message(distribution, false, true, nothing)
Message(NormalMeanPrecision{Float64}(μ=0.0, w=1.0))
mean(message), precision(message)
(0.0, 1.0)
logpdf(message, 1.0)
-1.4189385332046727
is_clamped(message), is_initial(message)
(false, true)

The user should not really interact with Message structure while working with ReactiveMP unless doing some advanced inference procedures that involve prediction.