Steven GellerQuantum Computing, End to End

Book contents

Current section

Part V. Practical Software

  1. Python and Quantum Programming Workflow
  2. Building a Small Simulator From Scratch
  3. Qiskit, Primitives, and Circuit Execution
  4. Cirq and Alternative Toolchains
  5. Transpilation and Hardware-Aware Compilation
  6. Noise Models and Noisy Simulation
  7. Benchmarking Quantum Programs
  8. Resource Estimation for Fault-Tolerant Algorithms
  9. Reproducible Quantum Labs

Part V. Practical Software · Chapter 38

Qiskit, Primitives, and Circuit Execution

An SDK tutorial can put a Bell circuit on screen in ten minutes; knowing whether the output means anything takes a bit more structure. This chapter separates the stable execution workflow — build, choose a backend, set shots, record, interpret — from the API surface that keeps changing underneath it.

Lab
In this chapter 11 sections

Define the circuit and observable independently of the backend, use the appropriate primitive for expectation estimation or sampled outcomes, pin the Qiskit version and execution options, and store the transpiled circuit, shots or precision target, backend identity, and result schema.

The useful distinction is semantic, not syntactic: an estimator answers a question about an observable; a sampler answers a question about a distribution. A versioned adapter makes those contracts explicit without promoting today’s class names into timeless pedagogy.

One circuit enters two execution contractscircuit + metadataEstimator: E[O]Sampler: Pr(x)precision + observableshots + bit map
Figure 38.1. Sharing a circuit does not make the result types interchangeable. Their inputs, uncertainty, and validation rules differ.

Sampler and estimator answer different questions

For a state ψ\lvert \psi \rangle and observable O, an estimator targets E[O]=ψOψE[O]=\langle\psi|O|\psi\rangle. A sampler approximates Pr(X=x)\Pr(X=x) through finite draws. Qiskit documents these as distinct primitive interfaces [Qiskit primitives documentation]. The estimator needs an observable and precision contract; the sampler needs measurement interpretation and a shot contract.

Keep a framework-neutral fixture beside the adapter: circuit operations in the book’s q0-most-significant convention, the analytic expectation or exact support, tolerances, and an acceptance rule. OpenQASM 3 can record circuit and control semantics, while QIR defines an intermediate-representation contract; neither makes interchange automatic [OpenQASM 3 specification] [QIR Alliance specification].

The pinned Qiskit environment

The lab records Python, exact Qiskit distribution versions, a lock hash, imports, primitive implementation, and review date. It does not install Qiskit in the core lab environment. Optional dependency churn should break an optional adapter job, not the reference simulator. Store the output schema version too: a numerical result can remain correct while a container or metadata field changes.

Execution envelope
Interpreterexact major/minor; supported platform
Resolver evidencelock file and SHA-256
Primitivefully qualified implementation and options
Targetideal reference or named backend identity
Reviewdate plus migration owner

Estimate Z after a Hadamard

Prepare +\lvert + \rangle by applying H to 0\lvert 0 \rangle and ask for Pauli Z. Analytically, the +1 and −1 eigenvalues have equal weight, so E[Z]=0. This is an expectation check, not a histogram check. Store circuit and observable hashes, estimator options, returned value, target precision, and metadata. On an ideal reference primitive, use a tight numerical tolerance. On shot-based or hardware execution, attach an uncertainty method and backend evidence.

The derivation is the durable oracle. The Qiskit call is a dated adapter. That separation allows an API migration to alter imports or result extraction without altering the expected value.

The zero expectation alone is a weak fixture: the states 0\lvert 0 \rangle and 1\lvert 1 \rangle could be accidentally averaged by a broken batch adapter and also yield zero. Add anchor cases. For 0\lvert 0 \rangle, Z=1\langle Z\rangle=1; for 1\lvert 1\rangle, Z=1\langle Z\rangle=-1; for +\lvert +\rangle, X=1\langle X\rangle=1 and Z=0\langle Z\rangle=0. The set exercises state preparation, observable ordering, sign, and batch alignment. Store results keyed by stable case IDs rather than assuming the returned list is in submission order.

