transaction
¶
Transaction, a retryable, all-or-nothing block of correlated random draws for StochasBase.
Transaction
dataclass
¶
Transaction(
base: StochasBase,
retry_on: type[Exception] | tuple[type[Exception], ...],
max_retries: int,
)
Iterable of retry attempts returned by StochasBase.transaction().
Construct via Transaction.begin(), which snapshots base.dists, base.design, and base.named. A failed attempt (retryable or not) rolls back to that snapshot before the exception is either suppressed (to retry) or allowed to propagate, so a transaction only ever commits the registrations made by the attempt that succeeds.
begin
classmethod
¶
begin(
base: StochasBase,
retry_on: type[Exception],
max_retries: int = 10,
) -> Self
begin(
base: StochasBase,
retry_on: type[Exception] | tuple[type[Exception], ...],
max_retries: int = 10,
) -> Self
Starts a transaction, snapshotting base.dists, base.design, and base.named for rollback.
Source code in src/stochas/transaction.py
TransactionAttempt
dataclass
¶
TransactionAttempt(transaction: Transaction)
One attempt of a StochasBase.transaction(); use as with attempt:.
base
property
¶
base: StochasBase
The StochasBase model this transaction is retrying against: the one .transaction() was called on. Use it for anything not wrapped below, e.g. attempt.base.with_seed(...) or attempt.base.model_dump().
sample_dist
¶
sample_dist(
dist: Distribution[T],
size: int = 1,
force: bool = False,
warn: bool = True,
convert_units: bool = True,
) -> NamedValue[NDArray[Any, T]]
Samples dist via attempt.base (the model this transaction is retrying against), reseeding it only the first time this transaction sees dist.name.
Without this, every attempt would reset the distribution's RNG to the same state and draw the exact same (rejected) value forever. reset_rng is therefore not exposed here; it is derived from whether this transaction has already seeded dist.name, tracked by the actual instance last used (Transaction._seeded, a DistributionDict) rather than the name alone. A caller may pass a brand-new Distribution instance with the same name on every attempt instead of reusing one, and dist.adopt_prior_state transplants the previous instance's seed, trial number, and live _rng stream onto the new one so both patterns draw identical values.
If that carried-over state leaves dist.is_nominal true, every remaining attempt for this name is going to deterministically return the same already-rejected nominal value; this is worth a warning, logged once per name per transaction rather than once per retry.
Source code in src/stochas/transaction.py
sample_design
¶
sample_design(
dv: DesignFloat,
force: bool = False,
warn: bool = True,
convert_units: bool = True,
) -> float
sample_design(
dv: DesignInt,
force: bool = False,
warn: bool = True,
convert_units: bool = True,
) -> int
sample_design(
dv: DesignBool,
force: bool = False,
warn: bool = True,
convert_units: bool = True,
) -> bool
sample_design(
dv: DesignCategorical[T],
force: bool = False,
warn: bool = True,
convert_units: bool = True,
) -> T
sample_design(
dv: AnyDesignValue,
force: bool = False,
warn: bool = True,
convert_units: bool = True,
) -> Any
Samples dv via attempt.base (the model this transaction is retrying against).
Design variables aren't RNG-backed (an optimizer, not stochas, picks their value), so there's no reseeding to manage here: this is a plain passthrough to StochasBase.sample_design, kept on TransactionAttempt so a design variable stays fixed for the duration of one attempt and rolls back with everything else on a rejected one, exactly like sample_dist.