DataBindingStage

class DataBindingStage(data_params, loss_reduction, loss_constant=0.0, sample_loss=None)[source]

Bases: BundleStage

Fan a parametric circuit out over a classical feature batch.

Each row of env.feature_batch becomes a body variant whose data_params are pre-bound to that sample’s values. Downstream stages see a weight-only parametric circuit; the per-sample results are aggregated on the backward pass via loss_reduction.

The stage owns only the data axis — which parameters are bound from data, how per-sample results are reduced, and the optional supervised loss. The circuit and the weight parameters come from the incoming MetaCircuit batch (weights are parameters minus data_params, order preserved), and the feature_batch / labels come from the PipelineEnv at run time — so one stage serves any batch (train, mini-batch, or inference).

The stage owns two implementations of expand(), selected at pipeline-construction time via validate():

  • Template fast path (default when no DAG-walking stage sits downstream): builds the parametric QASM body from the incoming DAG once (cached), renders per-sample partial bodies as strings (data substituted, weight placeholders preserved), and parks them on MetaCircuit.qasm_bodies keyed by body_tag. All variants share the incoming parametric DAG ref in circuit_bodies (~O(1) DAG memory regardless of batch size). ParameterBindingStage’s fast path consults the pre-rendered bodies and skips its DAG → QASM step.

  • Eager fallback path (used when QEM, Pauli twirling, or any other stage with consumes_dag_bodies=True sits between this stage and ParameterBinding): substitutes each sample’s data into its own bound DAG. Memory scales linearly with batch size, but per-sample DAGs are required because downstream stages walk them.

Parameters:
  • data_params (tuple[Parameter, ...]) – The Qiskit Parameter objects bound from data. Their order must match env.feature_batch’s column order. Everything else in the incoming MetaCircuit.parameters is treated as a weight and handed downstream (order preserved).

  • loss_reduction (Callable[[ndarray[tuple[Any, ...], dtype[double]]], float]) – Callable (n_samples,) float applied during reduce() to collapse one base-key’s per-sample expectation values into a single scalar. Invoked once per observable when the upstream measurement stage returns a per-observable list.

  • loss_constant (float) – Constant added to each per-sample expectation value before loss_reduction, so reductions apply to the full (unshifted) loss.

  • sample_loss (Callable[[float, float], float] | None) – Optional per-sample loss (prediction, label) float (e.g. squared error). When set and env.labels is provided, each per-sample prediction is mapped through it against its label before loss_reduction — turning the unsupervised aggregate into a supervised training loss.

Attributes Summary

axis_name

Axis name introduced by this stage.

handles_measurement

Whether this stage sets up measurement circuits and result format.

Methods Summary

dry_expand(batch, env)

Dry path: share the incoming parametric DAG across all sample variants.

expand(batch, env)

Transform keyed MetaCircuit batch and return expansion lineage plus token.

introspect(batch, env, token)

Return stage-specific metadata for dry-run reporting.

reduce(results, env, token)

Identity by default; override if this stage reduces results.

validate(before, after)

Pick template vs. eager path based on downstream DAG consumers.

Attributes Documentation

axis_name
handles_measurement

Methods Documentation

dry_expand(batch, env)[source]

Dry path: share the incoming parametric DAG across all sample variants. Per-sample data substitution is skipped — dry-run only needs correct circuit counts and depth/width stats, both of which are invariant under data binding.

Return type:

tuple[ExpansionResult, Any]

expand(batch, env)[source]

Transform keyed MetaCircuit batch and return expansion lineage plus token.

Return type:

tuple[ExpansionResult, Any]

introspect(batch, env, token)[source]

Return stage-specific metadata for dry-run reporting.

Override in subclasses to provide richer introspection data. Called by the dry-run tool after expand with the post-expand batch, the pipeline env, and the stage’s token.

Return type:

dict[str, Any]

reduce(results, env, token)[source]

Identity by default; override if this stage reduces results.

Return type:

dict[Any, Any]

validate(before, after)[source]

Pick template vs. eager path based on downstream DAG consumers.

The template path emits per-sample QASM strings and a shared parametric DAG; it requires that no downstream stage walk circuit_bodies gate-by-gate. A stage is treated as a DAG-walker only when its forward pass is not structurally a no-op:

  • ParameterBindingStage is transparent — its fast path reads the parked qasm_bodies and never touches the shared DAG.

  • QEMStage with the default _NoMitigation protocol is transparent — its expand returns the input DAG unchanged.

  • Everything else with consumes_dag_bodies=True (active QEM protocols, PauliTwirlStage, user-defined DAG-mutating stages) forces the eager fallback.

Return type:

None