From 5a250c7ae6dc6cb1031462adbf55bfca9a13d440 Mon Sep 17 00:00:00 2001 From: SoranaAurelia <52232581+SoranaAurelia@users.noreply.github.com> Date: Sat, 18 Nov 2023 01:55:17 +0200 Subject: [PATCH] Allow correct retrieval of circuit with initialize instruction from qpy file (#11206) * treated cases for StatePreparation initialization when reading from qpy file * added test for state preparation from qpy * added docstring to test function * added fix release note * Fixup release note --------- Co-authored-by: Jake Lishman (cherry picked from commit 9111d0f9e198a87433da2d5dd8fa9427b9140194) --- qiskit/qpy/binary_io/circuits.py | 14 +++++++++++--- ...tatepreparation-retrieval-1feea5eb74db7f1e.yaml | 5 +++++ test/python/circuit/test_circuit_load_from_qpy.py | 12 ++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/fix-qpy-statepreparation-retrieval-1feea5eb74db7f1e.yaml diff --git a/qiskit/qpy/binary_io/circuits.py b/qiskit/qpy/binary_io/circuits.py index 81785bf78151..6d910746a89a 100644 --- a/qiskit/qpy/binary_io/circuits.py +++ b/qiskit/qpy/binary_io/circuits.py @@ -319,9 +319,17 @@ def _read_instruction( if condition: gate = gate.c_if(*condition) else: - if gate_name in { - "Initialize", - "StatePreparation", + if gate_name in {"Initialize", "StatePreparation"}: + if isinstance(params[0], str): + # the params are the labels of the initial state + gate = gate_class("".join(label for label in params)) + elif instruction.num_parameters == 1: + # the params is the integer indicating which qubits to initialize + gate = gate_class(int(params[0].real), instruction.num_qargs) + else: + # the params represent a list of complex amplitudes + gate = gate_class(params) + elif gate_name in { "UCRXGate", "UCRYGate", "UCRZGate", diff --git a/releasenotes/notes/fix-qpy-statepreparation-retrieval-1feea5eb74db7f1e.yaml b/releasenotes/notes/fix-qpy-statepreparation-retrieval-1feea5eb74db7f1e.yaml new file mode 100644 index 000000000000..67cdafcb463a --- /dev/null +++ b/releasenotes/notes/fix-qpy-statepreparation-retrieval-1feea5eb74db7f1e.yaml @@ -0,0 +1,5 @@ +fixes: + - | + Fixed QPY deserialization of the :class:`.StatePreparation` and :class:`.Initialize` circuit + instructions with string and integer parameters (as opposed to an explicit statevector, which + was already working). Fixed `#11158 `__. diff --git a/test/python/circuit/test_circuit_load_from_qpy.py b/test/python/circuit/test_circuit_load_from_qpy.py index f8ba8c260df9..4f8523358dbd 100644 --- a/test/python/circuit/test_circuit_load_from_qpy.py +++ b/test/python/circuit/test_circuit_load_from_qpy.py @@ -1685,6 +1685,18 @@ def test_qpy_deprecation(self): # pylint: disable=no-name-in-module, unused-import, redefined-outer-name, reimported from qiskit.circuit.qpy_serialization import dump, load + @ddt.data(0, "01", [1, 0, 0, 0]) + def test_valid_circuit_with_initialize_instruction(self, param): + """Tests that circuit that has initialize instruction can be saved and correctly retrieved""" + qc = QuantumCircuit(2) + qc.initialize(param, qc.qubits) + with io.BytesIO() as fptr: + dump(qc, fptr) + fptr.seek(0) + new_circuit = load(fptr)[0] + self.assertEqual(qc, new_circuit) + self.assertDeprecatedBitProperties(qc, new_circuit) + class TestSymengineLoadFromQPY(QiskitTestCase): """Test use of symengine in qpy set of methods."""