ψ QuantumVerseInterview preparation
Φ · Interview preparation

Qiskit Reference

Study questions and source-based explanations extracted from the supplied PDF. Mathematical expressions are reproduced as text here; use the original PDF for authoritative typesetting and complex formula layout.

Open original PDF   All subjects

3456789101112131415161718

Source page 3

Qiskit Reference Deck 1 SDK Architecture & Core Concepts SDK Architecture & Core Concepts

Q1.1 What is Qiskit, and how is the SDK split into separate packages since the Qiskit 1.0 stabi- lization?
Qiskit is IBM’s open-source Python SDK for building, transpiling, and running quantum circuits, both on lo- cal simulators and real superconducting quantum hardware accessed via IBM Quantum. Since the Qiskit 1.0 re- lease, the project deliberately split what used to be one large, monolithic package into focused, independently- versioned components: qiskit (the core SDK – circuit construction, transpiler, quantum_info, primitives inter- faces), qiskit-aer (high-performance local simulators, now installed separately via pip install qiskit-aer), and qiskit-ibm-runtime (the client for submitting jobs to real IBM Quantum hardware and cloud-based primi- tives). This split lets each component evolve, version, and release on its own schedule, rather than forcing every user to take on simulator or cloud-runtime dependencies just to build and manipulate circuits locally.
Q1.2 What is a QuantumCircuit, and what are its two fundamental register types?
QuantumCircuit is Qiskit’s central data structure representing a quantum program as an ordered sequence of in- structions (gates, measurements, control-flow blocks) acting on qubits and, for measurement outcomes, classical bits. A circuit is built from a QuantumRegister (a named group of qubits) and a ClassicalRegister (a named group of classical bits used to store measurement results) – though for quick scripting, QuantumCircuit(n, m) directly creates n qubits and m classical bits without needing to explicitly instantiate register objects. from qiskit import QuantumCircuit qc = QuantumCircuit(2, 2) # 2 qubits , 2 classical bits qc.h(0) # Hadamard on qubit 0 qc.cx(0, 1) # CNOT: qubit 0 controls qubit 1 qc.measure([0, 1], [0, 1]) # measure both qubits into both clbits
Q1.3 Why does Qiskit’s current, recommended execution model center on Primitives (Sampler and Estimator) rather than the older backend.run() pattern?
The older pattern (backend.run(circuit)) returns only raw measurement counts, leaving the user responsible for manually converting those counts into whatever higher-level quantity (an expectation value, a probability distribution) their algorithm actually needs – and provides no standard, built-in hooks for error mitigation. Primitives instead expose two task-oriented interfaces matching what most quantum algorithms actually want: Sampler returns quasi- probability distributions over measurement outcomes, and Estimator directly returns expectation values of specified observables – with built-in, configurable error suppression/mitigation particularly important for running on real, noisy hardware. This primitives-first model is now the standard, actively promoted way to write portable Qiskit algorithm code, whether targeting a local simulator or real IBM Quantum hardware, since both expose the same Sampler/Estimator interface.
Q1.4 What is a PUB (Primitive Unified Bloc), and why did the V2 primitives introduce this concept over the V1 primitives’ simpler, separate-list-based interface?
A PUB bundles everything one ”unit of work” submitted to a primitive needs into a single tuple: a circuit, plus (for

Source page 4

Qiskit Reference Deck 1 Estimator) the observable(s) to measure, plus any parameter values to bind, plus an optional per-PUB shot count. V1 primitives instead required passing separate, index-aligned lists of circuits, observables, and parameter values, forcing awkward duplication (e.g. repeating the same circuit multiple times just to pair it with different parameter sets or observables) and making it error-prone to keep those parallel lists correctly aligned. The PUB structure lets a single circuit be efficiently paired with many observables and/or parameter-value sweeps in one call, and is the reason V2 primitives (SamplerV2, EstimatorV2) are the current standard – V1 primitives were fully removed from qiskit-ibm-runtime in August 2024. from qiskit.primitives import StatevectorEstimator as Estimator from qiskit.quantum_info import SparsePauliOp estimator = Estimator() observable = SparsePauliOp("ZZ") job = estimator.run([(qc, observable)]) # a single PUB: (circuit , observable) result = job.result()[0].data.evs # expectation value(s)

