Delay

abstract class Delay

Base class for objects supporting delayed sampling.

Classes derived from Delay support delayed sampling. Ostensibly this includes all Distribution and Expression classes, although among Expression classes only Random actually implements the interface.

Design & Implementation

The MM-path for delayed sampling is kept as a singly-linked list of Delay objects directed from root to leaf along the MM-path. While all objects in the path are ostensibly of abstract type Delay, they are alternately of concrete type Random and Distribution (R* denotes a Random object, D* a Distribution object):

The root is necessarily of type Random, but the leaf may be of either type Distribution (as above) or, if a Random has been associated with that Distribution, of type Random. In the latter case the final node is doubly-linked:

While, if the leaf node is of type Random, it has a backward link to its associated Distribution, note that all other nodes of type Random only have a forward link to the distribution associated with their next node on the MM-path.

User code maintains external references to the Random objects, but typically not the Distribution objects. Delayed sampling operations are triggered by the use of these references.

One advantage of this arrangement is that variable elimination naturally occurs as a result of garbage collection. Once no references remain to a Random that is the root of an MM-path it is collected, usually along with the next Distribution in the list. Not only has it then been marginalized out in establishing the MM-path, but it has now been eliminated as the program has discarded it without it ever being sampled.

Events on the list are triggered by user operations on the Random objects, to which the user code maintains references.

The graft operation occurs when the leaf node is a Random, and that Random enters the construction of a new Distribution object in a form that allows it to be marginalized out. The Distribution is appened to the list and the existing backward link remove:

If a Random is subsequently associated with the Distribution it is added as before:

If a Random leaf node must be realized it simply simulates a value from its associated distribution and removes its backward link:

Member Variables

Name Description
next:Delay? Next node on the MM-path.
side:Delay? Side node on the MM-path. This is used only for peculiar cases to establish joint distributions over two or more Randoms, such as for the normal-inverse-gamma distribution.

Member Functions

Name Description
hasNext Is there a next node on the MM-path?
setNext Set the next node on the MM-path.
getNext Get the next node on the MM-path.
takeNext Set the next node on the MM-path to nil and return its previous value.
getNext Get a proceeding node on the MM-path.
hasSide Is there a side node on the MM-path?
setSide Set the side node on the MM-path.
getSide Get the side node on the MM-path.
takeSide Set the side node on the MM-path to nil and return its previous value.
getSide Get a proceeding side node on the MM-path.
isInternal Is this an internal node on the MM-path?
isSubordinate Is this a subordinate distribution?
setSubordinate Set this as a subordinate distribution.
prune Prune the MM-path from below this.
hoist Construct a lazy expression for the log-pdf of this node.
constant Render the node constant.
isRandom Is this a random variable?
isDistribution Is this a distribution?

Member Function Details

constant

function constant()

Render the node constant.

getNext

final function getNext() -> Delay

Get the next node on the MM-path.

final function getNext(n:Integer) -> Delay?

Get a proceeding node on the MM-path.

  • n Number of steps to the desired node, e.g. 1 for the next node, 2 for the node after that, etc. Must be greater than zero.

Returns The proceeding node on the MM-path that is n steps from this. If there is no such node, returns nil. If there is a loop at the end of the MM-path, will iterate through that loop as many times as given and return non-nil.

getSide

final function getSide() -> Delay

Get the side node on the MM-path.

final function getSide(n:Integer) -> Delay?

Get a proceeding side node on the MM-path.

  • n Number of steps to the desired node, e.g. 1 for the next node, 2 for the node after that, etc. Must be greater than zero.

Returns The proceeding side node on the MM-path that is n steps from this. If there is no such node, returns nil. If there is a loop at the end of the MM-path, will iterate through that loop as many times as given and return non-nil.

hasNext

final function hasNext() -> Boolean

Is there a next node on the MM-path?

hasSide

final function hasSide() -> Boolean

Is there a side node on the MM-path?

hoist

function hoist() -> Expression<Real>?

Construct a lazy expression for the log-pdf of this node.

isDistribution

function isDistribution() -> Boolean

Is this a distribution?

isInternal

final function isInternal() -> Boolean

Is this an internal node on the MM-path? A node is internal if hasNext() is true, and it is not part of a loop at the end of the MM-path.

isRandom

function isRandom() -> Boolean

Is this a random variable?

isSubordinate

function isSubordinate() -> Boolean

Is this a subordinate distribution? A subordinate distribution is aside some other distribution.

prune

function prune() -> Delay

Prune the MM-path from below this.

Returns If this is a Random node, then this. If this is a Distribution node, then the updated Distribution for the first parent, which is now the leaf of the MM-path.

setNext

final function setNext(node:Delay?)

Set the next node on the MM-path.

  • node Next node.

setSide

final function setSide(node:Delay?)

Set the side node on the MM-path.

  • node Side node.

setSubordinate

function setSubordinate()

Set this as a subordinate distribution.

takeNext

final function takeNext() -> Delay?

Set the next node on the MM-path to nil and return its previous value.

takeSide

final function takeSide() -> Delay?

Set the side node on the MM-path to nil and return its previous value.