Skip to main content

Overview

Every QuantumDevice has a set of runtime options that control the behavior of the device.run() call. These options govern which steps in the job submission pipeline are enabled, and can be updated using device.set_options(). The four default options correspond to the pipeline steps that precede job submission:
Each option corresponds to a step in the apply_runtime_profile pipeline invoked by device.run():
Disabling an option skips that step entirely. For example, setting transform=False means the program will not undergo any device-specific gate set transformations before validation.

Transform

The QuantumDevice.transform step applies device-specific transformations to the program. This is where gate decompositions, topology mapping, and other hardware-aware compilation passes are performed. The base class implementation is a no-op — each provider overrides transform() with its own logic. Setting transform=False skips this step:

IonQ

The IonQDevice.transform method decomposes the input OpenQASM program into the IonQ native gate set. It loads the program, applies gate mappings (single-qubit, two-qubit, and three-qubit), and falls back to pyqasm.unroll() if the initial transformation fails:
To skip the IonQ gate decomposition and submit the program as-is:

IBM

The QiskitBackend.transform method runs the program through a Qiskit PassManager to produce an ISA (Instruction Set Architecture) circuit compatible with the target backend. By default, it uses generate_preset_pass_manager(backend=...), but you can supply your own:
See the Provider-Specific Options section for more details on the pass_manager option.

AWS

The BraketDevice.transform method applies provider-aware transformations. For IonQ devices accessed through Amazon Braket, it routes the circuit through pytket for an expanded gate set, then applies Braket-specific transformations. For other Braket-supported devices, it applies standard device transformations through the load_program interface.

Validate

The validate step verifies that the run input satisfies all criteria for submission to the target device. This includes checks such as ensuring the number of qubits in the circuit does not exceed the device’s capacity, and that the program conforms to the device’s ProgramSpec. Validation behavior is controlled by the ValidationLevel enum:

Validation in action

By default, validation is set to RAISE. If a program violates device constraints, a ProgramValidationError is raised:

Disabling validation

To skip validation entirely, set the validation level to NONE. You can use either the enum or pass False as a shorthand:

Downgrading to warnings

To receive warnings instead of errors, set the validation level to WARN:

Re-enabling validation

To restore the default strict validation behavior:

Prepare

The prepare step serializes the quantum program into the intermediate representation (IR) required for submission to the target device’s API. This might produce a JSON payload, an OpenQASM string, bytecode, or any other format expected by the provider. The base class implementation delegates to ProgramSpec.serialize(), which is defined per-provider. For example, Pasqal Pulser sequences are serialized into a JSON-based abstract representation, and OpenQASM programs may be wrapped into a Program object with format and data fields. Setting prepare=False skips this step, leaving the program in its current in-memory representation:
This can be useful during debugging or when you want to inspect the transformed program before it gets serialized:

Provider-Specific Options

Providers can extend the default options with their own fields. These additional options are merged into the device’s configuration at initialization and follow the same set_options interface.

IBM pass_manager

The QiskitBackend adds a pass_manager option that accepts a Qiskit PassManager instance (or None). When set, the custom pass manager is used during the transform step instead of the default preset pass manager:
Reset to the default behavior by setting pass_manager back to None:
The pass_manager option includes a built-in validator that only accepts None or a PassManager instance. Attempting to set it to any other type raises a ValueError.

Advanced: RuntimeOptions

Under the hood, device options are managed by the RuntimeOptions class, a dataclass-like container with dictionary-style access, dynamic field support, and custom validators. While device.set_options() is the primary interface for users, understanding RuntimeOptions can be useful when writing a new provider.

Initializing with custom fields

Adding dynamic fields

Fields can be added at any time using attribute or dictionary syntax:

Removing dynamic fields

Dynamic (non-default) fields can be deleted. Default fields cannot be removed:

Setting validators

Validators are callables that return True for valid values. Once set, every update to the field is checked against the validator:
If a validator already exists and the current value does not satisfy the new validator, a ValueError is raised. You must update or delete the field first before replacing the validator:

Merging options

Providers use merge() to combine custom options with the device defaults. The override_validators parameter controls whether validators from the merged options replace existing ones:
This is what happens internally when you pass options to a QuantumDevice constructor, as shown in the IBM pass_manager example.