Skip to content

Result Types

The standalone and handler-based APIs return dataclasses.

Common base for results from the NumPyro-free conditioning primitive.

dsx.condition returns this type under both Filter and Smoother. It carries the complete inference output through the handler stack without registering NumPyro sites. Filter results may additionally expose the canonical one-step-ahead predicted_observations and an evaluation_result attached by an outer evaluation handler. Posterior distributions are time-major: dists[i] corresponds to times[..., i]. Leading axes on times are optional plate axes, while each distribution may carry the matching plate axes in its batch shape.

Outputs computed by an evaluation handler.

Evaluation handlers attach this object to the ConditionedResult they consume. NumPyro registration remains deferred so dsx.condition stays side-effect free while dsx.sample can register the same outputs later.

Bases: Module

Result of simulation without eager NumPyro side effects.

This result therefore stores the realized state path x and observation path y produced on the requested simulator time grid.

For raw forward simulation, times, x_0, states, and observations are populated. The field names match their NumPyro site suffixes. When a simulator is layered outside a Filter or Smoother for posterior rollout, the same result object instead carries predicted_times, predicted_states, and predicted_observations.

Simulator outputs always retain a trailing coordinate axis: x_0 has shape (*plate, n_simulations, state_coordinates), and paths have shape (*plate, n_simulations, time, coordinates). Scalar states, categorical labels, and scalar observations use a singleton coordinate axis.

obs_times and ctrl_times record where observations and controls actually sit -- the names match the obs_times / ctrl_times keywords used elsewhere in the API. They need not equal times, so read alignment off these fields rather than inferring it from array lengths: e.g. open-loop "previous_transition" observes on times[1:] and controls on times[:-1].

obs_times is populated by every simulator. ctrl_times accompanies controls: populated by DiscreteTimeSimulator (when controls are supplied) and DiscreteControlLoopSimulator, and None for an uncontrolled model or for ODE/SDE simulators, which do not record controls yet.

For open-loop simulation of a discrete-time model with dynamics.observation_control_alignment="previous_transition", states are of length :math:T (matching times), while observations and controls are of length :math:T-1. Closed-loop simulation currently runs this convention only (an unspecified field resolves to it; an explicit "same_time" is not implemented yet), so it returns the same shapes. In both cases, :math:y_0 is never sampled because there is no control that produced it.

See DiscreteTimeSimulator.

unflatten(layout: LayoutCollection) -> StructuredSimulatedResult

Return a structured copy of this result.

Each populated state, control, and observation field (including x_0 and the predicted_* fields) is converted by the matching sublayout of layout. Fields whose sublayout is None and time fields are copied unchanged. StructuredSimulatedResult.flatten undoes the conversion.

Bases: Module

A SimulatedResult with structured values.

Returned by SimulatedResult.unflatten. It has the same fields, but x_0, states, controls, observations, predicted_states, and predicted_observations may be pytrees of arrays, as described by the sublayouts of a LayoutCollection. Leaves keep the leading batch and time axes of the flat field. Time fields are never converted.

This is a user-facing helper: Dynestyx itself only consumes flat results. flatten(layout) converts back to a SimulatedResult.

flatten(layout: LayoutCollection) -> SimulatedResult

Return the flat result that unflatten(layout) converted.

layout must be the LayoutCollection passed to unflatten. Raises ValueError if a structured field has no sublayout.