From 76f7dffdd50f129706c2065bd48de279eefc6a6d Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:46:38 -0500 Subject: [PATCH 1/4] Fix: Discard cache when assigning new parameters in `CircuitData`. --- crates/circuit/src/circuit_data.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/circuit/src/circuit_data.rs b/crates/circuit/src/circuit_data.rs index 1c12aef9efc..699ad5f3d1c 100644 --- a/crates/circuit/src/circuit_data.rs +++ b/crates/circuit/src/circuit_data.rs @@ -1394,13 +1394,7 @@ impl CircuitData { // Standard gates can all rebuild their definitions, so if the // cached py_op exists, update the `params` attribute and clear out // any existing cache. - if let Some(borrowed) = previous.py_op.get() { - borrowed - .bind(py) - .getattr(params_attr)? - .set_item(parameter, new_param)?; - borrowed.bind(py).setattr("_definition", py.None())? - } + previous.py_op.take(); } } else { // Track user operations we've seen so we can rebind their definitions. From 0f469899a8345be3d89b7092072e3cc0b8023888 Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:03:30 -0500 Subject: [PATCH 2/4] Docs: Add release note --- .../notes/fix-assign-parameters-ffa284ebde429704.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 releasenotes/notes/fix-assign-parameters-ffa284ebde429704.yaml diff --git a/releasenotes/notes/fix-assign-parameters-ffa284ebde429704.yaml b/releasenotes/notes/fix-assign-parameters-ffa284ebde429704.yaml new file mode 100644 index 00000000000..b1e1dc5f67d --- /dev/null +++ b/releasenotes/notes/fix-assign-parameters-ffa284ebde429704.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + Fix incorrect behavior in :class:`.CircuitData` in which, upon parameter assignment, + we attempted to modify the cached operation inside of a ``PackedInstruction``. Now + we instead discard said cache prompting the ``PackedInstruction`` to build a new Python + operation should it be needed. \ No newline at end of file From 2ec61bb4559715956497ed069aaf00089e849f50 Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:36:12 -0500 Subject: [PATCH 3/4] Test: Add test case --- test/python/transpiler/test_basis_translator.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/python/transpiler/test_basis_translator.py b/test/python/transpiler/test_basis_translator.py index 820c4f241a1..06762a78f1f 100644 --- a/test/python/transpiler/test_basis_translator.py +++ b/test/python/transpiler/test_basis_translator.py @@ -21,6 +21,7 @@ from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit import transpile from qiskit.circuit import Gate, Parameter, EquivalenceLibrary, Qubit, Clbit, Measure +from qiskit.circuit.equivalence_library import StandardEquivalenceLibrary as std_eq_lib from qiskit.circuit.classical import expr, types from qiskit.circuit.library import ( HGate, @@ -481,6 +482,22 @@ def test_different_bits(self): out = BasisTranslator(std_eqlib, basis).run(circuit_to_dag(base)) self.assertEqual(set(out.count_ops(recurse=True)), basis) + def test_correct_parameter_assignment(self): + """Test correct parameter assignment from an equivalence during translation""" + rx_key = next(key for key in std_eq_lib.keys() if key.name == "rx") + + # The circuit doesn't need to be parametric. + qc = QuantumCircuit(1) + qc.rx(0.5, 0) + + BasisTranslator( + equivalence_library=std_eq_lib, + target_basis=["cx", "id", "rz", "sx", "x"], + )(qc) + + inst = std_eq_lib._get_equivalences(rx_key)[0].circuit.data[0] + self.assertEqual(inst.params, inst.operation.params) + class TestUnrollerCompatability(QiskitTestCase): """Tests backward compatability with the Unroller pass. From 0b5f59b7d8f4b60637799ada63e7e0847da2c9a4 Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Wed, 11 Dec 2024 17:15:53 -0500 Subject: [PATCH 4/4] Docs: Add relevant comment --- crates/circuit/src/circuit_data.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/circuit/src/circuit_data.rs b/crates/circuit/src/circuit_data.rs index 699ad5f3d1c..fa36d8b841f 100644 --- a/crates/circuit/src/circuit_data.rs +++ b/crates/circuit/src/circuit_data.rs @@ -1392,8 +1392,11 @@ impl CircuitData { #[cfg(feature = "cache_pygates")] { // Standard gates can all rebuild their definitions, so if the - // cached py_op exists, update the `params` attribute and clear out - // any existing cache. + // cached py_op exists, discard it to prompt the instruction + // to rebuild its cached python gate upon request later on. This is + // done to avoid an unintentional duplicated reference to the same gate + // instance in python. For more information, see + // https://github.com/Qiskit/qiskit/issues/13504 previous.py_op.take(); } } else {