Reliability contracts

PyMAB fails explicitly when input data, component capabilities, logged-data support, or persisted results violate their contracts. Catch the most specific exception that your application can recover from; PyMABError is the common package-level base.

Run provenance

Every SimulationResult records the PyMAB, Python, and NumPy versions, the versioned random-stream scheme, and immutable snapshots of the configured environment and policies. These snapshots contain constructor configuration, not learned policy state. A migrated legacy result uses explicit "unknown" values instead of inventing provenance.

Backend selection is explicit in ExperimentConfig. backend="auto" uses Rust when every component is built in and native-compatible, then falls back to the Python reference runner for custom policies, reward models, dynamics, and callable context providers. backend="rust" requires native execution and raises one CompatibilityError listing every incompatible component; backend="python" always uses the reference runner. Inspect Experiment.backend_compatibility() before a run when fallback itself should be surfaced in application diagnostics.

Rust and NumPy use different random generators. Each backend is independently reproducible for a fixed version and seed, but stochastic trajectories are not expected to match across backends. Provenance records both the actual backend and its versioned RNG scheme.

Configuration and metadata are recursively immutable and JSON-compatible. Arrays are read-only. Use SimulationResult.equals for value comparison; mutable policies and environments intentionally retain identity equality. Built-in policy state exposed through Python is also read-only; call update, reset, or clone instead of mutating state arrays.

Persistence

JSON and compressed NPZ writes use a sibling temporary file, flush it, and atomically replace the destination. A missing .json or .npz suffix is added consistently during save and load. Wrong suffixes, malformed files, unsupported schemas, and invalid fields raise SerializationError.

Contextual experiments always record a deterministic context digest. Set ExperimentConfig(record_contexts=True) only when the complete (replicate, step, arm, feature) context tensor is needed; it can be large.

PyMAB’s public exception hierarchy.

exception CompatibilityError[source]

Bases: PyMABError, TypeError

Raised when two valid components cannot be used together.

__init__(*args, **kwargs)
classmethod __new__(*args, **kwargs)
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception OverlapError[source]

Bases: ValidationError

Raised when logged data cannot identify an off-policy estimate.

__init__(*args, **kwargs)
classmethod __new__(*args, **kwargs)
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception PyMABError[source]

Bases: Exception

Base class for errors raised by PyMAB.

__init__(*args, **kwargs)
classmethod __new__(*args, **kwargs)
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception SerializationError[source]

Bases: PyMABError

Raised when a persisted result cannot be encoded or decoded safely.

__init__(*args, **kwargs)
classmethod __new__(*args, **kwargs)
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception ValidationError[source]

Bases: PyMABError, ValueError

Raised when external data or configuration violates a contract.

__init__(*args, **kwargs)
classmethod __new__(*args, **kwargs)
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

Immutable, JSON-compatible experiment provenance.

class RunProvenance[source]

Bases: object

Runtime and component configuration needed to audit a simulation.

pymab_version: str
python_version: str
numpy_version: str
rng_scheme: str
environment: Mapping[str, None | bool | int | float | str | tuple[None | bool | int | float | str | tuple[JSONValue, ...] | Mapping[str, JSONValue], ...] | Mapping[str, None | bool | int | float | str | tuple[JSONValue, ...] | Mapping[str, JSONValue]]]
policies: Mapping[str, None | bool | int | float | str | tuple[None | bool | int | float | str | tuple[JSONValue, ...] | Mapping[str, JSONValue], ...] | Mapping[str, None | bool | int | float | str | tuple[JSONValue, ...] | Mapping[str, JSONValue]]]
backend: str = 'python'
classmethod unknown(*, pymab_version)[source]

Create an explicit placeholder when migrating legacy results.

Parameters:

pymab_version (str)

Return type:

RunProvenance

classmethod capture(*, pymab_version, environment, policies, backend='python', rng_scheme='pymab-v2-blake2b-seedsequence-v1')[source]

Capture immutable runtime and component configuration.

Parameters:
Return type:

RunProvenance

to_dict()[source]

Return a JSON-serializable provenance payload.

Return type:

dict[str, object]

equals(other)[source]

Return whether another provenance record has the same value.

Parameters:

other (object)

Return type:

bool

__init__(pymab_version, python_version, numpy_version, rng_scheme, environment, policies, backend='python')
Parameters:
Return type:

None

component_snapshot(component)[source]

Describe a configured component without serializing learned state.

Parameters:

component (object)

Return type:

Mapping[str, None | bool | int | float | str | tuple[None | bool | int | float | str | tuple[JSONValue, …] | Mapping[str, JSONValue], …] | Mapping[str, None | bool | int | float | str | tuple[JSONValue, …] | Mapping[str, JSONValue]]]

freeze_json(value, *, name='value')[source]

Return a recursively immutable JSON value.

Parameters:
Return type:

None | bool | int | float | str | tuple[JSONValue, …] | Mapping[str, JSONValue]

thaw_json(value)[source]

Convert an immutable JSON value into standard JSON containers.

Parameters:

value (None | bool | int | float | str | tuple[JSONValue, ...] | Mapping[str, JSONValue])

Return type:

None | bool | int | float | str | list[object] | dict[str, object]

Atomic, schema-aware persistence for simulation results.

class ResultSerializer[source]

Bases: object

Serialize and migrate pymab.results.SimulationResult payloads.

classmethod save_json(result, path)[source]
Parameters:
Return type:

Path

classmethod load_json(path)[source]
Parameters:

path (str | Path)

Return type:

SimulationResult

classmethod save_npz(result, path)[source]
Parameters:
Return type:

Path

classmethod load_npz(path)[source]
Parameters:

path (str | Path)

Return type:

SimulationResult

classmethod from_payload(payload)[source]
Parameters:

payload (Mapping[str, object])

Return type:

SimulationResult