From e3cd5b3c97cce0423def8a8806196ca6f4a8aa03 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:14:15 +0200 Subject: [PATCH] Fix `StatevectorSampler` to raise an error if a circuit with c_if is passed (#12842) (#12851) * fix StatevectorSampler with c_if * add comment (cherry picked from commit 239a669ab72527f2b6aec62eb8f1886dd493f14f) Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com> --- qiskit/primitives/statevector_sampler.py | 7 +++-- ...evector-sampler-c_if-9753f8f97a3d0ff5.yaml | 5 ++++ .../primitives/test_statevector_sampler.py | 28 +++++++++++++------ 3 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 releasenotes/notes/fix-statevector-sampler-c_if-9753f8f97a3d0ff5.yaml diff --git a/qiskit/primitives/statevector_sampler.py b/qiskit/primitives/statevector_sampler.py index 7488faa284de..58980cb79f6e 100644 --- a/qiskit/primitives/statevector_sampler.py +++ b/qiskit/primitives/statevector_sampler.py @@ -207,7 +207,7 @@ def _preprocess_circuit(circuit: QuantumCircuit): qargs_index = {v: k for k, v in enumerate(qargs)} circuit = circuit.remove_final_measurements(inplace=False) if _has_control_flow(circuit): - raise QiskitError("StatevectorSampler cannot handle ControlFlowOp") + raise QiskitError("StatevectorSampler cannot handle ControlFlowOp and c_if") if _has_measure(circuit): raise QiskitError("StatevectorSampler cannot handle mid-circuit measurements") # num_qubits is used as sentinel to fill 0 in _samples_to_packed_array @@ -283,4 +283,7 @@ def _final_measurement_mapping(circuit: QuantumCircuit) -> dict[tuple[ClassicalR def _has_control_flow(circuit: QuantumCircuit) -> bool: - return any(isinstance(instruction.operation, ControlFlowOp) for instruction in circuit) + return any( + isinstance((op := instruction.operation), ControlFlowOp) or op.condition + for instruction in circuit + ) diff --git a/releasenotes/notes/fix-statevector-sampler-c_if-9753f8f97a3d0ff5.yaml b/releasenotes/notes/fix-statevector-sampler-c_if-9753f8f97a3d0ff5.yaml new file mode 100644 index 000000000000..d743b52ee900 --- /dev/null +++ b/releasenotes/notes/fix-statevector-sampler-c_if-9753f8f97a3d0ff5.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed a bug of :class:`.StatevectorSampler` that ignored gates with ``c_if``. + It will raise an error because :class:`.Statevector` cannot handle ``c_if``. diff --git a/test/python/primitives/test_statevector_sampler.py b/test/python/primitives/test_statevector_sampler.py index c065871025d7..1f84c072564d 100644 --- a/test/python/primitives/test_statevector_sampler.py +++ b/test/python/primitives/test_statevector_sampler.py @@ -280,6 +280,11 @@ def test_run_errors(self): qc3 = QuantumCircuit(1, 1) with qc3.for_loop(range(5)): qc3.h(0) + qc4 = QuantumCircuit(2, 2) + qc4.h(0) + qc4.measure(1, 1) + qc4.x(0).c_if(1, 1) + qc4.measure(0, 0) sampler = StatevectorSampler() with self.subTest("set parameter values to a non-parameterized circuit"): @@ -301,6 +306,9 @@ def test_run_errors(self): with self.subTest("with control flow"): with self.assertRaises(QiskitError): _ = sampler.run([qc3]).result() + with self.subTest("with c_if"): + with self.assertRaises(QiskitError): + _ = sampler.run([qc4]).result() with self.subTest("negative shots, run arg"): with self.assertRaises(ValueError): _ = sampler.run([qc1], shots=-1).result() @@ -584,17 +592,21 @@ def test_circuit_with_aliased_cregs(self): c2 = ClassicalRegister(1, "c2") qc = QuantumCircuit(q, c1, c2) - qc.ry(np.pi / 4, 2) - qc.cx(2, 1) - qc.cx(0, 1) - qc.h(0) - qc.measure(0, c1) - qc.measure(1, c2) qc.z(2).c_if(c1, 1) qc.x(2).c_if(c2, 1) qc2 = QuantumCircuit(5, 5) qc2.compose(qc, [0, 2, 3], [2, 4], inplace=True) - cregs = [creg.name for creg in qc2.cregs] + # Note: qc2 has aliased cregs, c0 -> c[2] and c1 -> c[4]. + # copy_empty_like copies the aliased cregs of qc2 to qc3. + qc3 = QuantumCircuit.copy_empty_like(qc2) + qc3.ry(np.pi / 4, 2) + qc3.cx(2, 1) + qc3.cx(0, 1) + qc3.h(0) + qc3.measure(0, 2) + qc3.measure(1, 4) + self.assertEqual(len(qc3.cregs), 3) + cregs = [creg.name for creg in qc3.cregs] target = { cregs[0]: {0: 4255, 4: 4297, 16: 720, 20: 726}, cregs[1]: {0: 5000, 1: 5000}, @@ -602,7 +614,7 @@ def test_circuit_with_aliased_cregs(self): } sampler = StatevectorSampler(seed=self._seed) - result = sampler.run([qc2], shots=self._shots).result() + result = sampler.run([qc3], shots=self._shots).result() self.assertEqual(len(result), 1) data = result[0].data self.assertEqual(len(data), 3)