Skill Tracer
Skills › Scientific Agent Skills › qiskit › backends.md

backends.md

385 lines · skills/qiskit/references/backends.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Backends, Runtime Modes, Simulation, and Noise Management
2
3Cloud authentication, QPU, session, and batch snippets are illustrative and were not executed in this refresh. Local evidence is listed in [sources.md](sources.md).

Backends, Runtime Modes, Simulation, and Noise Management

Cloud authentication, QPU, session, and batch snippets are illustrative and were not executed in this refresh. Local evidence is listed in sources.md.

Raw lines 1 to 3
4## BackendV2
5
6Qiskit 2.x providers expose hardware and simulators through `BackendV2`. Important public attributes include:
7
8```python
9print(backend.name)
10print(backend.num_qubits)
11print(backend.operation_names)
12print(backend.coupling_map)
13print(backend.target)
14print(backend.status())
15```
17The `Target` describes operation support, qubit operands, connectivity, and available timing/error metadata.
19Do not use `backend.configuration()`, `BackendProperties`, or other BackendV1 patterns in new code.

BackendV2

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.

Raw lines 4 to 20
21## Connect to IBM Quantum
23Use a securely saved account:
25```python
26from qiskit_ibm_runtime import QiskitRuntimeService
28service = QiskitRuntimeService()
29```
31New account configurations use `channel="ibm_quantum_platform"`. See [setup.md](setup.md) for secure credential setup. Never embed or print an API key.

Connect to IBM Quantum

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.

Raw lines 21 to 32
33## Discover Backends
35Select by requirements, not by a system name copied from a tutorial:
37```python
38backends = service.backends(
39 operational=True,
40 simulator=False,
41 min_num_qubits=20,
44for candidate in backends:
45 status = candidate.status()
46 print(
47 candidate.name,
48 candidate.num_qubits,
49 status.pending_jobs,
50 )
51```
53For exploratory work:
55```python
56backend = service.least_busy(
57 operational=True,
58 simulator=False,
59 min_num_qubits=20,
61```
63Least busy is not necessarily best. For a production experiment, compare:
65- required qubit count,
66- connectivity and native two-qubit operations,
67- calibration quality on candidate subgraphs,
68- control-flow or fractional-gate requirements,
69- plan and region,
70- queue and expected execution time.
72The bundled read-only inspector summarizes one selected backend:
74```bash
75python scripts/inspect_runtime.py --min-qubits 20
76python scripts/inspect_runtime.py --backend BACKEND_NAME --json
77```

Discover Backends

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:

  • required qubit count,
  • connectivity and native two-qubit operations,
  • calibration quality on candidate subgraphs,
  • control-flow or fractional-gate requirements,
  • plan and region,
  • queue and expected execution time.

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
Raw lines 33 to 78
Runs code python scripts/inspect_runtime.py :75
79## Inspect Target Capabilities
81```python
82target = backend.target
84print("operations:", sorted(backend.operation_names))
85print("supports if_else:", "if_else" in backend.operation_names)
86print("supports reset:", "reset" in backend.operation_names)
87print("coupling edges:", list(backend.coupling_map.get_edges()))
88```
90Operation support can vary by qubit tuple. A name appearing in `operation_names` does not imply every qubit or pair supports it.

Inspect Target Capabilities

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.

Raw lines 79 to 91
92## Prepare ISA Circuits
94```python
95from qiskit.transpiler import generate_preset_pass_manager
97pass_manager = generate_preset_pass_manager(
98 backend=backend,
99 optimization_level=1,
100 seed_transpiler=23,
102isa_circuit = pass_manager.run(circuit)
103```
105For Estimator:
107```python
108isa_observable = observable.apply_layout(isa_circuit.layout)
109```
111Runtime V2 primitives do not perform this conversion automatically.

Prepare ISA Circuits

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.

Raw lines 92 to 112
113## Job Mode
115Use job mode for independent one-off primitive calls:
117```python
118from qiskit_ibm_runtime.executor_sampler import Sampler
120sampler = Sampler(mode=backend)
121job = sampler.run([isa_circuit], shots=1024)
123job_id = job.job_id()
124print("job_id:", job_id)
125result = job.result()
126```
128Persist the ID before blocking. Retrieve later:
130```python
131service = QiskitRuntimeService()
132job = service.job(job_id)
133print(job.status())
134result = job.result()
135```
137Cancel only if the experiment should no longer consume allocation:
139```python
140job.cancel()
141```

