Skip to content

Delay


abstract class Delay

Base class for objects supporting delayed sampling.

classDiagram Delay <|-- Expression Delay <|-- Distribution Expression <|-- Random link Delay "../Delay/" link Expression "../Expression/" link Random "../Random/"

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 M-path for delayed sampling is kept as a singly-linked list of Delay objects directed from root to leaf along the M-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):

graph LR R1((R1)) --> D2((D2)) --> R2((R2)) --> D3((D3))

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:

graph LR R1((R1)) --> D2((D2)) --> R2((R2)) --> D3((D3)) --> R3((R3)) R3((R3)) .-> D3

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 M-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.

Note

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 M-path it is collected, usually along with the next Distribution in the list. Not only has it then been marginalized out in establishing the M-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:

graph LR R1((R1)) --> D2((D2)) --> R2((R2)) --> D3((D3)) --> R3((R3)) --> D4((D4))

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

graph LR R1((R1)) --> D2((D2)) --> R2((R2)) --> D3((D3)) --> R3((R3)) --> D4((D4)) --> R4((R4)) R4((R4)) .-> D4

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

graph LR R1((R1)) --> D2((D2)) --> R2((R2)) --> D3((D3)) --> R3((R3)) --> D4((D4)) --> R4
graph LR R1((R1)) --> D2((D2)) --> R2((R2)) --> D3((D3)) --> R3((R3)) --> D4((D4'))

Member Variables

Name Description
next:Delay? Next node on the M-path.
side:Delay? Side node on the M-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 M-path?
setNext Set the next node on the M-path.
getNext Get the next node on the M-path.
takeNext Set the next node on the M-path to nil and return its previous value.
getNext Get a proceeding node on the M-path.
hasSide Is there a side node on the M-path?
setSide Set the side node on the M-path.
getSide Get the side node on the M-path.
takeSide Set the side node on the M-path to nil and return its previous value.
getSide Get a proceeding side node on the M-path.
isInternal Is this an internal node on the M-path?
isSubordinate Is this a subordinate distribution?
setSubordinate Set this as a subordinate distribution.
prune Prune the M-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 M-path.

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

Get a proceeding node on the M-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 M-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 M-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 M-path.

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

Get a proceeding side node on the M-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 M-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 M-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 M-path?

hasSide

final function hasSide() -> Boolean

Is there a side node on the M-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 M-path? A node is internal if hasNext() is true, and it is not part of a loop at the end of the M-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 M-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 M-path.

setNext

final function setNext(node:Delay?)

Set the next node on the M-path.

  • node Next node.

setSide

final function setSide(node:Delay?)

Set the side node on the M-path.

  • node Side node.

setSubordinate

function setSubordinate()

Set this as a subordinate distribution.

takeNext

final function takeNext() -> Delay?

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

takeSide

final function takeSide() -> Delay?

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