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 Qiskit’s SamplerV2 primitive. A QiskitJob handle is returned immediately; call Job.result() to block and retrieve the JobResult.

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}.

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 SamplerV2. 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, the Qiskit sampler does not support per-circuit shot counts, so all circuits are run at max(shots) and a UserWarning is emitted.

Returns:
QiskitJob