Hey @ElOceanografo,
Graphs in RxInfer
are undirected (in fact we don’t even have a notion of direction in the inference data structures). There are also no problems with running inference in loopy graphs, but for that you will need to initialise messages. The inference function supports the initmessages
keyword arguments precisely for this.
You can take a look at the Linear regression example, which uses loopy Belief propagation and uses the initmessages
keyword.
The @model
macro works in such a way that ~
simply creates a link between variables with a given factor. So you can even write something like
@model function loopy_model()
x = randomvar()
y = randomvar()
# This two statements create an obvious loop
x ~ Normal(mean = y, var = 1.0)
y ~ Normal(mean = x, var = 1.0)
z = datavar(Float64)
z ~ Normal(mean = x + y, var = 1.0)
end
And later on the inference
result = inference(
model = loopy_model(),
data = (z = 1.0, ),
# The inference will throw an error without the `initmessages`
initmessages = (
x = vague(NormalMeanPrecision),
),
)
Be aware, however, that loopy belief propagation usually requires many iterations to converge (and for some models it does not converge at all, there are no convergency guaranties for loopy belief propagation). By default, the inference
function performs only 1
iteration. This can be controlled with the iterations
keyword argument. You may also be interested in the convergency metric with the free_energy = true
argument as follows:
result = inference(
model = loopy_model(),
data = (z = 1.0, ),
initmessages = (
x = vague(NormalMeanPrecision),
),
iterations = 100,
free_energy = true
)
In my case it gives me the following output:
Inference results:
Posteriors | available for (y, x)
Free Energy: | Real[14.6851, 13.992, 13.2988, 12.6057, 11.9126, 11.2194, 10.5263, 9.83311, 9.13997, 8.44682 … 1.75593, 1.75593, 1.75593, 1.75593, 1.75593, 1.75593, 1.75593, 1.75593, 1.75593, 1.75593]
I can see that for this example the Free Energy values did indeed converge to a stable point.