Job Mode

Use job mode for independent one-off primitive calls:

from qiskit_ibm_runtime.executor_sampler import 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()
Raw lines 113 to 142
143## Batch Mode
145Batch mode is for independent jobs that can be submitted together. It is available to Open Plan users.
147```python
148from qiskit_ibm_runtime import Batch
149from qiskit_ibm_runtime.executor_sampler import Sampler
151with Batch(backend=backend, max_time="10m") as batch:
152 sampler = Sampler(mode=batch)
153 jobs = [
154 sampler.run([isa_circuit], shots=1024)
155 for isa_circuit in isa_circuits
156 ]
158# The batch accepts no new jobs; submitted jobs can still finish.
159results = [job.result() for job in jobs]
160```
162Batch jobs are scheduled as a group, but do not assume an application-level result order beyond the job list you preserve.

Batch Mode

Batch mode is for independent jobs that can be submitted together. It is available to Open Plan users.

from qiskit_ibm_runtime import Batch
from qiskit_ibm_runtime.executor_sampler import 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.

Raw lines 143 to 163
164## Session Mode
166Session mode is for iterative workloads such as VQE parameter updates:
168```python
169from qiskit_ibm_runtime import Session
170from qiskit_ibm_runtime.executor_estimator import Estimator
172with Session(backend=backend, max_time="20m") as session:
173 estimator = Estimator(mode=session)
174 jobs = [
175 estimator.run([pub], precision=0.03)
176 for pub in iterative_pubs
177 ]
178```
180Open 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.
182Creating `Estimator(mode=backend)` inside a session context still selects job mode. Use `mode=session`.

Session Mode

Session mode is for iterative workloads such as VQE parameter updates:

from qiskit_ibm_runtime import Session
from qiskit_ibm_runtime.executor_estimator import Estimator

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.

Raw lines 164 to 183
184## Ideal Local Primitives
186For small ideal circuits:
188```python
189from qiskit.primitives import StatevectorEstimator, StatevectorSampler
191sampler = StatevectorSampler(seed=23)
192estimator = StatevectorEstimator(seed=23)
193```
195These implementations use local statevector simulation and do not model backend noise. Sampler is finite-shot; zero-precision Estimator is exact only for unitary state preparation.
197Memory for a dense statevector grows as \(2^n\). Use an algorithm-appropriate Aer method or tensor-network tooling for larger circuits.

Ideal Local Primitives

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. Sampler is finite-shot; zero-precision Estimator is exact only for unitary state preparation.

Memory for a dense statevector grows as \(2^n\). Use an algorithm-appropriate Aer method or tensor-network tooling for larger circuits.

Raw lines 184 to 198
199## Aer Simulation
201Install the pinned Aer distribution:
203```bash
204uv pip install "qiskit-aer==0.17.2"
205```
207Create an ideal Aer backend:
209```python
210from qiskit_aer import AerSimulator
212aer = AerSimulator(method="automatic")
213```
215Run through Runtime's local-testing primitive interface:
217```python
218from qiskit.transpiler import generate_preset_pass_manager
219from qiskit_ibm_runtime.executor_sampler import Sampler
221pass_manager = generate_preset_pass_manager(
222 backend=aer,
223 optimization_level=1,
224 seed_transpiler=23,
226isa_circuit = pass_manager.run(circuit)
228sampler = Sampler(
229 mode=aer,
230 options={"simulator": {"seed_simulator": 23}},
232result = sampler.run([isa_circuit], shots=1024).result()
233```
235The Runtime 0.50 client-side primitives perform preprocessing and postprocessing locally, including enabled mitigation/twirling paths. This differs from deprecated server-side primitives whose local mode ignored many options. Use `resilience_level=0` for an unmitigated Estimator baseline and inspect finalized options. Local results still do not verify service limits, scheduling, costs, or QPU mitigation effectiveness. `dry_run=True` on a remote backend is a server job returning random mock data, not Aer simulation.

Aer Simulation

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.executor_sampler import 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()