For a Pauli observable with eigenvalues ±1 estimated from nn independent shots, a sample mean E^\hat E has estimated standard error (1E^2)/n\sqrt{(1-\hat E^2)/n} under the simple binomial model. An ideal state-vector estimator has numerical error instead, so reporting “shots” for it is a category mistake. The record schema should make the uncertainty source explicit: analytic, finite-shot, mitigation-derived, or backend-reported.

Sample a Bell circuit without losing bit order

The paired sampler fixture prepares the Bell state and measures both qubits. Exact support is {00,11}; expected probability is one half for each. Finite shots fluctuate. With n shots and ideal p=0.5, a simple teaching band can use C00/n[0.53/(2n),0.5+3/(2n)]C_{00}/n\in[0.5-3/(2\sqrt n),0.5+3/(2\sqrt n)]. This is an explicitly declared normal-approximation fixture, not a universal test.

Finite-shot output cannot be interpreted like a state vector [Nielsen and Chuang] [benchmarking review]. Normalize the SDK’s native classical-bit display into the book convention before comparing support, and preserve the native record so the translation remains auditable.

Bell support is deliberately paired with asymmetric calibration fixtures. Prepare 01 and 10, measure them, and verify the adapter maps each native key to the intended book string. Without those rows, reversing both classical columns leaves 00 and 11 unchanged and the headline test passes. The normalization function should receive the explicit logical-to-classical map emitted by compilation; it should never infer order from dictionary iteration or a formatted histogram label.

Quasi-distributions need another boundary. Error mitigation can produce small negative weights or values above one, which are not raw counts and must not be rounded into a histogram. Retain the native numeric type, normalization convention, and mitigation metadata. A sampler acceptance test may compare an explicitly normalized probability estimate, but its record must distinguish that estimate from observed integer frequencies.

Pinned Qiskit sampler/estimator lab

Stored primitive assertions
caseoracleevidence
H then Z estimatorE[Z]=0value, precision, observable/circuit hashes
Bell samplersupport 00/11, p=.5/.5shots, seed, native and normalized bit maps
migrationsame semantic oracleold/new schema diff
from math import sqrt
def band(shots, sigma=3):
    if type(shots) is not int or shots <= 0:
        raise ValueError("shots must be a positive integer")
    half_width = sigma / (2 * sqrt(shots))
    return 0.5 - half_width, 0.5 + half_width

records = [
    {"shots": 1_000, "counts": {"00": 508, "11": 492}},
    {"shots": 10_000, "counts": {"00": 4_963, "11": 5_037}},
]
thousand_band = band(1_000)
ten_thousand_band = band(10_000)
assert abs(0.0) <= 1e-12  # analytic H-Z estimator oracle
for record in records:
    assert set(record["counts"]) == {"00", "11"}
    assert sum(record["counts"].values()) == record["shots"]
    lo, hi = band(record["shots"])
    assert lo <= record["counts"]["00"] / record["shots"] <= hi
invalid_rejected = False
try:
    band(0)
except ValueError:
    invalid_rejected = True
assert ten_thousand_band[1] - ten_thousand_band[0] < thousand_band[1] - thousand_band[0]
assert invalid_rejected
print(f"PASS: 38 primitives band1000={thousand_band} band10000={ten_thousand_band} invalid_shots={invalid_rejected}")

Transpiled evidence belongs in the record

Backend compilation and measurement conventions are evidence, not plumbing [benchmarking review]. Record target identity, native instruction set, initial/final layout, optimization level, seed, native gate counts, depth in layers, measurement map, and transpiled-circuit hash. A result from an ideal primitive and one from a named processor may share an API while supporting different claims.

Parameter binding is part of this evidence. Hash the symbolic circuit, the ordered parameter names, and the bound numeric vector separately. A batch in which angles are transposed can return correctly shaped data for the wrong experiments. Before interpreting values, assert that every submitted case ID, observable ID, and parameter-set ID appears exactly once in the result record.

