QiskitBackend#

class QiskitBackend(backend: Backend | None = None, name: str | None = None, options: Mapping | None = None)[source]#

A Backend that wraps a Qiskit backend.

This allows easy access to any Qiskit-compatible simulator or real quantum hardware through the Qrisp backend interface.

Circuits are converted from Qrisp’s internal representation to Qiskit QuantumCircuit objects, transpiled for the target backend, and submitted through the backend’s own run() method. A QiskitJob handle is returned immediately; call Job.result() to block and retrieve the JobResult.

Note

Submission deliberately goes through Backend.run() rather than Qiskit’s BackendSamplerV2 primitive. BackendSamplerV2 reconstructs its output from the memory field of the result and parses each entry as a hexadecimal string. Not every provider honours that convention (qiskit-iqm, for instance, writes plain binary bitstrings), which yields either an OverflowError or, worse, silently wrong counts. Reading counts directly via Result.get_counts() avoids the ambiguity, and Qrisp never needs per-shot memory anyway.

Parameters:
backendQiskit backend object, optional

A Qiskit backend object that runs QuantumCircuit objects. Defaults to AerSimulator() if not provided.

namestr or None, optional

A name for the backend. Defaults to the Qiskit backend’s own name.

optionsdict or None, optional

Runtime options. Defaults to {"shots": 1000}.

Raises:
TypeError

If backend is a real IBM Quantum backend, which cannot run through Backend.run(). Use QiskitRuntimeBackend for those. IBM fake backends run locally and are supported here.

Examples

Simulation on the Aer simulator

We start by creating a QiskitBackend wrapping the Qiskit Aer simulator, and then measure a QuantumFloat multiplication:

from qrisp import QuantumFloat
from qrisp.interface import QiskitBackend
from qiskit_aer import AerSimulator

qiskit_backend = QiskitBackend(backend=AerSimulator())

qf = QuantumFloat(4)
qf[:] = 3
res = qf * qf

When get_measurement is called, Qrisp compiles the computation into a QuantumCircuit, converts it directly to a Qiskit QuantumCircuit, transpiles it for the target backend, and submits it through the backend’s run() method. Internally, run_async returns a QiskitJob immediately; run() then blocks on job.result() until execution completes and the counts are returned to get_measurement:

>>> res.get_measurement(backend=qiskit_backend)
{9: 1.0}

For local simulators the job is already DONE by the time run_async() returns. For remote hardware backends the job will initially be QUEUED or RUNNING, and result() will block until execution completes on the device.

Noisy simulation on a fake hardware backend

The same interface works with Qiskit’s fake hardware backends, which model real device noise and connectivity constraints:

from qrisp import QuantumFloat
from qiskit_ibm_runtime.fake_provider import FakeWashingtonV2
from qrisp.interface import QiskitBackend

qiskit_backend = QiskitBackend(backend=FakeWashingtonV2())

qf = QuantumFloat(2)
qf[:] = 2
res = qf * qf

Internally, run_async() transpiles the circuit to the device’s native gate set and qubit connectivity before submission, so the results reflect realistic noise characteristics:

>>> res.get_measurement(backend=qiskit_backend)
{4: 0.6962, ...}   # Note: actual counts may vary due to noise and randomness

The result is no longer a sharp peak at {4: 1.0} because the noise model introduces gate errors and readout errors, spreading probability mass across neighbouring bitstrings.

QiskitBackend.run_async(circuits, shots: int | list[int] | None = None) QiskitJob[source]#

Transpile and submit one or more circuits to the Qiskit backend.

This method returns a QiskitJob immediately. Call Job.result() on the returned object to block and retrieve the JobResult.

Parameters:
circuitsQuantumCircuit or Sequence[QuantumCircuit]

One Qrisp circuit or a sequence of Qrisp circuits to execute.

shotsint or list[int] or None, optional

Number of shots. If None, the backend’s shots option is used. If a list[int] is provided, Qiskit applies a single shot count to the whole submission, so all circuits are run at max(shots) and a UserWarning is emitted.

Returns:
QiskitJob