Easy Integration with the iqm-qdmi Python Package¶
To ease the distribution and integration of the IQM QDMI Device library, we have
packaged it as a Python module available on PyPI under the name iqm-qdmi. This
package provides a convenient way to discover installation paths and metadata
that are useful when integrating the IQM QDMI Device into downstream build
systems, such as CMake-based projects or Python workflows.
Install From PyPI¶
Use uv (or your Python package manager of choice) to install the package:
uv pip install iqm-qdmi
Quick Usage¶
The package itself makes the following variables available for import:
__version__: installed package version.IQM_QDMI_INCLUDE_DIR: include directory for C/C++ headers.IQM_QDMI_CMAKE_DIR: CMake package directory forfind_packageintegration.IQM_QDMI_LIBRARY_PATH: full path to the shared library.
1from iqm.qdmi import __version__, IQM_QDMI_INCLUDE_DIR, IQM_QDMI_CMAKE_DIR, IQM_QDMI_LIBRARY_PATH
2
3print(f"QDMI on IQM version: {__version__}")
4print(f"Include directory: {IQM_QDMI_INCLUDE_DIR}")
5print(f"CMake directory: {IQM_QDMI_CMAKE_DIR}")
6print(f"Library path: {IQM_QDMI_LIBRARY_PATH}")
QDMI on IQM version: 1.5.0
Include directory: /home/runner/work/QDMI-on-IQM/QDMI-on-IQM/.nox/docs/lib/python3.14/site-packages/iqm/qdmi/data/include
CMake directory: /home/runner/work/QDMI-on-IQM/QDMI-on-IQM/.nox/docs/lib/python3.14/site-packages/iqm/qdmi/data/share/cmake
Library path: /home/runner/work/QDMI-on-IQM/QDMI-on-IQM/.nox/docs/lib/python3.14/site-packages/iqm/qdmi/data/lib/libiqm-qdmi-device.so
Command Line Interface¶
The above values can also be conveniently queried from the command line via the
iqm-qdmi entry point.
1!iqm-qdmi --help
usage: iqm-qdmi [-h] [--version | --include_dir | --cmake_dir | --lib_path]
Command line interface for the QDMI on IQM library.
options:
-h, --help show this help message and exit
--version show program's version number and exit
--include_dir Print the path to the iqm-qdmi C/C++ include directory
--cmake_dir Print the path to the iqm-qdmi CMake module directory
--lib_path Print the path to the iqm-qdmi shared library
1!iqm-qdmi --version
1.5.0
1!iqm-qdmi --include_dir
/home/runner/work/QDMI-on-IQM/QDMI-on-IQM/.nox/docs/lib/python3.14/site-packages/iqm/qdmi/data/include
1!iqm-qdmi --cmake_dir
/home/runner/work/QDMI-on-IQM/QDMI-on-IQM/.nox/docs/lib/python3.14/site-packages/iqm/qdmi/data/share/cmake
1!iqm-qdmi --lib_path
/home/runner/work/QDMI-on-IQM/QDMI-on-IQM/.nox/docs/lib/python3.14/site-packages/iqm/qdmi/data/lib/libiqm-qdmi-device.so
Sampler and Estimator CLI Utilities¶
If you install the package with the qiskit extra, the following additional
command-line scripts are exposed:
iqm-sampler(see thesamplerentry point module): Samples a serialized QPY circuit on the specified backend.iqm-estimator(see theestimatorentry point module): Variational Quantum Eigensolver (VQE) parameter estimation for a serialized ansatz and observable.
iqm-sampler Usage¶
For example, to execute a QPY circuit file (bell.qpy):
iqm-sampler bell.qpy --shots 128
iqm-estimator Usage¶
To run a parameter estimation job:
iqm-estimator ansatz.qpy observable.pkl --maxiter 10
The estimator CLI and offloader.estimate use Qiskit’s default precision of
1/64, corresponding to 4,096 shots per measurement circuit. See the
primitive options.
Programmatic Offloading with the offloader Module¶
For workflows running on a Slurm login node (such as Jupyter notebooks on a
gateway service), the package exposes the offloader module.
It allows you to programmatically submit quantum workloads to the Slurm quantum
queue.
The module provides two primary functions:
sample(): Serializes the circuit to QPY and submits a Slurm job usingsrun iqm-sampler. The returned sampler result is converted to joint counts across all classical registers in Qiskit’s bit order.estimate(): Serializes the ansatz and observable, submits a Slurm job usingsrun iqm-estimator, and returns the completeVQEResultproduced by the worker.
Both worker CLIs reserve stdout for one base64-encoded pickle containing the native Qiskit result; diagnostics belong on stderr. The offloader is intended for controlled Slurm deployments with trusted workers and serialized inputs. Use compatible Python and dependency environments on the submitting and worker nodes. Result loading uses standard pickle without a restricted unpickler.
Both functions support local=True to execute in the submitting process instead
of Slurm, and simulator=True to select the simulator in either mode.
Selecting the Slurm Partition¶
Both functions submit their srun jobs to a site-defined partition. Its name is
resolved in this order:
The
partitionkeyword argument.The
IQM_SLURM_PARTITIONenvironment variable, which lets an administrator set the site’s name once for every user. An empty value counts as unset.quantum.
counts = sample(qc, shots=512, partition="qc-nodes")
Slurm’s own SLURM_PARTITION has no effect here, because the resolved name is
always passed as an explicit --partition, which takes precedence over it.
Important
Use the MQT Core Slurm guide for scheduler setup, device selection, and job submission.
Sizing the Slurm Allocation¶
Both functions accept a nodes keyword argument, forwarded as --nodes and
defaulting to a single node. The worker itself always runs as one task
(--ntasks=1), so nodes only sizes the allocation for a site whose partition
demands more than one node; it does not distribute or parallelize the workload.
It has no environment fallback: the node count is a per-job resource request rather than a site-wide constant.
Selecting a Quantum Computer per Job¶
For remote execution (local=False), pass an IQM quantum-computer UUID as
qc_id or an IQM alias such as emerald:mock as qc_alias. These values are
forwarded to the iqm-sampler and iqm-estimator workers. When neither is
provided, the worker uses the backend’s environment defaults. These
arguments identify the IQM quantum computer; request its Slurm license
separately with licenses. Credentials come from the job environment.
Requesting a Slurm License¶
The optional licenses argument is forwarded to srun unchanged. The offloader
selects the quantum computer through its explicit arguments. Applications can
also open a catalogue ID with qdmi_driver.open_device() and pass that device
to IQMBackend, as shown in
IQM on Slurm.
Programmatic Sampling Example¶
from iqm.qdmi.offloader import sample
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
# programmatically offload via Slurm
counts = sample(qc, shots=512, simulator=True)
print("Counts:", counts)
Querying the Device Directly¶
The Qiskit backend covers circuit execution, but a QDMI device also answers
questions about itself. MQT Core discovers the installed device manifest without
importing device implementation code or loading the device library. Open its
stable ID IQM_QDMI_DEVICE_ID through the MQT Core QDMI
driver:
from mqt.core.qdmi import builtin_driver as qdmi_driver
from iqm.qdmi import IQM_QDMI_DEVICE_ID
device = qdmi_driver.open_device(IQM_QDMI_DEVICE_ID, token="…", custom2="emerald")
print(device.status())
print(device.supported_program_formats())
Queue Length and Queue Position¶
The device reports how busy the quantum computer is, so a client can decide whether to submit now or wait:
waiting = device.queue_length() # jobs waiting, excluding those executing
queue_length() returns None when the IQM API does not supply a trustworthy
value. A queued job reports how many jobs are ahead of it; querying it refreshes
the job’s status first:
ahead = job.queue_position # None once the job is no longer queued
Retrieving an Existing Job¶
A job outlives the session that submitted it. Given its ID, a later session can pick it up again to poll, wait, cancel, or fetch results:
job = device.retrieve_job_by_id("d3416f0a-…")
print(job.check())
A retrieved job cannot be resubmitted, and its parameters cannot be changed.