MessagePassingRulesBase

MessagePassingRulesBase is the rule system of the ReactiveMP ecosystem. It declares factor nodes and the rules they compute. It finds the rule for a call and runs it, without an inference engine.

This site is for rule authors, who define nodes and rules for a package of their own, started from the template, and for students who want to see how a message passing rule works by calling one. Engine authors find the calls that look rules up and run them on the Internals page.

You use the package for three things:

  • to define a node and its rules, as every rule package does;
  • to call a rule by hand, at the REPL or in a test;
  • to look rules up and run them, from an engine.

A rule is an ordinary Julia function of its inputs. Julia dispatches it on the node, on the target and on the types of the incoming messages and marginals. Because resolution is Julia's own dispatch, a rule defined in any loaded package is found.

The package depends on BayesBase and on small numerical packages (FastCholesky, IrrationalConstants). It depends on no distribution package and on no engine. It also holds the math helpers that the rule packages share.

MessagePassingRulesBase.MessagePassingRulesBase — Module
MessagePassingRulesBase

The rule system of message passing on factor graphs: the macros that declare factor nodes, their message update rules, marginal rules, average energies and dependencies, and the lookup an engine uses to find and run a rule for a node, a target and the types of its inputs. Rules are ordinary functions of their inputs, callable and testable without an engine, and found through Julia's dispatch, whichever loaded package defines them.

It depends on BayesBase and small numerical packages, not on a distribution package or an engine.

Examples

julia> struct Shift end

julia> @define_factor_node(node = Shift, type = Deterministic, interfaces = [:out, :in])

julia> @define_message_update_rule(
           node = Shift, target = :out, args = (m[:in]::Real,), logscale = 0,
           body = (args) -> args.m[:in] + 1,
       )

julia> getresult(@call_message_update_rule(node = Shift, target = :out, m = (in = 1.0,)))
2.0
source
Where these rules run

The ReactiveMP engine runs these rules on a factor graph, which RxInfer builds from a model. The examples on this site call the rules directly, as a test does.

A first node and rule

A node, out = in + 1, with one rule, for the message towards out, called as an engine would call it:

julia> using MessagePassingRulesBase

julia> struct Shift end   # out = in + 1

julia> @define_factor_node(node = Shift, type = Deterministic, interfaces = [:out, :in])

julia> @define_message_update_rule(
           node = Shift, target = :out, args = (m[:in]::Real,), logscale = 0,
           body = (args) -> args.m[:in] + 1,
       )

julia> result = @call_message_update_rule(node = Shift, target = :out, m = (in = 1.0,));

julia> getresult(result), getlogscale(result)
(2.0, 0)

Your first node builds a real node step by step, and explains each part.

The site