The Runtime 0.50 client-side primitives perform preprocessing and postprocessing locally, including enabled mitigation/twirling paths. This differs from deprecated server-side primitives whose local mode ignored many options. Use resilience_level=0 for an unmitigated Estimator baseline and inspect finalized options. Local results still do not verify service limits, scheduling, costs, or QPU mitigation effectiveness. dry_run=True on a remote backend is a server job returning random mock data, not Aer simulation.

Raw lines 199 to 236
237## Approximate a Real Backend in Aer
239```python
240from qiskit_aer import AerSimulator
242noisy_aer = AerSimulator.from_backend(backend)
243pass_manager = generate_preset_pass_manager(
244 backend=noisy_aer,
245 optimization_level=1,
246 seed_transpiler=23,
248noisy_isa = pass_manager.run(circuit)
250sampler = Sampler(
251 mode=noisy_aer,
252 options={"simulator": {"seed_simulator": 23}},
254result = sampler.run([noisy_isa], shots=4096).result()
255```
257This captures a subset of backend properties at model-construction time. It does not reproduce drift, all crosstalk, or every Runtime service behavior.

Approximate a Real Backend in Aer

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.

Raw lines 237 to 258
259## Fake Backends
261Fake backends provide a local `BackendV2` target and calibration-like snapshot:
263```python
264from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
266fake_backend = FakeSherbrooke()
267```
269Use 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.

Fake Backends

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.

Raw lines 259 to 270
271## Estimator Noise Management
273Runtime Estimator exposes increasing levels of built-in mitigation:
275```python
276from qiskit_ibm_runtime.executor_estimator import Estimator
278estimator = Estimator(
279 mode=backend,
280 options={"resilience_level": 1},
282```
284Current supported resilience levels:
286- `0`: disable built-in resilience.
287- `1`: measurement mitigation.
288- `2`: measurement mitigation plus additional techniques such as ZNE, according to current defaults.
290There is no resilience level 3 in the current V2 API.
292Configure explicit techniques when the experiment requires control:
294```python
295estimator = Estimator(mode=backend)
296estimator.options.dynamical_decoupling.enable = True
297estimator.options.dynamical_decoupling.sequence_type = "XpXm"
299estimator.options.twirling.enable_gates = True
300estimator.options.twirling.num_randomizations = 32
301estimator.options.twirling.shots_per_randomization = 100
303estimator.options.resilience.zne_mitigation = True
304estimator.options.resilience.zne.noise_factors = (1, 3, 5)
305estimator.options.resilience.zne.extrapolator = "exponential"
306```
308Mitigation adds bias assumptions, circuit variants, shots, classical processing, and cost. It is not guaranteed to improve an observable.

Estimator Noise Management

Runtime Estimator exposes increasing levels of built-in mitigation:

from qiskit_ibm_runtime.executor_estimator import 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.

Raw lines 271 to 309
310## Sampler Noise Management
312Sampler returns sampled classical data and does not use Estimator resilience levels:
314```python
315sampler = Sampler(mode=backend)
316sampler.options.dynamical_decoupling.enable = True
317sampler.options.dynamical_decoupling.sequence_type = "XpXm"
318sampler.options.twirling.enable_gates = True
319```
321Measurement and gate-twirling defaults differ between Sampler and Estimator. Record `primitive.finalize_options().model_dump()` for the client-side implementation. Measurement mitigation forces measurement twirling; gate-based mitigation can force both. Explicitly enabled methods can override the meaning of `resilience_level=0`.

Sampler Noise Management

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. Record primitive.finalize_options().model_dump() for the client-side implementation. Measurement mitigation forces measurement twirling; gate-based mitigation can force both. Explicitly enabled methods can override the meaning of resilience_level=0.

Raw lines 310 to 322
323## Feature Compatibility
325Some combinations are restricted. Current examples include incompatibilities among:
327- fractional gates,
328- gate twirling,
329- probabilistic error amplification (PEA),
330- probabilistic error cancellation (PEC),
331- gate-folding zero-noise extrapolation (ZNE),
332- some dynamic-circuit features.
334Client-side Sampler 0.50 rejects input `BoxOp` circuits (including with twirling enabled in the tested wheel); dynamical decoupling rejects dynamic control flow. This is stricter than the current Sampler page, which only mentions boxes when twirling is disabled. Always consult the current Estimator/Sampler options and backend target. Do not copy a mitigation configuration between Runtime versions without revalidation.