Q1.5 What is the difference between BackendV1 and BackendV2, and why does essentially all current Qiskit tooling now assume the Target-based BackendV2 interface?
BackendV1 described a backend’s capabilities through several separate, loosely-connected pieces (a configuration object, a properties object for calibration data, and a defaults object for pulse defaults) that could drift out of sync and were awkward to query programmatically. BackendV2 consolidates all of this into a single, unified Target object – a structured description of exactly which instructions the backend supports, on which qubits/qubit-pairs, together with their duration, error rate, and other calibration data, all in one queryable place. Modern Qiskit’s transpiler, primitives, and provider integrations are all built directly around the Target/BackendV2 model, and BackendV1 support has been fully removed from current Qiskit – any lingering BackendV1-based provider code needs to be migrated to BackendV2 to work with current Qiskit versions.

Source page 5

Qiskit Reference Deck 2 Building Circuits Building Circuits

Q2.1 What is a Parameter, and why is building a circuit with symbolic, unbound parameters preferable to constructing a brand-new circuit object for every different set of rotation an- gles?
A Parameter is a named, symbolic placeholder that can be used in place of a concrete numerical value anywhere a circuit expects one (most commonly, a gate’s rotation angle) – letting you build the circuit’s structure exactly once, then bind different concrete numerical values to it later, as many times as needed. This matters enormously for variational algorithms (VQE, QAOA) and parameter sweeps, where the same circuit structure must be evaluated repeatedly with many different parameter values during optimization – building and transpiling a fresh circuit object from scratch for every iteration would be wasteful, since transpilation (Section 3) is one of the more expensive steps in the pipeline; with a parameterized circuit, the expensive transpilation step is performed once, and only cheap numerical parameter binding is repeated on each iteration. from qiskit.circuit import Parameter theta = Parameter("theta") qc = QuantumCircuit(1) qc.ry(theta, 0) bound_qc = qc.assign_parameters({theta: 1.57}) # bind a concrete value
Q2.2 What is the difference between compose() and simply appending gates directly onto an existing QuantumCircuit, and when is compose() the right tool?
Directly calling gate methods (qc.h(0), qc.cx(0,1)) appends individual instructions one at a time to a single cir- cuit object. compose() instead takes a separate, already-built QuantumCircuit (often one representing a reusable subroutine – a state-preparation block, an entangling layer, or a previously-built ansatz) and inserts its entire instruc- tion sequence into another circuit at a specified qubit/clbit mapping, optionally at a specific insertion point. This is the standard way to build larger circuits compositionally out of smaller, independently-constructed, and independently- testable building blocks, rather than writing one long, monolithic sequence of gate calls – particularly valuable when the same reusable sub-circuit (e.g. a Bell-pair preparation routine) needs to be inserted into several different larger circuits.
Q2.3 What is the qiskit.circuit.library, and why does using its pre-built circuit constructs (like EfficientSU2 or QFT) tend to be preferable to hand-writing the equivalent gate se- quence yourself?
The circuit library is a collection of pre-built, parameterized, well-tested circuit constructs for common patterns – variational ansätze (EfficientSU2, TwoLocal, RealAmplitudes), the Quantum Fourier Transform (QFT), and various standard state-preparation and arithmetic circuits. Using these is generally preferable to hand-rolling the equivalent gate sequence because they’re already validated for correctness, expose sensible, well-documented con- figuration options (entanglement pattern, repetition count, rotation gate choice) covering the vast majority of practical variations users actually need, and are maintained/optimized by the Qiskit team itself – reducing both the risk of a subtle hand-written bug and the amount of boilerplate circuit-construction code a project needs to maintain. from qiskit.circuit.library import EfficientSU2

Source page 6

Qiskit Reference Deck 2 ansatz = EfficientSU2(num_qubits=4, reps=2, entanglement="linear") print(ansatz.num_parameters) # ready-to-optimize parameterized ansatz

