Skip to content
Kartikey Purohit
← Course overview

Sample Papers

Paper 4

Fundamentals of Quantum Computing Using Qiskit v2.X Developer Flavor: quantum_info operators (little-endian traps) and dynamic circuits.

Questions 34 (half-length paper; real exam is 68)
Time limit 45 minutes (~79 seconds/question)
Passing target 24 / 34 ≈ 69% (mirrors the real 47/68 threshold)
Answer format Single best answer A–D unless a question says "Choose TWO"

Instructions

  1. Assume qiskit 2.x, qiskit-ibm-runtime (V2 primitives), and qiskit-aer are installed; all imports shown are the only ones needed.
  2. Qiskit's little-endian convention applies everywhere: qubit 0 is the rightmost character in bitstrings, Pauli strings, and statevector labels.
  3. Numerical outputs are exact up to floating-point rounding; pick the closest option.
  4. No notes, no interpreter. Time yourself. Answers are in paper-04-answers.md.

Section 1 — Create Quantum Circuits (Q1–Q6)

Q1. Which counts dictionary does this code print?

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
 
qc = QuantumCircuit(2, 2)
qc.x(0)
qc.measure(0, 0)
with qc.if_test((qc.clbits[0], 1)):
    qc.x(1)
qc.measure(1, 1)
counts = AerSimulator().run(qc, shots=100).result().get_counts()
print(counts)
  • A. {'11': 100}
  • B. {'01': 100}
  • C. {'10': 100}
  • D. Roughly {'01': 50, '11': 50}

Q2. Which counts dictionary does this code print?

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
 
qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0)
with qc.if_test((qc.clbits[0], 0)) as else_:
    qc.x(0)
with else_:
    qc.z(0)
qc.measure(0, 0)
counts = AerSimulator().run(qc, shots=100).result().get_counts()
print(counts)
  • A. {'1': 100}
  • B. {'0': 100}
  • C. Roughly {'0': 50, '1': 50}
  • D. It raises an error — a clbit cannot be measured twice

Q3. Which of the following is NOT a control-flow builder available on QuantumCircuit for dynamic circuits?

  • A. if_test
  • B. while_loop
  • C. switch
  • D. goto

Q4. What does this code print?

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
 
a = Parameter('a')
b = Parameter('b')
qc = QuantumCircuit(1)
qc.ry(b, 0)
qc.rz(a, 0)
print([p.name for p in qc.parameters])
  • A. ['a', 'b']
  • B. ['b', 'a']
  • C. ['rz', 'ry']
  • D. The order is undefined and changes run to run

Q5. You built a 1-qubit sub-circuit sub and want a controlled version of it appended to a 2-qubit circuit qc, with qubit 0 as control and qubit 1 as target. Which snippet is correct?

  • A.
    gate = sub.to_gate()
    qc.append(gate.control(1), [0, 1])
  • B. qc.append(sub.controlled(), [0, 1])
  • C. qc.control(sub, 0, 1)
  • D. qc.append(sub.to_gate(control=0), [1])

Q6. Which probability dictionary does this code print?

from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
 
a = QuantumCircuit(1)
a.x(0)
b = QuantumCircuit(1)   # stays |0>
qc = a.tensor(b)
print(Statevector.from_instruction(qc).probabilities_dict())
  • A. {'01': 1.0}
  • B. {'10': 1.0}
  • C. {'00': 1.0}
  • D. {'11': 1.0}

Section 2 — Perform Quantum Operations (Q7–Q12)

Q7. What does this code print?

from qiskit.quantum_info import Statevector, Pauli
 
sv = Statevector.from_label('10')
print(sv.expectation_value(Pauli('IZ')).real)
  • A. 1.0
  • B. -1.0
  • C. 0.0
  • D. It raises an error — labels and Paulis have different lengths

Q8. What does this code print?

from qiskit.quantum_info import Pauli
 
print(Pauli('Z').tensor(Pauli('X')).to_label())
  • A. XZ
  • B. ZX
  • C. -iY
  • D. Y

Q9. What does this code print?

from qiskit.quantum_info import SparsePauliOp
 
op = SparsePauliOp.from_sparse_list([('ZZ', [0, 3], 1.0)], num_qubits=4)
print(op.paulis[0])
  • A. ZIIZ
  • B. ZZII
  • C. IZZI
  • D. It raises an error — the Pauli string must have length 4

Q10. You want the expectation value of Z on qubit 2 of a 3-qubit circuit (identity on the others). Which observable is correct?

  • A. SparsePauliOp('IIZ')
  • B. SparsePauliOp('ZII')
  • C. SparsePauliOp('IZI')
  • D. SparsePauliOp('Z') — the qubit index is passed at run time

