Tutorials / Concept
Statefulness is the coding paradigm that lets AI4BayesCode take blocks built separately and run them together as one sampler. This explains what it means and why it matters.
A standard MCMC sampler is a closed loop. You give it your data, tell it how many iterations to run, and it runs to the end on its own. It assumes the quantities it conditions on are fixed. That holds when the sampler is the whole model. But when you place a sampler inside a larger model, those quantities are no longer fixed. Other blocks update them on every iteration. A regression with missing predictors has to impute those predictors before fitting the regression at each iteration, or a model's response might be a latent variable that another sampling component re-samples each iteration.
A standard sampler cannot take a changed input. The only way to give it the updated values is to reinitialize it every iteration, and reinitializing discards its internal state. Take BART for example. Its state is the ensemble of trees it has built, and it works by updating one tree at a time, conditional on the others. If BART sits inside a larger model and BART's response is updated each iteration, reinitializing it every iteration throws away the ensemble, so it can never carry out its one-tree-at-a-time updates.
A stateful block solves this. It keeps its internal state across iterations. On each iteration it receives the updated values from the other sampling component outside this block, advances its own parameters by one step, and returns its new state, without reinitializing. Three functions carry it out: set_current receives the updated inputs from outside blocks, step advances one iteration, and get_current returns its current values to other blocks.
To put that precisely, write \(\Theta\) for a block's own parameters and \(\mathcal{D}\) for the quantities it conditions on. A standard sampler holds \(\mathcal{D}\) fixed and just advances,
\[ (\Theta^{(t)},\, \mathcal{D}) \;\longrightarrow\; (\Theta^{(t+1)},\, \mathcal{D}), \]
while a stateful block takes the update to \(\mathcal{D}\) first, then advances:
\[ (\Theta^{(t)},\, \mathcal{D}^{(t)}) \;\longrightarrow\; (\Theta^{(t)},\, \mathcal{D}^{(t+1)}) \;\longrightarrow\; (\Theta^{(t+1)},\, \mathcal{D}^{(t+1)}). \]
The first arrow is set_current, the second is step. Because every block works this way, blocks built separately drop into one larger sampler and keep running, instead of reinitializing from scratch.
Worked examples are coming soon.