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, 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

  • Tutorials: Your first node declares a normal node and writes its belief propagation and variational rules. A deterministic node with a group writes rules for a sum of any number of inputs. A node with its own algorithm gives a node a parametrised algorithm and declares what its rules take. A new message passing scheme writes natural-gradient message passing as an algorithm and its rules.
  • Defining nodes: @define_factor_node, what a declaration records, and the queries that read it.
  • Defining rules: the three rule macros, targets, the inputs a rule receives, the slots of its body, in-place rules, scratch memory and annotations.
  • Algorithms and dependencies: how the factorisation selects belief propagation, variational message passing or their structured form under the default algorithm. The page also covers a node's own algorithm, extensions of the default, parametrised algorithms, @define_dependencies and initial messages.
  • Log scales: what a rule declares about the normalising constant of its message, and how a rule reads the log scales of its inputs.
  • The rule context: the services a rule reads from ctx, and who checks them.
  • Calling rules: how to call a rule by hand, read its result and find out why no rule fits, and how code resolves and runs rules.
  • Inspecting rules: which rule a call would run, and how to list, tabulate and check the rules that exist.
  • Rule fallbacks: what an engine may send where no rule fits.
  • Math helpers: the linear algebra and Gaussian algebra the rule packages share.
  • Keyword reference: every keyword of every macro, in one place.
  • Glossary: the terms these pages use.
  • Internals: the calls an engine makes to run a resolved rule, and internal helpers.