Q11. Which probability dictionary does this code print (up to float rounding)?

from qiskit import QuantumCircuit
from qiskit.quantum_info import DensityMatrix, partial_trace
 
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
rho = partial_trace(DensityMatrix.from_instruction(qc), [1])
print(rho.probabilities_dict())
  • A. {'0': 1.0}
  • B. {'0': 0.5, '1': 0.5}
  • C. {'00': 0.5, '11': 0.5}
  • D. It raises an error — a density matrix has no probabilities

Q12. (Choose TWO) Which statements about Pauli operators and rotations are TRUE?

  • A. X and Z anticommute: XZ = −ZX
  • B. rz(π) is equivalent to the Z gate up to a global phase
  • C. X and Z commute: XZ = ZX
  • D. Y = XZ exactly, with no extra phase factor

Section 3 — Run Quantum Circuits (Q13–Q17)

Q13. Which snippet selects the least busy real (non-simulator), operational IBM backend?

  • A. backend = service.least_busy(operational=True, simulator=False)
  • B. backend = service.backends(busy=False)[0]
  • C. backend = least_busy(service.backends())
  • D. backend = service.backend("least_busy")

Q14. What does this code print?

from qiskit_ibm_runtime.fake_provider import FakeManilaV2
 
backend = FakeManilaV2()
print(backend.num_qubits)
  • A. 2
  • B. 5
  • C. 27
  • D. 127

Q15. Which snippet runs a single standalone Sampler job (job mode) on backend?

  • A. sampler = SamplerV2(mode=backend)
  • B. sampler = SamplerV2(mode="job")
  • C. sampler = SamplerV2(session=backend)
  • D. backend.run(qc, shots=1024)

Q16. Which statement about running dynamic circuits (mid-circuit measurement + if_test feedforward) on IBM hardware is TRUE?

  • A. Dynamic circuits skip transpilation because control flow cannot be optimized
  • B. They must still be transpiled to the backend ISA before being passed to a V2 primitive
  • C. Only simulators can execute if_test
  • D. They require V1 primitives, since V2 rejects classical feedforward

Q17. What does this code print?

from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler
 
qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0)
res = StatevectorSampler().run([(qc, None, 128)], shots=512).result()
print(res[0].data.c.num_shots)
  • A. 512
  • B. 128
  • C. 640
  • D. It raises an error — shots can only be set once

Section 4 — Use the Sampler Primitive (Q18–Q21)

Q18. What does this code print?

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.primitives import StatevectorSampler
 
q = QuantumRegister(2, 'q')
c1 = ClassicalRegister(1, 'alpha')
c2 = ClassicalRegister(1, 'beta')
qc = QuantumCircuit(q, c1, c2)
qc.x(0)
qc.measure(0, c1[0])
qc.measure(1, c2[0])
res = StatevectorSampler().run([qc], shots=50).result()
print(res[0].data.alpha.get_counts())
  • A. {'1': 50}
  • B. {'0': 50}
  • C. {'01': 50}
  • D. It raises an AttributeError — multi-register data must be read with join_data()

Q19. In a V2 Sampler result with several classical registers, what does result[0].join_data() do?

  • A. Concatenates the per-register BitArrays into a single combined BitArray
  • B. Merges the results of several PUBs into one
  • C. Downloads any data still pending on the server
  • D. Averages the counts across shots

Q20. What does this code print?

from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler
 
qc = QuantumCircuit(3)
qc.x(2)
qc.measure_all()
res = StatevectorSampler().run([qc], shots=10).result()
ba = res[0].data.meas
print(ba.num_bits, ba.get_bitstrings()[0])
  • A. 3 001
  • B. 3 100
  • C. 8 100
  • D. 3 010

Q21. Which snippet enables measurement twirling on a SamplerV2 instance?

  • A. sampler.options.twirling.enable_measure = True
  • B. sampler.options.resilience.measure_mitigation = True
  • C. sampler.options.twirling = "measure"
  • D. sampler.options.dynamical_decoupling.enable = True

Section 5 — Use the Estimator Primitive (Q22–Q25)

Q22. What does this code print?

import numpy as np
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.primitives import StatevectorEstimator
from qiskit.quantum_info import SparsePauliOp
 
theta = Parameter('t')
qc = QuantumCircuit(1)
qc.ry(theta, 0)
obs = SparsePauliOp('Z')
res = StatevectorEstimator().run([(qc, obs, [[0.0], [np.pi]])]).result()
print(res[0].data.evs.round(2))
  • A. [ 1. -1.]
  • B. [-1. 1.]
  • C. [1. 1.]
  • D. [0. 0.]