Q2.4 What is the modern, recommended way to build classically-conditioned logic in a circuit (an if_test block), and why was the older c_if method removed in Qiskit 2.0?
The legacy c_if method attached a classical condition directly onto a single gate call (e.g. qc.x(0).c_if(creg, 1)), which only supported simple register-equality conditions and didn’t compose well with more expressive classical logic or nested control flow. Qiskit 2.0 removed c_if entirely in favor of the if_test context manager, which wraps a genuine IfElseOp block around one or more instructions, supporting richer conditions (including expressions built from Qiskit’s classical-expression system, not just simple register equality) and nesting cleanly with other control- flow constructs like while_loop and for_loop – part of Qiskit’s broader, ongoing investment in dynamic circuits (classical control flow interleaved with quantum operations, mid-circuit measurement feeding real-time decisions) as a first-class capability. qc = QuantumCircuit(2, 2) qc.h(0) qc.measure(0, 0) with qc.if_test((qc.clbits[0], 1)): # if clbit 0 measured as 1 qc.x(1)

Source page 7

Qiskit Reference Deck 3 Transpilation & ISA Circuits Transpilation & ISA Circuits

Q3.1 What does transpile() actually do, and why is a circuit written in ”any” gates almost never directly runnable on real hardware without it?
Real quantum hardware only natively supports a small, fixed set of basis gates (e.g. a specific single-qubit rotation plus one two-qubit entangling gate) and has restricted qubit connectivity (only certain physical qubit pairs can be directly entangled) – a circuit written using arbitrary, convenient gates (a Toffoli, an arbitrary controlled-U, a SWAP between two non-adjacent qubits) generally cannot run as-is. transpile() (or, more flexibly, a PassManager built via generate_preset_pass_manager()) rewrites the circuit into an equivalent one expressed entirely in the target backend’s native gates, with two-qubit operations remapped only onto physically connected qubit pairs (inserting SWAP gates where necessary), while also applying various optimization passes to reduce the resulting gate count and circuit depth – since deeper circuits accumulate more noise/decoherence on real, imperfect hardware. from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager pm = generate_preset_pass_manager(optimization_level=3, backend=backend) isa_circuit = pm.run(qc)
Q3.2 What is an ”ISA circuit,” and why does Qiskit Runtime require every circuit submitted to a primitive to already be transpiled into this form before it’s accepted?
An ISA (Instruction Set Architecture) circuit is one that has already been transpiled to use only instructions and qubit connections genuinely present in the target backend’s Target – exactly matching what that specific piece of hardware can actually execute natively. Since March 2024, Qiskit Runtime requires every circuit (and, for Estimator, every associated observable) submitted to a primitive to already be in ISA form – submitting a non-ISA circuit raises an explicit error rather than being silently, automatically transpiled server-side. This shift makes transpilation an explicit, visible step the user controls and reasons about directly (rather than an invisible, potentially inconsistent step performed automatically behind the scenes), and it means an observable like a SparsePauliOp must also have its qubit layout explicitly applied (observable.apply_layout(isa_circuit.layout)) to correctly match the transpiled circuit’s possibly-permuted qubit ordering.
Q3.3 What do Qiskit’s four transpiler optimization_level settings (0 through 3) control, and what is the practical trade-off between choosing a higher versus a lower level?
The optimization level controls how much effort the transpiler’s preset pass managers spend trying to reduce the final circuit’s gate count/depth and improve qubit-layout selection: level 0 does the bare minimum needed to make the circuit runnable (basic translation and routing, essentially no optimization); level 1 adds light optimization (removing some redundant gates); level 2 performs more thorough gate cancellation and improved routing/layout heuristics; level 3 runs the most aggressive available optimization passes, including more expensive synthesis and noise-adaptive layout selection. The practical trade-off is straightforward: higher levels generally produce shorter, less noisy circuits (better results on real hardware) at the cost of significantly longer classical transpilation time – for quick local testing, level 1 is often adequate, while level 3 is typically worth its extra compile time before submitting a circuit to actual, error-prone quantum hardware.

Source page 8

Qiskit Reference Deck 3

