Skip to content
Kartikey Purohit
← Course overview

Sample Papers

Paper 8

Exam: Fundamentals of Quantum Computing Using Qiskit v2.X Developer Time limit: 45 minutes | Questions: 34 | Passing target: 24/34 (~69%) Difficulty flavor: Balanced, exam-realistic. Slight emphasis on job/result retrieval and error suppression vs mitigation.

Instructions

  • Single best answer (A–D) unless the question explicitly says "choose TWO".
  • All code assumes Qiskit v2.x, qiskit-ibm-runtime 0.4x, and standard imports unless shown.
  • Qiskit is little-endian: qubit 0 is the rightmost character in bitstrings, Pauli strings, and statevector labels.
  • No notes, no interpreter. Mark and move on if stuck — ~79 seconds per question.

Section 1 — Create Quantum Circuits (Q1–Q6)

Q1. What does this print?

from qiskit import QuantumCircuit
 
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
print(qc.size(), qc.depth())
  • A. 4 4
  • B. 4 3
  • C. 3 3
  • D. 5 4

Q2. Which snippet prepares the Bell state (|01⟩ + |10⟩)/√2 from |00⟩?

  • A.
    qc.h(0); qc.cx(0, 1)
  • B.
    qc.h(0); qc.h(1)
  • C.
    qc.x(0); qc.x(1); qc.cx(0, 1)
  • D.
    qc.x(1); qc.h(0); qc.cx(0, 1)

Q3. What does this print?

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
 
theta = Parameter('θ')
qc = QuantumCircuit(1)
qc.ry(theta, 0)
out = qc.assign_parameters({theta: 3.14}, inplace=True)
print(out)
  • A. None
  • B. The bound circuit's repr
  • C. It raises an error — inplace is not a valid argument
  • D. The original unbound circuit's repr

Q4. Which is the recommended Qiskit v2.x way to make a circuit executable on a specific backend?

  • A. isa_qc = transpile(qc) — no backend argument is needed
  • B. backend.run(qc) — the backend transpiles internally
  • C.
    pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
    isa_qc = pm.run(qc)
  • D. isa_qc = qc.transpile(backend)

Q5. What does this print?

from qiskit import QuantumCircuit
 
qc = QuantumCircuit(1)
qc.s(0)
qc.t(0)
inv = qc.inverse()
print([instr.operation.name for instr in inv.data])
  • A. ['sdg', 'tdg']
  • B. ['t', 's']
  • C. ['s', 't']
  • D. ['tdg', 'sdg']

Q6. Which sequence lists the preset transpiler pipeline stages in the correct order?

  • A. layout → init → translation → routing → optimization → scheduling
  • B. init → layout → routing → translation → optimization → scheduling
  • C. init → translation → layout → optimization → routing → scheduling
  • D. translation → layout → routing → scheduling → optimization → init

Section 2 — Perform Quantum Operations (Q7–Q12)

Q7. What are the two expectation values (rounded)?

from qiskit.quantum_info import Pauli, Statevector
 
sv = Statevector.from_label('+')
print(sv.expectation_value(Pauli('X')), sv.expectation_value(Pauli('Z')))
  • A. 1.0 and 0.0
  • B. 0.0 and 1.0
  • C. 1.0 and 1.0
  • D. 0.5 and 0.5

Q8. What does this print?

from qiskit.quantum_info import SparsePauliOp
 
a = SparsePauliOp('X')
b = SparsePauliOp('Z')
print(a.tensor(b).paulis)
  • A. ['ZX']
  • B. ['XZ', 'ZX']
  • C. ['XZ']
  • D. It raises an error — single-qubit operators cannot be tensored

Q9. Which of these two-qubit states is a product state (i.e. NOT entangled)?

  • A. (|00⟩ + |11⟩)/√2
  • B. (|00⟩ + |01⟩)/√2
  • C. (|01⟩ + |10⟩)/√2
  • D. (|00⟩ − |11⟩)/√2

Q10. What does this print?

from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
 
