boundlab.Expr#

class boundlab.Expr[source]#

Bases: ABC

Abstract base of every BoundLab expression component.

Subclasses implement the primitives below; the base class derives the whole tensor-algebra surface (+, -, *, @, reductions, conversion, concretization) from them. All linear structure is funnelled through einsum(), so a component only has to know how a linear map acts on its own representation to be sound under every derived operation.

Methods

__init__

absub

Bound on the magnitude: \(\max(|lb|, ub) \ge \sup |x|\).

add

Same-class addition; __add__ dispatches here when classes match and otherwise groups the addends in an ExprGroup.

broadcast_to

chw

Center/halfwidth form: c = (ub + lb) / 2, w = (ub - lb) / 2.

classset

The set of component classes present in this value.

convert_from

Hook: build an instance of cls representing exactly expr, or None when this class cannot.

convert_to

Hook: convert self into expr_type, or None when this class does not know how.

einsum

Apply the linear map described by an integer-label einsum.

from_exprlike

Lift a tensor/scalar into a broadcast Bias; pass Expr through.

lb

Sound elementwise lower bound on every concrete value represented.

lbub

(lb, ub) in one call; components override it when computing both at once is cheaper than two passes.

matmul

mean

numel

reshape

rmatmul

split

Split into (matching, rest) so that matching + rest == self.

squeeze

sum

to

Convert to another component class, exactly.

to_intervals

Collapse to the box hull Bias(c) + Noise(w).

torch_print

Diagnostics as a TensorFormat.

transpose

ub

Sound elementwise upper bound on every concrete value represented.

unsqueeze

abstract property shape_dtype: ShapeDtype#

Allocation-free (shape, dtype) metadata of the value.

abstractmethod einsum(subscripts, *operands)[source]#

Apply the linear map described by an integer-label einsum.

subscripts holds one label tuple per input followed by the output labels (see boundlab.utils.einsum_parser()). This is the single linear primitive: __mul__, __matmul__, sum and mean all lower to it, so implementing it soundly makes every derived linear operation sound.

abstractmethod reshape(*shape)[source]#
abstractmethod transpose(*perm)[source]#
abstractmethod broadcast_to(*shape)[source]#
abstractmethod add(other)[source]#

Same-class addition; __add__ dispatches here when classes match and otherwise groups the addends in an ExprGroup.

abstractmethod ub()[source]#

Sound elementwise upper bound on every concrete value represented.

abstractmethod lb()[source]#

Sound elementwise lower bound on every concrete value represented.

property shape: Sequence[Any]#
property dtype: dtype#
lbub()[source]#

(lb, ub) in one call; components override it when computing both at once is cheaper than two passes.

absub()[source]#

Bound on the magnitude: \(\max(|lb|, ub) \ge \sup |x|\).

chw()[source]#

Center/halfwidth form: c = (ub + lb) / 2, w = (ub - lb) / 2.

final to_intervals(name='')[source]#

Collapse to the box hull Bias(c) + Noise(w).

Sound but lossy: every correlation between error symbols is dropped, so downstream cancellation (x - x = 0) no longer happens.

property ndim: int#
final numel()[source]#
static from_exprlike(expr, shape)[source]#

Lift a tensor/scalar into a broadcast Bias; pass Expr through.

final __add__(other)[source]#
__mul__(other)[source]#
property T: Self#
squeeze(axes=None)[source]#
unsqueeze(axes)[source]#
sum(axis, keepdims=False)[source]#
mean(axis, keepdims=False)[source]#
matmul(other)[source]#
rmatmul(other)[source]#
torch_print(group='reason')[source]#

Diagnostics as a TensorFormat.

The result is safe to hand to Torch diagnostic output under tracing: only plain arrays cross the callback boundary, never expression metadata (which may hold tracers, e.g. reason weights).

classmethod convert_from(expr)[source]#

Hook: build an instance of cls representing exactly expr, or None when this class cannot. One half of to().

convert_to(expr_type)[source]#

Hook: convert self into expr_type, or None when this class does not know how. The other half of to().

final to(expr_type)[source]#

Convert to another component class, exactly.

Identity short-circuits; otherwise the target’s convert_from is tried, then this class’s convert_to. Raises TypeError when neither side knows the conversion — conversions never approximate.

final classset()[source]#

The set of component classes present in this value.

A single component reports {type(self)}, an ExprGroup its member classes, and Zeros the empty set. Handlers use this to decide which part of a value they know how to transform.

split(ty)[source]#

Split into (matching, rest) so that matching + rest == self.

The main way handlers peel off the component class they transform while passing the remainder through untouched.