Qiskit Quantum Backend Selector
Noise- and queue-aware backend selection and routing for IBM Quantum
backends, built on qiskit-ibm-runtime.
QiskitRuntimeService.least_busy() only looks at queue depth. This
package scores candidate backends per-circuit — factoring in whether the
circuit actually fits, and (optionally) an estimate of expected fidelity
after transpilation — then can route job submission with automatic
failover if a backend errors out.
Install
pip install qiskit-quantum-backend-selector
Or from source:
pip install -e .
Quick start
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_backend_selector import BackendSelector, HybridScoring
service = QiskitRuntimeService()
selector = BackendSelector(service=service, strategy=HybridScoring())
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
best_backend = selector.select(qc)
With automatic failover on submission errors:
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit_backend_selector import BackendRouter
router = BackendRouter(selector, max_attempts=3)
def submit(backend, circuit):
sampler = Sampler(mode=backend)
return sampler.run([circuit])
job = router.submit(qc, submit)
Scoring strategies
QueueOnlyScoring— ranks by reported pending-job count. Cheap, equivalent in spirit toleast_busy().NoiseAwareScoring— transpiles the circuit against each candidate backend's real coupling map and basis gates, then estimates fidelity by multiplying per-gate and per-readout error rates frombackend.properties()along the transpiled circuit.HybridScoring— weighted sum of the two above (queue_weight,noise_weight, defaults 0.4/0.6).
Any strategy that implements score(backend, circuit) -> float | None
can be dropped in; returning None excludes a backend (e.g. it doesn't
have enough qubits for the circuit).
QueueOnlyScoring, NoiseAwareScoring, and HybridScoring all accept
an optional CalibrationCache (see monitor.py) to avoid refetching
backend.status()/backend.properties() on every call when scoring
many circuits in a short window:
from qiskit_backend_selector import HybridScoring, CalibrationCache
queue_cache = CalibrationCache(ttl_seconds=30) # queue depth changes fast
noise_cache = CalibrationCache(ttl_seconds=3600) # calibration data doesn't
strategy = HybridScoring(queue_cache=queue_cache, noise_cache=noise_cache)
Live smoke test
scripts/live_smoke_test.py exercises this against a real
QiskitRuntimeService — real auth, real calibration data, an actual job
submission — none of which the fake-backend test suite covers. Run it
manually with your own IBM Quantum credentials configured:
python scripts/live_smoke_test.py
This has been run twice against a live service (2026-09-03). First
run caught a real bug (non-ISA circuit submission — see below, fixed in
router.py); second run, after the fix, submitted cleanly to ibm_fez
and returned a real RuntimeJobV2. Re-run after any further change to
router.py or scoring.py.
Fidelity estimate: validation status
scripts/validate_fidelity_estimate.py checks NoiseAwareScoring's
analytic prediction against a Qiskit Aer noise-model simulation built from
the same calibration data (AerSimulator.from_backend). Sample results:
| Circuit / backend | Predicted | Simulated | Diff |
|---|---|---|---|
| bell_pair / Manila | 0.9351 | 0.9395 | -0.0044 |
| bell_pair / Sherbrooke | 0.9565 | 0.9602 | -0.0037 |
| ghz3 / Manila | 0.8332 | 0.8397 | -0.0066 |
| ghz5 / Sherbrooke | 0.8805 | 0.8869 | -0.0064 |
| ghz4 / Manila | 0.8119 | 0.8292 | -0.0174 |
Agreement is within ~0.02 across these cases, and tests/test_fidelity_validation.py
regression-tests this stays under a 0.05 tolerance (skipped automatically
if the optional qiskit-aer extra isn't installed: pip install -e ".[validate]").
Read this narrowly. Aer's noise model is built from the same
calibration numbers NoiseAwareScoring reads, using thermal-relaxation and
depolarizing channels per gate — which are themselves built from
independence assumptions similar to the analytic estimate's. Close
agreement here shows the analytic math is a reasonable approximation of
that noise model, not that the noise model matches a real device on any
given day. It does not touch crosstalk, calibration drift, or correlated
errors — the gap flagged below still stands until validated against an
actual hardware run.
Known limitations
- Independent-error assumption.
NoiseAwareScoringmultiplies gate and readout error rates as if they were independent. Checked against Aer noise-model simulation (see above) it tracks within ~0.02 — but that simulation shares the same independence assumptions, so this doesn't rule out systematic overstatement on real hardware, where crosstalk, drift, and spatially correlated errors aren't Markovian per-gate channels. Treat it as a relative ranking signal until checked against real device results. - Transpile cost. Noise-aware scoring transpiles the circuit against
every candidate backend on every call.
CalibrationCache(now wired in) avoids refetchingstatus()/properties(), but transpilation itself isn't cached — for large batches of circuits against many backends this still gets expensive. - Queue score ignores job cost.
QueueOnlyScoringcounts pending jobs, not their size or expected runtime, so it can't tell a queue of five quick jobs from a queue of five expensive ones. - Hybrid weights are defaults, not tuned. The 0.4/0.6 split in
HybridScoringis a reasonable starting point, not the result of empirical calibration against real turnaround-time or fidelity data. - No live-service integration tests in CI.
scripts/live_smoke_test.pyhas been run manually twice: once caught a real bug (non-ISA circuit submission, fixed — see above), once confirmed the fix works end-to-end against real hardware (ibm_fez, jobdaciemu42tqs73as7h10). It still isn't run automatically, so nothing currently prevents a future regression from reaching a release without someone running it manually.BackendRouter's failover path itself is still verified only against injectedsubmit_fns in pytest, not real Runtime error modes like auth failures, rate limits, or mid-job backend retirement. - Static circuit assumption. Scoring assumes a fixed circuit width known ahead of time. Dynamic circuits with mid-circuit measurement and classical feedforward are transpiled and scored the same way, but the fidelity estimate doesn't account for any additional overhead specific to dynamic execution.
License
Apache-2.0
Metadata
Release files for qiskit-quantum-backend-selector 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| qiskit_quantum_backend_selector-0.1.0.tar.gz | 22.7 kB | Without provenance | Details for qiskit_quantum_backend_selector-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| qiskit_quantum_backend_selector-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for qiskit_quantum_backend_selector-0.1.0-py3-none-any.whl |
Total release size: 41.3 kB
Release files / qiskit_quantum_backend_selector-0.1.0.tar.gz
| Download URL | qiskit_quantum_backend_selector-0.1.0.tar.gz |
|---|---|
| Size | 22.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8dbb5ba234105ec3980bbd6a663506b909f8a4945a5d9f52045da27c0797b7ef
|
|
BLAKE2b-256 checksum How to use checksums |
e635c07ab59f498133090ce272625f8a84d3fc794ee931dd7f904028e9f30b95
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.2
|
Release files / qiskit_quantum_backend_selector-0.1.0-py3-none-any.whl
| Download URL | qiskit_quantum_backend_selector-0.1.0-py3-none-any.whl |
|---|---|
| Size | 18.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
790480cf6b328406d0413a071e6ccdab3230745de969ead75f65a5a25d90bd5f
|
|
BLAKE2b-256 checksum How to use checksums |
e9feecda887e8ae09ecd518731791048ec168e5d8579e52fb0641f8ce6a57385
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.2
|
Security for qiskit-quantum-backend-selector 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.