Q3.4 What replaced the deprecated StochasticSwap routing pass as Qiskit’s default routing algorithm, and what specific advantage does it offer?
StochasticSwap (deprecated in Qiskit 1.3, removed in 2.0) inserted SWAP gates using a randomized search heuris- tic to route two-qubit operations onto connected physical qubits. SabreSwap (Sabre = SWAP-based Bidirectional heuristic search) is now the default routing pass, using a more sophisticated bidirectional lookahead search that con- siders both the circuit’s forward and reverse instruction order when deciding where to insert SWAPs and which initial qubit layout to choose – consistently producing measurably fewer inserted SWAP gates (and therefore shallower, less noisy final circuits) than the older stochastic approach, while also typically running faster during transpilation itself.

Source page 9

Qiskit Reference Deck 4 Primitives: Sampler & Estimator Primitives: Sampler & Estimator

Q4.1 What is the difference between SamplerV2 and EstimatorV2, and how do you decide which one a given algorithm needs?
SamplerV2 runs a circuit (which must include measurements) and returns the raw measurement outcomes – bit- string counts/quasi-probabilities – appropriate whenever an algorithm’s actual output is a probability distribution over bitstrings (e.g. Grover’s algorithm, QAOA’s final solution readout, or general circuit sampling). EstimatorV2 instead takes a circuit without measurements plus one or more observables, and directly returns expectation values ⟨ψ| ˆO|ψ⟩– appropriate whenever the actual quantity of interest is an expectation value rather than a raw distribu- tion (e.g. VQE’s energy estimate, or any expectation-value-based cost function). Choosing the right primitive up front avoids manually computing an expectation value yourself from raw Sampler counts, a step Estimator already handles internally, including applying any configured error mitigation.
Q4.2 What does the resilience_level option on EstimatorV2 control when running on real IBM Quantum hardware, and what specific error-mitigation technique does the higher lev- els typically enable?
resilience_level trades off result accuracy against classical/quantum runtime overhead by selecting which built- in error suppression and mitigation techniques Qiskit Runtime automatically applies. Level 0 applies no mitigation at all (fastest, rawest result). Level 1 (the default) applies twirled readout error extinction (TREX) to mitigate mea- surement/readout errors. Level 2 additionally applies Zero Noise Extrapolation (ZNE) – deliberately running the circuit at several artificially amplified noise levels and extrapolating the resulting expectation values back to the (un- reachable) zero-noise limit – at the cost of several times more total shots/runtime, since each noise-amplification level requires its own separate execution. Choosing the right resilience level is a direct, explicit trade-off between result fidelity and both cost and turnaround time on real hardware.
Q4.3 Why must you explicitly bind concrete parameter values to a parameterized circuit before submitting it as part of a PUB to a primitive, rather than passing the parameterized circuit directly?
While QuantumCircuit objects can hold symbolic, unbound Parameter placeholders (Section 2) for convenient, reusable circuit construction, a primitive job ultimately must execute one (or more, per PUB) fully concrete circuit(s) with definite numerical gate parameters – there is no such thing as ”running” an unbound symbolic circuit directly. A PUB’s parameter-values component is exactly what supplies these concrete numbers at submission time: (circuit, observable, parameter_values) for Estimator, or (circuit, parameter_values) for Sampler – and, importantly, a single PUB can supply an entire array of different parameter-value sets in one call, letting one submitted job efficiently sweep over many parameter combinations (e.g. every iteration’s trial point during a VQE optimization loop) without needing a separate job submission per parameter set. import numpy as np from qiskit.primitives import StatevectorEstimator as Estimator param_values = np.linspace(0, np.pi, 20) # sweep 20 angle values job = Estimator().run([(qc, observable, param_values)])

Source page 10

Qiskit Reference Deck 4

