Skip to content

Program Steps

The records a MonadicProgram is built from: Draw, Observe, Let, and Score, together with the Indexed argument form and reading, through which a step function declares the names it reads. The DSL compiler emits these records, so a program built from them in Python is the program the compiler would build from the equivalent source; the programs guide works through one.

program_steps

The steps a MonadicProgram is a sequence of.

A program is built from four kinds of step, each a record of the Step union:

  • Draw binds names to a sample from a morphism, applied to the program input or to earlier bindings;
  • Observe is a draw whose value is supplied as data and scored rather than sampled;
  • Let binds a name deterministically, to a constant, an alias, or a function of earlier bindings;
  • Score binds a name to a function of earlier bindings whose value also joins the log joint.

These are the records the DSL compiler emits, so a program assembled from them in Python is the program the compiler would build from the equivalent source.

A step function reads the environment by name. One that declares the names it reads, through reading, is encoded as a step over those values alone; one that declares nothing is encoded over every value bound before it, which is correct but makes a long program's encoding grow with its length.

READS module-attribute

READS = 'reads'

The attribute a step function declares the names it reads under.

Environment

Environment = dict[str, Tensor]

The bindings a step function reads, by name.

StepFunction

StepFunction = Callable[[Environment], Tensor]

A let or score step's function of the environment.

StepArgument

StepArgument = str | Indexed

One argument of a draw or observe step: a binding's name, or an Indexed gather of one.

Indexed didactic-model

Indexed(*, name: str, indices: tuple[str, ...] = field(converter=_check_indices))

Bases: Model

A binding gathered at index bindings, as mu[group] in source.

With mu of shape (K, ...) and an integer group of shape (N,), the argument has shape (N, ...). Several indices gather left to right.

ATTRIBUTE DESCRIPTION
name

The binding gathered from.

TYPE: str

indices

The integer bindings it is gathered at, at least one.

TYPE: tuple[str, ...]

Step didactic-model

Step()

Bases: TaggedUnion

One step of a MonadicProgram.

The variants are Draw, Observe, Let, and Score.

Draw didactic-model

Draw(*, names: tuple[str, ...], morphism: ContinuousMorphism | Morphism = field(opaque=True), args: tuple[StepArgument, ...] | None = field(default=None, opaque=True), kind: Literal['draw'] = 'draw')

Bases: Step

Bind names to a sample from a morphism.

In source, sample x <- f(a, b). With no arguments the morphism reads the program input; with one, it reads that binding; with several, it reads their concatenation along the feature axis, each placed by the declared parameter shape when the morphism is an inline distribution.

ATTRIBUTE DESCRIPTION
names

The names bound. One name binds the sample; several destructure a tuple-returning sub-program, or split a product-codomain sample along its components.

TYPE: tuple[str, ...]

morphism

The kernel sampled from. A Morphism is applied as a deterministic step through its tensor.

TYPE: ContinuousMorphism | Morphism

args

The bindings the morphism reads, or None for the program input.

TYPE: tuple[StepArgument, ...] | None

kind

The variant tag.

TYPE: Literal['draw']

Observe didactic-model

Observe(*, names: tuple[str, ...], morphism: ContinuousMorphism | Morphism = field(opaque=True), args: tuple[StepArgument, ...] | None = field(default=None, opaque=True), kind: Literal['observe'] = 'observe')

Bases: Step

Score supplied data under a morphism.

In source, observe y ~ f(a, b). The step reads its arguments as Draw does; its value is supplied under its name through observations when sampling and through the intermediates when scoring, and its log density joins the log joint.

ATTRIBUTE DESCRIPTION
names

The names bound to the observed value.

TYPE: tuple[str, ...]

morphism

The kernel the data are scored under.

TYPE: ContinuousMorphism | Morphism

args

The bindings the morphism reads, or None for the program input.

TYPE: tuple[StepArgument, ...] | None

kind

The variant tag.

TYPE: Literal['observe']

Let didactic-model

Let(*, name: str, value: float | str | StepFunction = field(opaque=True), kind: Literal['let'] = 'let')

Bases: Step

Bind a name deterministically.

In source, let w = expression.

ATTRIBUTE DESCRIPTION
name

The name bound.

TYPE: str

value

A constant, broadcast over the batch; the name of an earlier binding, which the step aliases; or a function of the environment, which may declare what it reads through reading.

TYPE: float | str | StepFunction

kind

The variant tag.

TYPE: Literal['let']

Score didactic-model

Score(*, name: str, score: StepFunction = field(opaque=True), kind: Literal['score'] = 'score')

Bases: Step

Bind a name to a log-density contribution.

The function's value is bound, as a let step's would be, and added to the log joint. The DSL compiler emits one for a marginalize block, whose function sums the block's scores over the marginalized variable.

ATTRIBUTE DESCRIPTION
name

The name bound.

TYPE: str

score

The contribution, of shape (batch,).

TYPE: StepFunction

kind

The variant tag.

TYPE: Literal['score']

reading

reading(function: StepCallable, names: Iterable[str]) -> StepCallable

Declare the environment names a step callable reads.

PARAMETER DESCRIPTION
function

The callable, a let or score step's value.

TYPE: StepCallable

names

The names it reads from the environment it is called with.

TYPE: Iterable[str]

RETURNS DESCRIPTION
StepCallable

The same callable, carrying the names under reads.

Source code in src/quivers/continuous/program_steps.py
def reading(
    function: StepCallable, names: collections.abc.Iterable[str]
) -> StepCallable:
    """Declare the environment names a step callable reads.

    Parameters
    ----------
    function : StepCallable
        The callable, a let or score step's value.
    names : Iterable[str]
        The names it reads from the environment it is called with.

    Returns
    -------
    StepCallable
        The same callable, carrying the names under ``reads``.
    """
    setattr(function, READS, frozenset(names))
    return function

reads_of

reads_of(function: Callable[..., object]) -> frozenset[str] | None

The environment names a step callable declares it reads.

PARAMETER DESCRIPTION
function

A let or score step's value.

TYPE: Callable

RETURNS DESCRIPTION
frozenset[str] | None

The declared names, or None when the callable declares none and may read any bound value.

Source code in src/quivers/continuous/program_steps.py
def reads_of(function: collections.abc.Callable[..., object]) -> frozenset[str] | None:
    """The environment names a step callable declares it reads.

    Parameters
    ----------
    function : Callable
        A let or score step's value.

    Returns
    -------
    frozenset[str] | None
        The declared names, or ``None`` when the callable declares none
        and may read any bound value.
    """
    names = getattr(function, READS, None)
    if names is None:
        return None
    assert isinstance(names, frozenset)
    return names