Skip to content

Commit

Permalink
Invalidate parameters cache on circuit copy (Qiskit#12619)
Browse files Browse the repository at this point in the history
Previously, the caching of the parameter view could persist between
copies of the circuit because it was part of the `copy.copy`.
  • Loading branch information
jakelishman authored and Procatv committed Aug 1, 2024
1 parent 2ffc4e5 commit f1033e3
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 0 deletions.
2 changes: 2 additions & 0 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -3674,6 +3674,8 @@ def copy_empty_like(
cpy._data = CircuitData(
self._data.qubits, self._data.clbits, global_phase=self._data.global_phase
)
# Invalidate parameters caching.
cpy._parameters = None

cpy._calibrations = _copy.deepcopy(self._calibrations)
cpy._metadata = _copy.deepcopy(self._metadata)
Expand Down
7 changes: 7 additions & 0 deletions releasenotes/notes/fix-parameter-cache-05eac2f24477ccb8.yaml
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/Qiskit/qiskit/issues/12617>`__.
23 changes: 23 additions & 0 deletions test/python/circuit/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,29 @@ def test_parameters_property_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_get_parameter(self):
"""Test the `get_parameter` method."""
x = Parameter("x")
Expand Down

0 comments on commit f1033e3

Please sign in to comment.