Q4.4 What is the difference between the plain qiskit.primitives reference implementations (e.g. StatevectorSampler) and the qiskit_ibm_runtime primitives, given that both ex- pose the identical V2 interface?
The qiskit.primitives module’s reference implementations (StatevectorSampler, StatevectorEstimator) compute results via exact local state-vector simulation – fast for small circuits, noise-free, and requiring no network access or IBM Quantum account, ideal for local algorithm development, unit testing, and debugging. qiskit_ibm_runtime’s SamplerV2/EstimatorV2 instead submit the job to actual IBM Quantum hardware or cloud-hosted simulators, subject to real device noise (or, for cloud simulators, configurable noise models), queue wait times, and the resilience-level error-mitigation options discussed above. Because both expose the exact same primitive interface, well-written algorithm code can typically swap between the two with minimal changes – developing and validating against the fast local reference implementation before submitting the identical logic to real hardware via the runtime primitives.

Source page 11

Qiskit Reference Deck 5 Running on Hardware & Qiskit Runtime Running on Hardware & Qiskit Runtime

Q5.1 What is QiskitRuntimeService, and what is the typical first step for connecting to and selecting an actual IBM Quantum backend?
QiskitRuntimeService is the main client class for authenticating with IBM Quantum’s cloud platform, discovering available backends (real devices and cloud-hosted simulators), and submitting primitive jobs to them. A typical workflow instantiates the service (using saved or explicitly provided account credentials), then either selects a specific named backend or uses least_busy() to automatically pick whichever currently-operational device (matching any specified constraints, like a minimum qubit count) has the shortest queue – a common, practical default for routine development work where any sufficiently large, healthy device will do. from qiskit_ibm_runtime import QiskitRuntimeService service = QiskitRuntimeService() # uses saved account credentials backend = service.least_busy(operational=True, min_num_qubits=27)
Q5.2 What is the difference between running primitive jobs in plain job mode, inside a Session, and inside a Batch?
Job mode (the default when no session/batch context is active) submits each primitive call as an entirely indepen- dent job, queued and scheduled on its own – simplest, but offers no guarantee of low latency between related calls, since other users’ jobs can be interleaved in the queue between yours. A Session reserves a period of dedicated, low-latency access to a backend across multiple sequential primitive calls – valuable for iterative algorithms (like VQE) where each iteration’s next circuit depends on the previous iteration’s measured result, and queueing delays between iterations would otherwise dominate total runtime. A Batch instead groups multiple, mutually independent jobs together for efficient parallel/bulk submission and scheduling (e.g. running many independent circuits from a parameter sweep) without needing the strict sequential low-latency guarantee a Session provides – choosing the right mode meaningfully affects both cost and turnaround time for a given workload’s actual access pattern.
Q5.3 What is a Qiskit Function, and how does it extend the runtime execution model beyond simply running individual circuits through a primitive?
A Qiskit Function is a higher-level, packaged service (offered by IBM or third-party providers through the Qiskit Functions catalog) that accepts a higher-level problem description as input – e.g. ”find the ground-state energy of this molecule” or ”solve this optimization problem” – and internally handles the entire pipeline (circuit construc- tion, transpilation, primitive calls, classical pre/post-processing, and often proprietary error-mitigation or algorithm- improvement techniques) needed to produce a result, without the calling user needing to manually implement or manage every one of those steps themselves. This reflects a broader shift in the Qiskit ecosystem toward quantum- centric supercomputing workflows – treating quantum execution as one specialized, callable component orches- trated within a larger, more automated classical-quantum pipeline, rather than requiring every user to hand-build the full circuit-to-result pipeline from scratch for every new problem.
Q5.4 What is a ”fake backend” (e.g. FakeManilaV2) in Qiskit’s testing ecosystem, and why is it valuable for local development before ever submitting a job to real, queued hardware?
What is a ”fake backend” (e.g. FakeManilaV2) in Qiskit’s testing ecosystem, and why is it valuable for local development before ever submitting a job to real, queued hardware?

Source page 12

Qiskit Reference Deck 5 A fake backend is a locally-runnable simulator configured with the exact Target, coupling map, and (optionally) a realistic noise model snapshot captured from an actual, real IBM Quantum device at a specific point in time – letting you transpile and run circuits against a faithful, hardware-realistic simulation entirely locally, with no network access, no queue wait, and no cost. This is valuable for developing and validating an entire algorithm pipeline end-to-end (including transpilation targeting the real device’s specific basis gates and connectivity, and observing plausible, realistic noise-degraded results) before ever submitting to the real, queued device – catching transpilation errors, layout issues, or basic algorithmic bugs cheaply and instantly, reserving actual hardware time/queue slots for genuinely final validation runs.