Q23. What does this code print?

from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorEstimator
from qiskit.quantum_info import SparsePauliOp
 
qc = QuantumCircuit(2)
qc.x(0)
obs = [SparsePauliOp('IZ'), SparsePauliOp('ZI')]
res = StatevectorEstimator().run([(qc, obs)]).result()
print(res[0].data.evs.round(2))
  • A. [-1. 1.]
  • B. [ 1. -1.]
  • C. [-1. -1.]
  • D. [1. 1.]

Q24. For hardware execution you compute isa = pm.run(qc). Which PUB is correct for EstimatorV2?

  • A. (isa, obs.apply_layout(isa.layout))
  • B. (qc, obs) — the Estimator transpiles internally
  • C. (isa, obs) — layout mapping is automatic for observables
  • D. (obs.apply_layout(isa.layout), isa)

Q25. Which statement about circuits passed to EstimatorV2 is TRUE?

  • A. They must end in measure_all() so the Estimator has bits to average
  • B. They must contain no measurements — the observable defines what is measured
  • C. Measurements are allowed but ignored
  • D. Only mid-circuit measurements are allowed

Section 6 — Visualize Circuits, Measurements, and States (Q26–Q29)

Q26. Which diagram does qc.draw('text') produce for this circuit?

from qiskit import QuantumCircuit
 
qc = QuantumCircuit(2)
qc.x(0)
  • A.
         ┌───┐
    q_0: ┤ X ├
         └───┘
    q_1: ─────
  • B.
    q_0: ─────
         ┌───┐
    q_1: ┤ X ├
         └───┘
  • C.
         ┌───┐
    q_0: ┤ X ├
         ├───┤
    q_1: ┤ X ├
         └───┘
  • D. It depends on the reverse_bits default, which varies by version

Q27. On the Bloch sphere, where does the state |−i⟩ = (|0⟩ − i|1⟩)/√2 point?

  • A. +Y
  • B. −Y
  • C. −X
  • D. −Z

Q28. Which snippet shows one Bloch sphere per qubit for the state produced by circuit qc (no measurements)?

  • A. plot_bloch_multivector(Statevector.from_instruction(qc))
  • B. plot_bloch_vector(qc)
  • C. plot_state_qsphere(qc.draw())
  • D. qc.draw('bloch')

Q29. A 3-qubit GHZ circuit is sampled 1,000 times on an ideal simulator and the counts are plotted with plot_histogram. What is the expected signature?

  • A. Eight bars of roughly equal height
  • B. Two bars, 000 and 111, each near 500
  • C. One bar at 000
  • D. Two bars, 001 and 110, each near 500

Section 7 — Retrieve and Analyze Results (Q30–Q32)

Q30. Which call checks whether an asynchronous Runtime job has finished, without blocking until completion?

  • A. job.result()
  • B. job.done()
  • C. job.wait()
  • D. job.metrics()

Q31. Hardware counts for a 3-qubit circuit are {'000': 400, '111': 600} over 1,000 shots. What is the estimated expectation value of Z on qubit 2 (i.e., ⟨Z⊗I⊗I⟩)?

  • A. -0.2
  • B. 0.2
  • C. -1.0
  • D. 0.6

Q32. What does job.usage() report for a Qiskit Runtime job?

  • A. The quantum (QPU) time consumed by the job, in seconds
  • B. The number of shots executed
  • C. The memory used by the result payload
  • D. The number of PUBs in the job

Section 8 — Operate with OpenQASM (Q33–Q34)

Q33. You export this dynamic circuit with qiskit.qasm3.dumps(qc):

from qiskit import QuantumCircuit
 
qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0)
with qc.if_test((qc.clbits[0], 1)):
    qc.x(0)

Which line appears in the exported OpenQASM 3 program?

  • A. if (c[0]) {
  • B. if c == 1:
  • C. c[0] ? x q[0];
  • D. Nothing — dumps raises an error because OpenQASM 3 cannot represent if_test

Q34. What does this code print?

from qiskit import qasm2
 
prog = 'OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; creg c[2]; ' \
       'h q[0]; cx q[0],q[1]; measure q -> c;'
qc = qasm2.loads(prog)
print(qc.num_qubits, qc.count_ops()['measure'])
  • A. 2 2
  • B. 2 1
  • C. It raises an error — OpenQASM 2 import was removed in Qiskit 2.x
  • D. 4 4

End of Paper 04. Check your work in paper-04-answers.md.