IQMBackend#

Module: iqm.qrisp_iqm.backends

class iqm.qrisp_iqm.backends.IQMBackend(server_url: str | None = None, *, device_instance: str | None = None, transpiler: Callable[[QuantumCircuit], QuantumCircuit] | None = None, calibration_set_id: UUID | str | None = None, use_metrics: bool = False, pass_manager: PassManager | None = None, use_timeslot: bool = False, compilation_options: CircuitCompilationOptions | None = None, compiler: Compiler | None = None, **user_auth_args)#

Bases: Backend

Qrisp backend for executing circuits on IQM quantum hardware.

After transpilation, run_async() automatically detects whether any of the circuits contains IQMPulseOperation instructions, and routes the job to the appropriate submission path:

  • No pulse ops → submitted as a gate-level IQMCircuitJob.

  • Has pulse ops → compiled locally down to pulse level, and submitted as a IQMPulseJob.

The server_url and device_instance parameters can alternatively be provided as the environment variables IQM_SERVER_URL and IQM_QUANTUM_COMPUTER. If the server requires user authentication, you can provide it either using environment variables or as keyword arguments. The user authentication kwargs are passed through to IQMClient as is, and are documented there.

Parameters:
  • server_url (str | None) – URL for connecting to a quantum computer. If None, use environment variable IQM_SERVER_URL.

  • device_instance (str | None) – IQM quantum computer identifier (e.g., "garnet"). If None, use environment variable IQM_QUANTUM_COMPUTER. If it is not defined, use the default quantum computer on the server.

  • user_auth_args – User authentication information, e.g. an API token.

  • transpiler (Callable[[QuantumCircuit], QuantumCircuit] | None) –

    Deprecated since version Use: pass_manager instead.

    Transforms quantum circuits for hardware compatibility. If provided, a DeprecationWarning is raised and the callable is wrapped in a CircuitPass and installed as the sole pass in the PassManager. Must not be used together with pass_manager.

  • calibration_set_id (UUID | str | None) – ID of the calibration set to use. None means the server’s current default calibration set is used.

  • use_metrics (bool) – Iff True, the backend will query the server for calibration data and related quality metrics, and pass these to the default pass manager. Currently a no-op — the flag is stored and will be wired into both submission paths in a future release.

  • pass_manager (PassManager | None) –

    PassManager for circuit transpilation. Accepted values:

    • None: Builds a pre-configured PassManager that performs routing, layout and other optimization to bring good performance without configuration overhead.

    • A PassManager instance: Used directly for transpilation, bypassing the default pipeline entirely.

  • use_timeslot (bool) – If True, submits the job to the timeslot queue. If False, the job is submitted to the normal on-demand queue.

  • compilation_options (CircuitCompilationOptions | None) – Options for compiling circuits to pulse schedules. On the pulse-level execution path, the CircuitCompilationOptions.max_circuit_duration_over_t2 attribute has no effect. None means use the default options.

  • compiler (Compiler | None) – IQM circuit-to-pulse compiler to use for pulse-level submissions. None uses the standard compiler.

Examples: Automatic transpilation (default PassManager):

>>> from iqm.qrisp_iqm import IQMBackend
>>> backend = IQMBackend(
...     token="YOUR_API_TOKEN",
...     device_instance="garnet"
... )
>>> from qrisp import QuantumCircuit
>>> qc = QuantumCircuit(2)
>>> qc.h(0)
>>> qc.cx(0, 1)
>>> qc.measure(qc.qubits)
>>> result = backend.run(qc, shots=1000)

Custom pass pipeline via :attr:`pm`:

>>> from qrisp import PassManager, convert_to_cz, convert_to_prx
>>> from iqm.qrisp_iqm import vf2pp_layout
>>> backend = IQMBackend(
...     token="YOUR_API_TOKEN",
...     device_instance="garnet",
...     pass_manager=PassManager()  # start with an empty manager
... )
>>> coupling_map = [(0, 1), (1, 2), (2, 3)]
>>> backend.pm += vf2pp_layout(coupling_map)
>>> backend.pm += convert_to_cz()
>>> backend.pm += convert_to_prx
>>> result = backend.run(my_circuit, shots=1000)

The pass_manager=PassManager() constructor argument gives you full control. You can also start from None and extend the pipeline (or even insert passes at arbitrary positions via insert_before()).

Pulse-level execution (automatic routing):

>>> from iqm.qrisp_iqm import IQMBackend
>>> from iqm.qrisp_iqm.pulse_operation  import IQMPulseOperation
>>> backend = IQMBackend(
...     token="YOUR_API_TOKEN",
...     device_instance="garnet"
... )
>>> # Circuit with IQMPulseOperation is compiled locally to a pulse-level job.
>>> job = backend.run_async(my_pulse_circuit, shots=1000)
>>> result = job.result()

Attributes

connectivity

Currently executable qubit connectivity for this IQM backend.

Methods

retrieve_job

Retrieve a previously submitted job.

run

Transpile and submit circuits for execution, return measurement result(s).

run_async

Transpile and submit circuits for execution on the IQM device, return immediately.

run(circuits: QuantumCircuit | Sequence[QuantumCircuit], shots: int | None = None, *, use_timeslot: bool | None = None, compilation_options: CircuitCompilationOptions | None = None) MeasurementResult | list[MeasurementResult]#

Transpile and submit circuits for execution, return measurement result(s).

Blocks until the execution is finished, which may take awhile if there are other jobs in the queue. Consider using run_async() instead.

Takes the same args as run_async().

Returns:

A pre-populated MeasurementResult when one circuit is submitted, or a list of them for multiple circuits.

Parameters:
Return type:

MeasurementResult | list[MeasurementResult]

run_async(circuits: QuantumCircuit | Sequence[QuantumCircuit], shots: int | None = None, *, use_timeslot: bool | None = None, compilation_options: CircuitCompilationOptions | None = None) IQMJob#

Transpile and submit circuits for execution on the IQM device, return immediately.

Automatically detects whether any of circuits contain IQMPulseOperation instances:

  • No pulse ops → submitted as a gate-level IQMCircuitJob.

  • Has pulse ops → compiled locally down to pulse level, and submitted as a IQMPulseJob.

Parameters:
  • circuits (QuantumCircuit | Sequence[QuantumCircuit]) – The circuit(s) to execute.

  • shots (int | None) – Number of shots per circuit. If None, use the backend default.

  • use_timeslot (bool | None) – If True, submits the job to the timeslot queue. If False, the job is submitted to the normal on-demand queue. None means use the default set in __init__().

  • compilation_options (CircuitCompilationOptions | None) – Options for compiling circuits to pulse schedules. On the pulse-level execution path, the CircuitCompilationOptions.max_circuit_duration_over_t2 attribute has no effect. None means use the default set in __init__().

Returns:

A job handle for the submitted execution.

Return type:

IQMJob

property connectivity: list[tuple[int, int]]#

Currently executable qubit connectivity for this IQM backend.

Cached once at construction time from the DynamicQuantumArchitecture.

Returns:

The two-qubit gate coupling map as a list of qubit-index pairs.

retrieve_job(job_id: str, *, pulse: Literal[False]) IQMCircuitJob#
retrieve_job(job_id: str, *, pulse: Literal[True]) IQMPulseJob

Retrieve a previously submitted job.

Parameters:
  • job_id – The IQM job ID (UUID as string) of the job to retrieve.

  • pulse – Whether the job was submitted at the pulse level.

Returns:

Handle for the previously submitted job.

Inheritance

Inheritance diagram of iqm.qrisp_iqm.backends.IQMBackend