Source page 13

Qiskit Reference Deck 6 Qiskit Aer & Simulation Qiskit Aer & Simulation

Q6.1 What is qiskit-aer, and why was it split out of the core qiskit package into its own separately-installed, separately-versioned project?
qiskit-aer is Qiskit’s high-performance simulation package, providing AerSimulator and related backends im- plemented in optimized C++ for substantially better simulation performance than the pure-Python reference imple- mentations bundled in core Qiskit. It was split into its own package (installed via pip install qiskit-aer) as part of the broader Qiskit 1.0 restructuring specifically so it could be developed, versioned, and released indepen- dently of the core SDK’s own release cadence – letting simulator-specific improvements (new simulation methods, GPU support, performance optimizations) ship on their own timeline without being coupled to, or blocked by, core Qiskit’s separate release schedule, and vice versa.
Q6.2 What is the difference between AerSimulator’s statevector, density_matrix, and matrix_product_state simulation methods, and what specific trade-off does each repre- sent?
Statevector simulation tracks a pure quantum state’s full 2n complex amplitude vector directly – exact and con- ceptually simplest, but memory usage grows exponentially with qubit count, typically capping practical simulation around 30-ish qubits on a single machine. Density-matrix simulation tracks the full 2n × 2n density matrix instead, needed specifically to correctly simulate mixed states arising from noise models – but its memory cost is the square of the statevector method’s, roughly halving the practically simulable qubit count for a given amount of memory. Matrix product state (MPS) simulation instead represents the state in a compressed tensor-network form that can, for circuits with limited entanglement between distant qubits, simulate substantially more qubits than statevector methods allow – at the cost of an approximation whose accuracy and efficiency both degrade for circuits generat- ing large amounts of long-range entanglement, where the compressed MPS representation stops being an efficient approximation at all.
Q6.3 How do you attach a realistic NoiseModel to AerSimulator, and why is simulating with noise essential before assuming an algorithm will actually work on real, imperfect hard- ware?
A NoiseModel specifies error probabilities/channels (depolarizing error, thermal relaxation, readout error) to ap- ply to specific gates and/or qubits during simulation – either built manually, or, much more commonly in practice, extracted directly from a real backend’s live calibration data via NoiseModel.from_backend(real_backend), producing a simulation whose noise characteristics closely mirror an actual device at the moment the calibration snapshot was taken. This matters because an algorithm that works perfectly on a noise-free statevector simulation can behave very differently – or fail outright – once realistic gate errors, decoherence, and readout errors are in- troduced, since many algorithms’ accuracy degrades with circuit depth in ways only visible under a realistic noise model; testing against a noise-modeled Aer simulation is a standard, essential intermediate validation step between pure ideal-simulator development and actual hardware submission. from qiskit_aer import AerSimulator from qiskit_aer.noise import NoiseModel noise_model = NoiseModel.from_backend(real_backend) noisy_sim = AerSimulator(noise_model=noise_model)

Source page 14

Qiskit Reference Deck 6

Q6.4 What is the difference between running a circuit through AerSimulator for a full shot-based sampling simulation versus computing an exact Statevector directly via qiskit.quantum_info?
AerSimulator (used via the run() method, or wrapped inside a local primitive) simulates the cir- cuit by executing it repeatedly for a specified number of shots, producing measurement-outcome statis- tics that mimic what a real quantum computer’s repeated runs would produce – appropriate whenever the goal is to realistically emulate the actual sampling process, including any attached noise model. quantum_info.Statevector.from_instruction(circuit) instead directly and exactly computes the circuit’s final quantum state vector via linear algebra, with no sampling/shot noise at all – appropriate for algorithm devel- opment, debugging, and verification purposes where you want to inspect the mathematically exact resulting state (amplitudes, exact probabilities) rather than emulate the statistical sampling process a real measurement or shot- based simulation would introduce.

Source page 15

Qiskit Reference Deck 7 Quantum Info & Operators Quantum Info & Operators