qc = QuantumCircuit(1)
qc.h(0)
qc.s(0)
sv = Statevector.from_label('0').evolve(qc)
print(sv.probabilities_dict())
  • A. {'0': 1.0}
  • B. {'1': 1.0}
  • C. {'0': 0.85, '1': 0.15}
  • D. {'0': 0.5, '1': 0.5}

Q11. Applying the t gate twice in a row is equivalent to which single gate?

  • A. s
  • B. z
  • C. tdg
  • D. The identity

Q12. What does this print?

from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, state_fidelity
 
qc = QuantumCircuit(1)
qc.x(0)
qc.h(0)
print(round(state_fidelity(Statevector(qc), Statevector.from_label('-')), 3))
  • A. 0.0
  • B. 0.5
  • C. 1.0
  • D. 0.707

Section 3 — Run Quantum Circuits (Q13–Q17)

Q13. You must run 25 independent characterization circuits — no circuit depends on another's results — and want them scheduled efficiently together. Which execution mode is the best fit?

  • A. Job mode, submitting them one at a time
  • B. Batch mode
  • C. Session mode — you always get the fastest total turnaround
  • D. They must be merged into a single circuit first

Q14. Which snippet stores your IBM Quantum account credentials on disk for later QiskitRuntimeService() calls?

  • A. QiskitRuntimeService.save_account(channel="ibm_quantum_platform", token=token)
  • B. QiskitRuntimeService(api_key=token).persist()
  • C. Session.save_account(token)
  • D. service.backend.save(token)

Q15. What makes a circuit an ISA circuit for a given backend?

  • A. It has been exported to OpenQASM 3
  • B. It contains at least one measurement on every qubit
  • C. It was created with optimization_level=3
  • D. It uses only the backend's supported basis gates and respects its qubit connectivity

Q16. You have no IBM Quantum account available and want to test your exact SamplerV2-style workflow (PUBs, result[0].data...) locally and noise-free. Which class do you use?

  • A. qiskit_ibm_runtime.SamplerV2 with mode=None
  • B. qiskit.execute with a local flag
  • C. qiskit.primitives.StatevectorSampler
  • D. AerSimulator.run() — it returns PUB results

Q17. How many shots run for each of the two PUBs?

sampler.options.default_shots = 1024
job = sampler.run([(isa_a,), (isa_b,)], shots=2048)
  • A. 1024 for both — options always win
  • B. 2048 for both — the run-level value overrides default_shots
  • C. 1024 for the first, 2048 for the second
  • D. It raises an error — shots cannot be passed to run()

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

Q18. What does this print?

from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler
 
qc = QuantumCircuit(2)
qc.x(1)
qc.measure_all()
result = StatevectorSampler().run([qc], shots=500).result()
print(result[0].data.meas.get_counts())
  • A. {'01': 500}
  • B. {'11': 500}
  • C. {'10': 500}
  • D. {'01': 250, '10': 250}

Q19. A 3-qubit circuit with measure_all() is run with shots=256. What does this print?

ba = result[0].data.meas
print(ba.num_bits, ba.num_shots)
  • A. 3 256
  • B. 256 3
  • C. 3 3
  • D. 8 256

Q20. Which line enables dynamical decoupling on a SamplerV2 instance?

  • A. sampler.options.resilience_level = 1
  • B. sampler.options.zne_mitigation = True
  • C. sampler.options.dynamical_decoupling = True
  • D. sampler.options.dynamical_decoupling.enable = True

Q21. A colleague runs StatevectorSampler on a Bell-state circuit that has no measurement instructions. What happens?

  • A. The sampler measures all qubits automatically in the Z basis
  • B. A hard exception is always raised before the job runs
  • C. The job completes, but the PUB's data is empty (a warning notes the missing measurements)
  • D. It returns the exact statevector amplitudes instead of samples

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

Q22. What does this print?

from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import StatevectorEstimator
 
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
obs = [SparsePauliOp('ZZ'), SparsePauliOp('XX'), SparsePauliOp('ZI')]
result = StatevectorEstimator().run([(qc, obs)]).result()
print(result[0].data.evs)
  • A. [1. 1. 0.]
  • B. [1. 0. 1.]
  • C. [0. 0. 1.]
  • D. [1. 1. 1.]

