diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index 0b492801bef8..4ddae549699e 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -2147,6 +2147,8 @@ def copy_empty_like(self, name: str | None = None) -> "QuantumCircuit": cpy._calibrations = copy.deepcopy(self._calibrations) cpy._metadata = copy.deepcopy(self._metadata) + # Invalidate parameters caching. + cpy._parameters = None if name: cpy.name = name diff --git a/releasenotes/notes/fix-parameter-cache-05eac2f24477ccb8.yaml b/releasenotes/notes/fix-parameter-cache-05eac2f24477ccb8.yaml new file mode 100644 index 000000000000..05ac759569f7 --- /dev/null +++ b/releasenotes/notes/fix-parameter-cache-05eac2f24477ccb8.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + The :attr:`.QuantumCircuit.parameters` attribute will now correctly be empty + when using :meth:`.QuantumCircuit.copy_empty_like` on a parametric circuit. + Previously, an internal cache would be copied over without invalidation. + Fix `#12617 `__. diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 80c26b5b5c0a..4aff0c9de8da 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -176,6 +176,29 @@ def test_get_parameters_by_index(self): for i, vi in enumerate(v): self.assertEqual(vi, qc.parameters[i]) + def test_parameters_property_independent_after_copy(self): + """Test that any `parameters` property caching is invalidated after a copy operation.""" + a = Parameter("a") + b = Parameter("b") + c = Parameter("c") + + qc1 = QuantumCircuit(1) + qc1.rz(a, 0) + self.assertEqual(set(qc1.parameters), {a}) + + qc2 = qc1.copy_empty_like() + self.assertEqual(set(qc2.parameters), set()) + + qc3 = qc1.copy() + self.assertEqual(set(qc3.parameters), {a}) + qc3.rz(b, 0) + self.assertEqual(set(qc3.parameters), {a, b}) + self.assertEqual(set(qc1.parameters), {a}) + + qc1.rz(c, 0) + self.assertEqual(set(qc1.parameters), {a, c}) + self.assertEqual(set(qc3.parameters), {a, b}) + def test_bind_parameters_anonymously(self): """Test setting parameters by insertion order anonymously""" phase = Parameter("phase")