Skip to content

Commit fb0f0b8

Browse files
committed
Merge remote-tracking branch 'origin/main' into partial-layout-interface
2 parents 89fa2ab + 3bd1d46 commit fb0f0b8

File tree

3 files changed

+29
-6
lines changed

3 files changed

+29
-6
lines changed

qiskit/primitives/base/base_sampler.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
from copy import copy
8181
from typing import Generic, TypeVar
8282

83-
from qiskit.circuit import QuantumCircuit
83+
from qiskit.circuit import ControlFlowOp, Measure, QuantumCircuit
8484
from qiskit.circuit.parametertable import ParameterView
8585
from qiskit.providers import JobV1 as Job
8686

@@ -159,7 +159,6 @@ def _run(
159159
) -> T:
160160
raise NotImplementedError("The subclass of BaseSampler must implment `_run` method.")
161161

162-
# TODO: validate measurement gates are present
163162
@classmethod
164163
def _validate_circuits(
165164
cls,
@@ -173,6 +172,11 @@ def _validate_circuits(
173172
"Sampler requires classical bits, plus measurements "
174173
"on the desired qubits."
175174
)
175+
if not _has_measure(circuit):
176+
raise ValueError(
177+
f"The {i}-th circuit does not have Measure instruction. "
178+
"Without measurements, the circuit cannot be sampled from."
179+
)
176180
return circuits
177181

178182
@property
@@ -192,3 +196,14 @@ def parameters(self) -> tuple[ParameterView, ...]:
192196
List of the parameters in each quantum circuit.
193197
"""
194198
return tuple(self._parameters)
199+
200+
201+
def _has_measure(circuit: QuantumCircuit) -> bool:
202+
for instruction in reversed(circuit):
203+
if isinstance(instruction.operation, Measure):
204+
return True
205+
elif isinstance(instruction.operation, ControlFlowOp):
206+
for block in instruction.operation.blocks:
207+
if _has_measure(block):
208+
return True
209+
return False
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
Add early validation for :class:`.BaseSampler` when input :class:`.QuantumCircuit` does not
5+
have measurements.

test/python/primitives/test_sampler.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from qiskit import QuantumCircuit
2020
from qiskit.circuit import Parameter
2121
from qiskit.circuit.library import RealAmplitudes
22-
from qiskit.exceptions import QiskitError
2322
from qiskit.extensions.unitary import UnitaryGate
2423
from qiskit.primitives import Sampler, SamplerResult
2524
from qiskit.providers import JobStatus, JobV1
@@ -276,6 +275,9 @@ def test_run_errors(self):
276275
qc2.measure_all()
277276
qc3 = QuantumCircuit(1)
278277
qc4 = QuantumCircuit(1, 1)
278+
qc5 = QuantumCircuit(1, 1)
279+
with qc5.for_loop(range(5)):
280+
qc5.h(0)
279281

280282
sampler = Sampler()
281283
with self.subTest("set parameter values to a non-parameterized circuit"):
@@ -294,10 +296,11 @@ def test_run_errors(self):
294296
with self.assertRaises(ValueError):
295297
_ = sampler.run([qc3], [[]])
296298
with self.subTest("no measurement"):
297-
with self.assertRaises(QiskitError):
298-
# The following raises QiskitError because this check is located in
299-
# `Sampler._preprocess_circuit`
299+
with self.assertRaises(ValueError):
300300
_ = sampler.run([qc4], [[]])
301+
with self.subTest("no measurement in control flow"):
302+
with self.assertRaises(ValueError):
303+
_ = sampler.run([qc5], [[]])
301304

302305
def test_run_empty_parameter(self):
303306
"""Test for empty parameter"""

0 commit comments

Comments
 (0)