Q7.1 What is SparsePauliOp, and why has it become the standard way to represent observ- ables/Hamiltonians in current Qiskit, particularly as input to EstimatorV2?
SparsePauliOp represents an operator as a weighted sum of Pauli strings (e.g. 0.5 IIZZ −0.3 XXII), storing only the non-zero Pauli terms rather than a full, dense 2n × 2n matrix – since most physically relevant Hamiltonians (molecular electronic structure Hamiltonians, Ising-model cost functions for QAOA) are naturally expressed as a modest-sized sum of Pauli terms, this sparse representation is both far more memory-efficient and the natural, direct input format EstimatorV2 expects for its observable argument. It also supports natural, efficient arithmetic (addition, scalar multiplication, tensor products) directly on the Pauli-sum representation, without ever needing to materialize a full dense matrix at all for typical use. from qiskit.quantum_info import SparsePauliOp H = SparsePauliOp(["ZZ", "XI", "IX"], coeffs=[1.0, 0.5, 0.5])
Q7.2 What is the qiskit.quantum_info module, and how does its combination with the primi- tives interface fully supersede the deprecated qiskit.opflow module?
quantum_info provides foundational data structures and algebra for quantum states and operators – Statevector, DensityMatrix, Operator, SparsePauliOp, and utilities for computing fidelities, partial traces, and other stan- dard quantum-information quantities – all built on plain, direct linear-algebra representations rather than opflow’s older, more abstract, and comparatively awkward expression-tree-based operator algebra. Combined with the primi- tives interface (which directly accepts quantum_info objects like SparsePauliOp as observables), this combination provides everything opflow used to offer – but expressed through simpler, more directly-inspectable data structures – which is precisely why opflow was deprecated and eventually removed: its functionality was fully absorbed and re-expressed through quantum_info plus primitives, without needing opflow’s separate, additional abstraction layer at all.
Q7.3 What is the Operator class, and how does it differ from SparsePauliOp in terms of what it represents and its typical use cases?
Operator represents a general unitary (or arbitrary linear) operator as an explicit, dense matrix – directly us- able for exact matrix-level manipulation, composition, and comparison of arbitrary operators (verifying two differ- ent circuit constructions implement the identical unitary, for instance, via Operator(qc1) == Operator(qc2)). SparsePauliOp, in contrast, specifically represents an operator as a sparse sum of Pauli terms, suited to representing Hamiltonians/observables to be measured rather than general arbitrary unitaries applied within a circuit. In practice, Operator is most useful for small-to-moderate circuits (dense matrices again suffer the same exponential memory blowup as statevector simulation) during verification, debugging, and unit-testing that a circuit implements its in- tended unitary transformation exactly, while SparsePauliOp is the standard choice specifically for the observable side of expectation-value calculations.
Q7.4 How do you compute the fidelity between two quantum states using quantum_info, and why is state fidelity a standard way to quantify how close an experimentally-obtained (possibly
How do you compute the fidelity between two quantum states using quantum_info, and why is state fidelity a standard way to quantify how close an experimentally-obtained (possibly

Source page 16

Qiskit Reference Deck 7 noisy) state is to some ideal target state? quantum_info.state_fidelity(state1, state2) computes the standard fidelity measure between two quan- tum states (pure or mixed, given as Statevector or DensityMatrix objects) – a value of 1 indicating the two states are identical, and 0 indicating they are perfectly distinguishable/orthogonal. This is the standard tool for quantifying, in a single interpretable number, how successfully a real (noisy) experimental run, or a noisy simulation, actually prepared some intended target state – e.g. verifying that a hardware-executed Bell-state preparation circuit produced a final state with high fidelity relative to the mathematically ideal Bell state, providing a concrete, quantitative bench- mark of an implementation’s or a device’s actual state-preparation quality. from qiskit.quantum_info import Statevector , state_fidelity ideal = Statevector.from_instruction(qc) fidelity = state_fidelity(ideal, experimentally_reconstructed_state)

Source page 17

Qiskit Reference Deck 8 Advanced Features Advanced Features

Q8.1 What are ”dynamic circuits,” and what specific new capability (beyond simple, pre-planned classical conditions) do mid-circuit measurement combined with real-time classical control flow unlock?
Dynamic circuits interleave quantum operations with classical computation and control flow during circuit execution – most importantly, allowing a mid-circuit measurement’s result to be read out and used, in real time within the same circuit execution, to decide which quantum operation happens next (via if_test, while_loop, or general classical-expression-based conditions), all before the circuit fully completes and without needing a separate, later circuit submission. This directly enables important techniques impossible with a purely ”measure only at the very end” circuit model – most notably, quantum error correction itself (which fundamentally requires repeated mid- circuit syndrome measurements that condition subsequent real-time correction operations), as well as measurement- based quantum computation and certain circuit-depth-reducing techniques that substitute mid-circuit measurement and classical feedforward for what would otherwise require additional entangling gates.
Q8.2 What is a custom TranspilerPass, and when would a Qiskit developer need to write one rather than simply relying on the built-in preset pass managers?
A TranspilerPass is a single, focused transformation or analysis step applied to a circuit’s internal DAG (directed acyclic graph) representation during transpilation – Qiskit’s preset pass managers (Section 3) are themselves just pre-configured pipelines chaining together many such built-in passes. A developer needs to write a custom pass specifically when a project requires transpilation logic the built-in passes don’t already provide – e.g. a specialized gate-decomposition rule specific to a particular experimental or novel hardware platform, a custom noise-aware qubit- layout heuristic tailored to a specific device’s unusual error characteristics, or a project-specific circuit optimization rule exploiting domain knowledge the general-purpose preset passes have no way to know about – and can then insert that custom pass into a PassManager alongside (or in place of) Qiskit’s standard built-in passes.
Q8.3 What visualization tools does Qiskit provide for inspecting circuits and results, and what does each (draw(), plot_histogram(), plot_state_city()) specifically show?
QuantumCircuit.draw() renders the circuit itself as a diagram (text, matplotlib, or LaTeX output) – essential for visually verifying a circuit’s structure matches what was intended, especially after transpilation has poten- tially rearranged and relabeled qubits. qiskit.visualization.plot_histogram() plots measurement-outcome counts/probabilities as a bar chart – the standard way to visually inspect a Sampler result’s output distribution. plot_state_city() (and related state-visualization functions like plot_bloch_multivector()) visualize a quantum state’s amplitudes or single-qubit Bloch-sphere representations directly – useful during development and debugging for building direct visual intuition about a small circuit’s actual resulting quantum state, in a way that raw printed numbers alone don’t as easily convey. qc.draw("mpl") # circuit diagram from qiskit.visualization import plot_histogram plot_histogram(sampler_result[0].data.meas.get_counts())

Source page 18

Qiskit Reference Deck 8

Q8.4 What is meant by ”quantum-centric supercomputing,” and how does it frame Qiskit’s on- going development direction (Qiskit Patterns, Qiskit Functions, tighter classical-HPC inte- gration) as distinct from viewing a quantum computer as a simple, standalone accelerator?
Quantum-centric supercomputing frames a quantum processor not as an isolated, standalone device you submit one job to and wait for a result from, but as one specialized component tightly integrated within a larger, heterogeneous classical high-performance-computing (HPC) workflow – with classical CPUs/GPUs handling pre-processing, tran- spilation, error mitigation post-processing, and classical optimization loops, while the quantum processor is invoked repeatedly, efficiently, and with low latency as needed within that larger pipeline. Qiskit Patterns (a structured four- step workflow: map a problem to circuits/operators, optimize/transpile for the target hardware, execute via primitives, and classically post-process results) and Qiskit Functions (Section 5) are both concrete expressions of this philos- ophy – reflecting Qiskit’s current development direction as building the software infrastructure specifically for this tightly-coupled, quantum-plus-classical-HPC execution model, rather than treating quantum hardware as a simple, isolated, occasionally-useful standalone accelerator called only occasionally and independently of any larger classical computation. End of deck. Qiskit evolves quickly – always cross-check against the current release notes at quantum.cloud.ibm.com/docs.