# Custom Functional Form Specification

In a nutshell, functional form constraints defines a function that approximates the product of colliding messages and computes posterior marginal that can be used later on during the inference procedure. An important part of the functional forms constraint implementation is the `prod`

function. More information about `prod`

function is present in the Prod Implementation section. For example, if we refer to our `CustomFunctionalForm`

as to `f`

we can see the whole functional form constraints pipeline as:

\[q(x) = f\left(\frac{\overrightarrow{\mu}(x)\overleftarrow{\mu}(x)}{\int \overrightarrow{\mu}(x)\overleftarrow{\mu}(x) \mathrm{d}x}\right)\]

## Interface

`ReactiveMP.jl`

, however, uses some extra utility functions to define functional form constraint behaviour. Here we briefly describe all utility function. If you are only interested in the concrete example, you may directly head to the Custom Functional Form example at the end of this section.

### Abstract super type

`ReactiveMP.AbstractFormConstraint`

— Type`AbstractFormConstraint`

Every functional form constraint is a subtype of `AbstractFormConstraint`

abstract type.

Note: this is not strictly necessary, but it makes automatic dispatch easier and compatible with the `CompositeFormConstraint`

.

See also: `CompositeFormConstraint`

### Form check strategy

Every custom functional form must implement a new method for the `default_form_check_strategy`

function that returns either `FormConstraintCheckEach`

or `FormConstraintCheckLast`

.

`FormConstraintCheckLast`

:`q(x) = f(μ1(x) * μ2(x) * μ3(x))`

`FormConstraintCheckEach`

:`q(x) = f(f(μ1(x) * μ2(x)) * μ3(x))`

`ReactiveMP.default_form_check_strategy`

— Function`default_form_check_strategy(form_constraint)`

Returns a default check strategy (e.g. `FormConstraintCheckEach`

or `FormConstraintCheckEach`

) for a given form constraint object.

See also: `FormConstraintCheckEach`

, `FormConstraintCheckLast`

, `constrain_form`

`ReactiveMP.FormConstraintCheckEach`

— Type`FormConstraintCheckEach`

This form constraint check strategy checks functional form of the messages product after each product in an equality chain. Usually if a variable has been connected to multiple nodes we want to perform multiple `prod`

to obtain a posterior marginal. With this form check strategy `constrain_form`

function will be executed after each subsequent `prod`

function.

See also: `FormConstraintCheckLast`

, `default_form_check_strategy`

, `constrain_form`

, `multiply_messages`

`ReactiveMP.FormConstraintCheckLast`

— Type`FormConstraintCheckEach`

This form constraint check strategy checks functional form of the last messages product in the equality chain. Usually if a variable has been connected to multiple nodes we want to perform multiple `prod`

to obtain a posterior marginal. With this form check strategy `constrain_form`

function will be executed only once after all subsequenct `prod`

functions have been executed.

See also: `FormConstraintCheckLast`

, `default_form_check_strategy`

, `constrain_form`

, `multiply_messages`

### Prod constraint

Every custom functional form must implement a new method for the `default_prod_constraint`

function that returns a proper `prod_constraint`

object.

`ReactiveMP.default_prod_constraint`

— Function`default_prod_constraint(form_constraint)`

Returns a default prod constraint needed to apply a given `form_constraint`

. For most form constraints this function returns `ProdGeneric`

.

See also: `ProdAnalytical`

, `ProdGeneric`

### Constrain form, a.k.a `f`

The main function that a custom functional form must implement, which we referred to as `f`

in the beginning in this section, is the `constrain_form`

function.

`ReactiveMP.constrain_form`

— Function`constrain_form(form_constraint, distribution)`

This function must approximate `distribution`

object in a form that satisfies `form_constraint`

.

See also: `FormConstraintCheckEach`

, `FormConstraintCheckLast`

, `default_form_check_strategy`

, `is_point_mass_form_constraint`

### Is point mass form constraint (optional)

Every custom functional form may implement a new method for the `is_point_mass_form_constraint`

function that returns either `true`

or `false`

. This is an utility function that simplifes computation of the Bethe Free Energy and is not strictly necessary.

`ReactiveMP.is_point_mass_form_constraint`

— Function`is_point_mass_form_constraint(form_constraint)`

Specifies whether form constraint always returns PointMass estimates or not. For a given `form_constraint`

returns either `true`

or `false`

.

See also: `FormConstraintCheckEach`

, `FormConstraintCheckLast`

, `constrain_form`

### Compatibility with `@constraints`

macro (optional)

To make custom functional form constraint compatible with the `@constraints`

macro, it must implement a new method for the `make_form_constraint`

function.

`ReactiveMP.make_form_constraint`

— Function`make_form_constraint(::Type, args...; kwargs...)`

Creates form constraint object based on passed `type`

with given `args`

and `kwargs`

. Used to simplify form constraint specification.

As an example:

`make_form_constraint(PointMass)`

creates an instance of `PointMassFormConstraint`

and

`make_form_constraint(SampleList, 5000, LeftProposal())`

should create an instance of `SampleListFormConstraint`

.

See also: `AbstractFormConstraint`

## Custom Functional Form Example

In this demo we show how to build a custom functional form constraint that is compatible with the `ReactiveMP.jl`

inference backend. An important part of the functional forms constraint implementation is the `prod`

function. More information about `prod`

function is present in the Prod Implementation section. We show a relatively simple use-case, which might not be very useful in practice, but serves as a simple step-by-step guide. Assume that we want a specific posterior marginal of some random variable in our model to have a specific Gaussian parametrisation, for example mean-precision. We can use built-in `NormalMeanPrecision`

distribution, but we still need to define our custom functional form constraint:

```
using ReactiveMP, GraphPPL
# First we define our functional form structure with no fields
struct MeanPrecisionFormConstraint <: AbstractFormConstraint end
```

Next we define the behaviour of our functional form constraint:

```
ReactiveMP.is_point_mass_form_constraint(::MeanPrecisionFormConstraint) = false
ReactiveMP.default_form_check_strategy(::MeanPrecisionFormConstraint) = FormConstraintCheckLast()
ReactiveMP.default_prod_constraint(::MeanPrecisionFormConstraint) = ProdGeneric()
function ReactiveMP.constrain_form(::MeanPrecisionFormConstraint, distribution)
# This is quite a naive assumption, that a given `dsitribution` object has `mean` and `precision` defined
# However this quantities might be approximated with some other external method, e.g. Laplace approximation
m = mean(distribution) # or approximate with some other method
p = precision(distribution) # or approximate with some other method
return NormalMeanPrecision(m, p)
end
function ReactiveMP.constrain_form(::MeanPrecisionFormConstraint, distribution::DistProduct)
# DistProduct is the special case, read about this type more in the corresponding documentation section
# ...
end
```

At this point we already can use our functional form constraint in the inference backend, however, lets also make our functional form constraint compatible with the `@constraints`

macro from `GraphPPL.jl`

package.

`ReactiveMP.make_form_constraint(::Type{ NormalMeanPrecision }, args...; kwargs...) = MeanPrecisionFormConstraint()`

```
@constraints begin
q(x) :: NormalMeanPrecision
end
```

```
Constraints:
marginals form:
q(x) :: Main.MeanPrecisionFormConstraint() [ prod_constraint = ProdGeneric(fallback = ProdAnalytical()) ]
messages form:
factorisation:
Options:
warn = true
```