Sprinkler system
This is the rain-sprinkler-wet-grass system from the Wikipedia entry on Bayesian Networks. It features a number of discrete (boolean) random variables, an observation (the grass is wet) and an variational posterior distribution that is optimized to approximate the exact posterior.
// posterior distribution for the sprinkler.
// It is conditional on rain.
// Parameters run over the full real axis, the
// sigmoid maps it to the domain [0,1].
val inRain = BBVIGuide(Bernoulli(sigmoid(Param(0.0))))
val noRain = BBVIGuide(Bernoulli(sigmoid(Param(0.0))))
// posterior distribution for the rain
val rainPost = BBVIGuide(Bernoulli(sigmoid(Param(0.0))))
// full model of the rain-sprinkler-grass system.
val model = infer {
// conditional sampling of the sprinkler.
// The probability that the sprinkler turned on
// is dependent on whether it rained or not.
def sprinkle(rain: Boolean): Boolean = {
if (rain) {
sample(Bernoulli(0.01), inRain)
} else {
sample(Bernoulli(0.4), noRain)
}
}
val rain = sample(Bernoulli(0.2), rainPost)
val sprinkled = sprinkle(rain)
val p_wet = (rain, sprinkled) match {
case (true, true) => 0.99
case (false, true) => 0.9
case (true, false) => 0.8
case (false, false) => 0.001
}
// bind model to data / add observation
observe(Bernoulli(p_wet), true)
// return quantity we're interested in
rain
}
The example shows a number of features:
- control flow (
if (...) ... else ...
) can be based on random variables - it’s possible to define functions of random variables