skills/qiskit/references/backends.md
Qiskit 2.x providers expose hardware and simulators through BackendV2. Important public attributes include:
print(backend.name)
print(backend.num_qubits)
print(backend.operation_names)
print(backend.coupling_map)
print(backend.target)
print(backend.status())
The Target describes operation support, qubit operands, connectivity, and available timing/error metadata.
Do not use backend.configuration(), BackendProperties, or other BackendV1 patterns in new code.
Use a securely saved account:
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
New account configurations use channel="ibm_quantum_platform". See setup.md for secure credential setup. Never embed or print an API key.
Select by requirements, not by a system name copied from a tutorial:
backends = service.backends(
operational=True,
simulator=False,
min_num_qubits=20,
)
for candidate in backends:
status = candidate.status()
print(
candidate.name,
candidate.num_qubits,
status.pending_jobs,
)
For exploratory work:
backend = service.least_busy(
operational=True,
simulator=False,
min_num_qubits=20,
)
Least busy is not necessarily best. For a production experiment, compare:
The bundled read-only inspector summarizes one selected backend:
python scripts/inspect_runtime.py --min-qubits 20
python scripts/inspect_runtime.py --backend BACKEND_NAME --json
target = backend.target
print("operations:", sorted(backend.operation_names))
print("supports if_else:", "if_else" in backend.operation_names)
print("supports reset:", "reset" in backend.operation_names)
print("coupling edges:", list(backend.coupling_map.get_edges()))
Operation support can vary by qubit tuple. A name appearing in operation_names does not imply every qubit or pair supports it.
from qiskit.transpiler import generate_preset_pass_manager
pass_manager = generate_preset_pass_manager(
backend=backend,
optimization_level=1,
seed_transpiler=23,
)
isa_circuit = pass_manager.run(circuit)
For Estimator:
isa_observable = observable.apply_layout(isa_circuit.layout)
Runtime V2 primitives do not perform this conversion automatically.
Use job mode for independent one-off primitive calls:
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(mode=backend)
job = sampler.run([isa_circuit], shots=1024)
job_id = job.job_id()
print("job_id:", job_id)
result = job.result()
Persist the ID before blocking. Retrieve later:
service = QiskitRuntimeService()
job = service.job(job_id)
print(job.status())
result = job.result()
Cancel only if the experiment should no longer consume allocation:
job.cancel()
Batch mode is for independent jobs that can be submitted together. It is available to Open Plan users.
from qiskit_ibm_runtime import Batch, SamplerV2 as Sampler
with Batch(backend=backend, max_time="10m") as batch:
sampler = Sampler(mode=batch)
jobs = [
sampler.run([isa_circuit], shots=1024)
for isa_circuit in isa_circuits
]
# The batch accepts no new jobs; submitted jobs can still finish.
results = [job.result() for job in jobs]
Batch jobs are scheduled as a group, but do not assume an application-level result order beyond the job list you preserve.
Session mode is for iterative workloads such as VQE parameter updates:
from qiskit_ibm_runtime import EstimatorV2 as Estimator, Session
with Session(backend=backend, max_time="20m") as session:
estimator = Estimator(mode=session)
jobs = [
estimator.run([pub], precision=0.03)
for pub in iterative_pubs
]
Open Plan users cannot submit session jobs; use job or batch mode. Sessions have maximum and interactive time-to-live limits. Close them as soon as submission is complete.
Creating Estimator(mode=backend) inside a session context still selects job mode. Use mode=session.
For small ideal circuits:
from qiskit.primitives import StatevectorEstimator, StatevectorSampler
sampler = StatevectorSampler(seed=23)
estimator = StatevectorEstimator(seed=23)
These implementations use local statevector simulation and do not model backend noise.
Memory for a dense statevector grows as (2^n). Use an algorithm-appropriate Aer method or tensor-network tooling for larger circuits.
Install the pinned Aer distribution:
uv pip install "qiskit-aer==0.17.2"
Create an ideal Aer backend:
from qiskit_aer import AerSimulator
aer = AerSimulator(method="automatic")
Run through Runtime's local-testing primitive interface:
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import SamplerV2 as Sampler
pass_manager = generate_preset_pass_manager(
backend=aer,
optimization_level=1,
seed_transpiler=23,
)
isa_circuit = pass_manager.run(circuit)
sampler = Sampler(
mode=aer,
options={"simulator": {"seed_simulator": 23}},
)
result = sampler.run([isa_circuit], shots=1024).result()
Most Runtime options other than shots and simulator settings are ignored in local testing. Do not infer that mitigation was simulated merely because an options object accepted the field.
from qiskit_aer import AerSimulator
noisy_aer = AerSimulator.from_backend(backend)
pass_manager = generate_preset_pass_manager(
backend=noisy_aer,
optimization_level=1,
seed_transpiler=23,
)
noisy_isa = pass_manager.run(circuit)
sampler = Sampler(
mode=noisy_aer,
options={"simulator": {"seed_simulator": 23}},
)
result = sampler.run([noisy_isa], shots=4096).result()
This captures a subset of backend properties at model-construction time. It does not reproduce drift, all crosstalk, or every Runtime service behavior.
Fake backends provide a local BackendV2 target and calibration-like snapshot:
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
fake_backend = FakeSherbrooke()
Use them to test target-aware transpilation and Runtime local mode. Fake-backend class names can change; inspect the installed qiskit_ibm_runtime.fake_provider module before selecting one.
Runtime Estimator exposes increasing levels of built-in mitigation:
from qiskit_ibm_runtime import EstimatorV2 as Estimator
estimator = Estimator(
mode=backend,
options={"resilience_level": 1},
)
Current supported resilience levels:
0: disable built-in resilience.1: measurement mitigation.2: measurement mitigation plus additional techniques such as ZNE, according to current defaults.There is no resilience level 3 in the current V2 API.
Configure explicit techniques when the experiment requires control:
estimator = Estimator(mode=backend)
estimator.options.dynamical_decoupling.enable = True
estimator.options.dynamical_decoupling.sequence_type = "XpXm"
estimator.options.twirling.enable_gates = True
estimator.options.twirling.num_randomizations = 32
estimator.options.twirling.shots_per_randomization = 100
estimator.options.resilience.zne_mitigation = True
estimator.options.resilience.zne.noise_factors = (1, 3, 5)
estimator.options.resilience.zne.extrapolator = "exponential"
Mitigation adds bias assumptions, circuit variants, shots, classical processing, and cost. It is not guaranteed to improve an observable.
Sampler returns sampled classical data and does not use Estimator resilience levels:
sampler = Sampler(mode=backend)
sampler.options.dynamical_decoupling.enable = True
sampler.options.dynamical_decoupling.sequence_type = "XpXm"
sampler.options.twirling.enable_gates = True
Measurement and gate-twirling defaults differ between Sampler and Estimator and can change. Record the resolved options for every experiment.
Some combinations are restricted. Current examples include incompatibilities among:
Always consult the current Estimator/Sampler options and backend target. Do not copy a mitigation configuration between Runtime versions without revalidation.
Request a backend target that exposes fractional gates when the algorithm benefits:
backend = service.backend(
backend_name,
use_fractional_gates=True,
)
Compile against the returned object. use_fractional_gates changes the target and can affect compatibility with control flow and mitigation.
Qiskit Pulse is not an alternative; qiskit.pulse was removed in Qiskit 2.0.
Qiskit can target non-IBM providers through separately installed provider packages. Each provider controls:
BackendV2 features,Prefer the provider's current documentation. If only BackendV2 is available, adapt it with BackendSamplerV2 or BackendEstimatorV2. Do not assume IBM Runtime options, sessions, or mitigation are portable.
Before submitting:
ibm_quantum_platform, verify the saved account, API key, and instance access.