How Conditioning and Scoring Works
A sample path is the course of a program as it executes, hence being the monadic context that the code is executing in. During this path, a new thread created for every random decision. It can be thought of as an execution trace. In probabilistic programming, each sample path is associated with a probability of how likely that execution trace is to happen. This probability is the joint probability of a bunch of random decisions made during the execution of the program. Some of this may be related to the actual variables in the model used (such as a latent variable we define), but if there is a random decision made, it will also be joint with the random variable corresponding to that random decision.
class Monad m => MonadCond m where
score :: Log R -> m ()
The score
function manually updates the probability of a sample path the program is on. For the most part, the probability of each sample path is hard-coded in all the random decisions we make - but the function score
acts like an override. When the user calls score
midway in a program to update the probability by some specified factor (for example the likelihood that an observed variable y is generated by a latent variable x), they explicitly supply the likelihood resulting from a conditioning operation. This tells the program to update the sample path’s associated probability such that during the execution path’s hard-coded updating of its probability it is as though the program notices “oh, i have some data here to compare to and hence update the sample path’s probability appropriately”. The fact that score
can be called on a double that is calculated by some specific equation is incidental to whatever algorithm, model, or statistical context is implemented in the program.