Migration test for the next Qiskit release

On a schedule, create a fresh environment with the candidate version, run schema tests before numerical tests, and classify failure as import/API, metadata/schema, circuit translation, or changed numerical semantics. Never update expected output merely because the new adapter emits it. Re-derive the oracle, document the migration, and retain the last passing record.

A schema migration should be narrow enough to review. Capture the old native result and the new native result, normalize both through version-specific readers, and compare the small semantic record. If the semantic record agrees, the change is an adapter migration. If it differs, stop and inspect transpilation, parameter association, observable convention, and bit order before changing a tolerance. Wider tolerances are not a remedy for a permuted experiment batch.

The deterministic and stochastic checks deliberately fail differently. A state-vector or exact reference expectation outside 10−12 is a semantic or numerical defect; rerunning it with more shots has no meaning. A finite-shot Bell frequency outside its predeclared interval is a statistical alert whose record includes n and the test method. Repeated alerts across independent seeds may motivate model investigation, but one alert is not automatically an adapter bug.

Store the two output schemas separately. The estimator row contains observable ID, value, uncertainty source, target precision, and backend metadata. The sampler row contains native keys, logical keys, integer shots when applicable, probabilities or quasi-weights with their numeric kind, and measurement mapping. A field named result that alternates between float, array, and distribution defeats schema validation.

The optional Qiskit job must be allowed to report unavailable. That state records the pinned environment requested, platform, resolver or import failure, and last known passing version. It does not convert the framework-neutral analytic fixtures into failures, and it does not disappear from the release record. This boundary keeps a software migration from rewriting the physics oracle.

Case identifiers must survive batching, transpilation, and result extraction. Assert their cardinality and order before attaching values to observables; otherwise a perfectly shaped array can associate the Bell sample with the Hadamard expectation. Shape validation is necessary, but semantic keys make the result reviewable.

Two-shot sampler audit

Prompt: Run the same Bell circuit through a Qiskit sampler at two shot counts, retain the transpiled circuit and metadata, and explain whether the frequency difference is statistically ordinary.

Deliverable: Pinned environment file, source module, two JSON result records, and a calculation of the acceptance intervals.

Pass condition: Both records identify version/backend/layout/shots; no impossible ideal outcomes occur; observed 00 and 11 frequencies fall inside the predeclared interval.

Reference package

Format: Version-specific reference module, stored records, and analytic binomial calculation.

Verification: CI recreates the optional environment and checks schema, metadata, circuit hash, total shots, support, and interval membership.

Both records preserve only 00 and 11, their counts sum to their declared shots, and each observed 00 fraction falls within the predeclared shot-dependent interval. A difference between the two fractions is therefore ordinary sampling evidence, not a changed state, provided the transpiled circuit and bit map also match.

Companion work

Artifacts for this chapter

These entries resolve to checked-in local source. Commands are reproduced exactly from the chapter manifest, and source-embedded fixtures are exported as direct downloads.

  1. Reproduce or test

    python3 tools/validate_briefs.py --briefs data/editorial_briefs_36_63.json --from 36 --through 63 --check-rewritten-sources --execute-artifacts

Provenance

Sources and review

  1. IBM Quantum. Qiskit documentation. IBM. 2026official documentation
  2. OpenQASM Technical Steering Committee. OpenQASM 3 specification. Linux Foundation Joint Development Foundation. 2026official technical specification
  3. QIR Alliance. Quantum Intermediate Representation specification and projects. Linux Foundation Joint Development Foundation. 2026official technical specification
  4. Michael A. Nielsen and Isaac L. Chuang. Quantum Computation and Quantum Information. Cambridge University Press. 2010textbook
  5. Timothy Proctor et al.. Benchmarking quantum computers. Nature Reviews Physics. 2025peer-reviewed perspective

The load-bearing claims in the chapter are mapped inline to this registered source set. A citation supports only the bounded claim beside it.

Cite this chapter