Using Qiskit to Run Quantum Workloads on IQM Hardware via QDMI-on-IQM

The iqm-qdmi Python package includes a wrapper for the IQM QDMI Device library that integrates it with Qiskit. This wrapper is implemented in the iqm.qdmi.qiskit submodule and is based on the open-source, MIT-licensed MQT Core library. To use the wrapper, make sure to install the iqm-qdmi package with the qiskit extra:

uv pip install iqm-qdmi[qiskit]

Then, the IQMBackend class can be imported from iqm.qdmi.qiskit and used as a drop-in replacement for any Qiskit backend.

1from iqm.qdmi.qiskit import IQMBackend
2from qiskit.circuit import QuantumCircuit
3from qiskit.compiler import transpile
4
5backend = IQMBackend(
6  base_url="https://resonance.iqm.tech",
7  qc_alias="emerald:mock",
8)
1qc = QuantumCircuit(2)
2qc.h(0)
3qc.cx(0, 1)
4qc.measure_all()
5
6transpiled_qc = transpile(qc, backend)
7result = backend.run(transpiled_qc, shots=128).result()
8print(result.get_counts())
{'00': 50, '11': 78}

Explicit arguments to IQMBackend(...) take precedence over IQM_SERVER_URL, IQM_TOKEN, IQM_TOKENS_FILE, IQM_QC_ID, and IQM_QUANTUM_COMPUTER from the environment. IQM_BASE_URL and IQM_QC_ALIAS remain supported as legacy aliases. Canonical variables take precedence over their legacy aliases, which take precedence over the registered device default.

The wrapper registers the packaged IQM QDMI device as a fallback under the stable ID iqm.default with the standard Resonance endpoint as its default. An existing configured definition with that ID is preserved, including its endpoint. Every backend opens a fresh device session with its own configuration.

Sampler and Estimator Primitives

IQMBackend provides small helpers (see sampler() and estimator()) for constructing BackendSamplerV2 and BackendEstimatorV2 primitives bound to the backend instance.

1sampler_job = backend.sampler().run([(transpiled_qc,)], shots=128)
2counts = sampler_job.result()[0].data["meas"].get_counts()
3print(f"Counts: {counts}")
Counts: {'00': 63, '11': 65}
1from qiskit.quantum_info import SparsePauliOp
2
3transpiled_qc.remove_final_measurements(inplace=True)
4observable = SparsePauliOp("Z" * backend.num_qubits)
5
6estimator_job = backend.estimator().run([(transpiled_qc, observable)])
7data = estimator_job.result()[0].data
8print(f"Expectation values: {data['evs']}")
9print(f"Standard deviations: {data['stds']}")
Expectation values: 0.00927734375
Standard deviations: 0.015624327570631967

CLI Scripts

The package also exposes the iqm-sampler and iqm-estimator CLI scripts for executing serialized circuits directly from the shell. For more details on these utilities and their usage, see the Python Package Guide.