Feature Compatibility

Some combinations are restricted. Current examples include incompatibilities among:

  • fractional gates,
  • gate twirling,
  • probabilistic error amplification (PEA),
  • probabilistic error cancellation (PEC),
  • gate-folding zero-noise extrapolation (ZNE),
  • some dynamic-circuit features.

Client-side Sampler 0.50 rejects input BoxOp circuits (including with twirling enabled in the tested wheel); dynamical decoupling rejects dynamic control flow. This is stricter than the current Sampler page, which only mentions boxes when twirling is disabled. Always consult the current Estimator/Sampler options and backend target. Do not copy a mitigation configuration between Runtime versions without revalidation.

Raw lines 323 to 335
336## Fractional Gates
338Request a backend target that exposes fractional gates when the algorithm benefits:
340```python
341backend = service.backend(
342 backend_name,
343 use_fractional_gates=True,
345```
347Compile against the returned object. `use_fractional_gates` changes the target and can affect compatibility with control flow and mitigation.
349Qiskit Pulse is not an alternative; `qiskit.pulse` was removed in Qiskit 2.0.

Fractional Gates

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.

Raw lines 336 to 350
351## Third-Party Providers
353Qiskit can target non-IBM providers through separately installed provider packages. Each provider controls:
355- authentication,
356- backend discovery,
357- supported `BackendV2` features,
358- whether native V2 primitives exist,
359- transpilation plugins,
360- result and cost semantics.
362Prefer 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.

Third-Party Providers

Qiskit can target non-IBM providers through separately installed provider packages. Each provider controls:

  • authentication,
  • backend discovery,
  • supported BackendV2 features,
  • whether native V2 primitives exist,
  • transpilation plugins,
  • result and cost semantics.

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.

Raw lines 351 to 363
364## Operational Checklist
366Before submitting:
3681. Verify the account, plan, instance, and region.
3692. Select a backend by circuit width and capabilities.
3703. Compile and test locally against a fake/noisy backend.
3714. Apply the circuit layout to Estimator observables.
3725. Estimate the number of PUBs, circuits after randomization/mitigation, shots, and maximum execution time.
3736. Choose job, batch, or session mode.
3747. Save job IDs immediately.
3758. Store versions, backend, target timestamp, compiler seed, primitive options, and metadata.

Operational Checklist

Before submitting:

  1. Verify the account, plan, instance, and region.
  2. Select a backend by circuit width and capabilities.
  3. Compile and test locally against a fake/noisy backend.
  4. Apply the circuit layout to Estimator observables.
  5. Estimate the number of PUBs, circuits after randomization/mitigation, shots, and maximum execution time.
  6. Choose job, batch, or session mode.
  7. Save job IDs immediately.
  8. Store versions, backend, target timestamp, compiler seed, primitive options, and metadata.
Raw lines 364 to 376
377## Common Failures
379- **Authentication failure**: use `ibm_quantum_platform`, verify the saved account, API key, and instance access.
380- **Backend not found**: list accessible backends; systems and account entitlements change.
381- **Circuit not ISA-compatible**: submit the circuit returned by the backend-specific pass manager.
382- **Open Plan session error**: use job or batch mode.
383- **Unsupported option combination**: check the current feature-compatibility table.
384- **Unexpected queue/cost**: inspect the plan, mode TTL, precision, shots, mitigation, and twirling expansion.
385- **Simulation differs from QPU**: document the model snapshot and unmodeled effects rather than tuning until outputs match.

Common Failures

  • Authentication failure: use ibm_quantum_platform, verify the saved account, API key, and instance access.
  • Backend not found: list accessible backends; systems and account entitlements change.
  • Circuit not ISA-compatible: submit the circuit returned by the backend-specific pass manager.
  • Open Plan session error: use job or batch mode.
  • Unsupported option combination: check the current feature-compatibility table.
  • Unexpected queue/cost: inspect the plan, mode TTL, precision, shots, mitigation, and twirling expansion.
  • Simulation differs from QPU: document the model snapshot and unmodeled effects rather than tuning until outputs match.
Raw lines 377 to 385