Q23. (choose TWO) Which two techniques are error mitigation (classical post-processing of results) rather than error suppression (applied before/during execution)?

  • A. Zero-noise extrapolation (ZNE)
  • B. Dynamical decoupling
  • C. TREX measurement-error mitigation
  • D. Pauli twirling

Q24. With no options set, what resilience_level does the Runtime EstimatorV2 use by default?

  • A. 0
  • B. 1
  • C. 2
  • D. 3

Q25. What does this print (rounded)?

import numpy as np
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import StatevectorEstimator
 
t = Parameter('t')
qc = QuantumCircuit(1)
qc.ry(t, 0)
pub = (qc, SparsePauliOp('Z'), [[0], [np.pi / 2], [np.pi]])
result = StatevectorEstimator().run([pub]).result()
print(np.round(result[0].data.evs, 3))
  • A. [-1. 0. 1.]
  • B. [1. 1. 1.]
  • C. It raises an error — one observable cannot broadcast over three parameter sets
  • D. [ 1. 0. -1.]

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

Q26. Which code produced this text drawing?

     ┌───┐
q_0: ┤ H ├──■──
     └───┘┌─┴─┐
q_1: ─────┤ X ├
          └───┘
  • A. qc.h(0); qc.cx(0, 1)
  • B. qc.h(1); qc.cx(1, 0)
  • C. qc.h(0); qc.cx(1, 0)
  • D. qc.h(1); qc.cx(0, 1)

Q27. Starting from |0⟩, a circuit applies x then h. Where does the qubit's Bloch vector point?

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

Q28. You call plot_histogram(counts, number_to_keep=2) on counts with six distinct bitstrings. What is drawn?

  • A. Only the first 2 shots of the experiment
  • B. Nothing — it raises an error when there are more than 2 outcomes
  • C. The 2 most frequent bitstrings as bars, with all others aggregated into a "rest" bar
  • D. All six bars, with bitstrings truncated to their 2 rightmost bits

Q29. You have ideal_counts from a noise-free simulator and hw_counts from real hardware and want to compare them in a single plot. Which call does it?

  • A. It is impossible — each counts dict needs its own figure
  • B. plot_bloch_multivector([ideal_counts, hw_counts])
  • C. plot_state_city(ideal_counts, hw_counts)
  • D. plot_histogram([ideal_counts, hw_counts], legend=['ideal', 'hardware'])

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

Q30. Your Runtime job finished overnight. Which call tells you how much QPU time the job consumed?

  • A. job.usage()
  • B. job.qpu_time()
  • C. backend.usage(job)
  • D. job.result().usage

Q31. A 2-qubit Sampler run gives {'00': 420, '01': 80, '10': 80, '11': 420} over 1000 shots. What is the estimated ⟨ZZ⟩?

  • A. 0.84
  • B. 0.68
  • C. −0.68
  • D. 1.0

Q32. After restarting your Python kernel you no longer have any job objects, and you don't remember the job IDs. Which call lists your three most recent Runtime jobs?

  • A. You cannot — job handles are lost when the kernel restarts
  • B. SamplerV2.jobs(limit=3)
  • C. backend.jobs(limit=3)
  • D. service.jobs(limit=3)

Section 8 — Operate with OpenQASM (Q33–Q34)

Q33. This OpenQASM 2 program is imported with qiskit.qasm2.loads and run for 1000 shots. What (approximately) are the counts?

OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
x q[1];
h q[0];
measure q -> c;
  • A. {'01': ~500, '11': ~500}
  • B. {'10': ~500, '11': ~500}
  • C. {'11': 1000}
  • D. {'00': ~500, '10': ~500}

Q34. Which capability exists in OpenQASM 3 but not in OpenQASM 2?

  • A. Defining custom composite gates
  • B. Barriers
  • C. Typed classical variables and input parameters
  • D. Including a standard gate library

End of Paper 08. Check your work against paper-08-answers.md.