Skip to content

Commit

Permalink
Fix QPY deserialization of UCRX, UCRY, and UCRZ gates (Qiskit#7933)
Browse files Browse the repository at this point in the history
This commit fixes the deserialization of the UCRX, UCRY, and UCRZ gates.
These gates aren't constructed in the standard way as other gate objects
where the parameters are passed directly as args to the class
constructor. Instead they behave the same as Initialize and the params
are passed as a list to the constructor to make a new gate object. This
commit fixes the handling in deserialization to treat these gates the
same as Initialize so that it can be properly deserialized by
qpy.load().

Fixes Qiskit#7847

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
mtreinish and mergify[bot] committed Apr 14, 2022
1 parent 36a3d96 commit 2f182f6
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
2 changes: 1 addition & 1 deletion qiskit/qpy/binary_io/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def _read_instruction(file_obj, circuit, registers, custom_instructions, version
if gate_name in {"IfElseOp", "WhileLoopOp"}:
gate = gate_class(condition_tuple, *params)
else:
if gate_name == "Initialize":
if gate_name in {"Initialize", "UCRXGate", "UCRYGate", "UCRZGate"}:
gate = gate_class(params)
else:
if gate_name == "Barrier":
Expand Down
18 changes: 18 additions & 0 deletions releasenotes/notes/ucr-gates-qpy-b8f6fb1e34fae258.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
fixes:
- |
Fixed an issue with QPY deserialization via the :func:`.qpy.load` function
of the :class:`~.UCRXGate`, :class:`~.UCRYGate`, and :class:`~.UCRZGate`.
Previously, a QPY file that contained any of these gates would error
when trying to load the file.
Fixed `#7847 <https://github.com/Qiskit/qiskit-terra/issues/7847>`__
issues:
- |
QPY deserialization with the :func:`.qpy.load` function of a directly
instantiated :class:`~.UCPauliRotGate` object in a circuit will fail
because the rotation axis argument to the class isn't stored in a standard
place. To workaround this you can instead use the subclasses:
:class:`~.UCRXGate`, :class:`~.UCRYGate`, or :class:`~.UCRZGate` (based on
whether you're using a rotation axis of ``"X"``, ``"Y"``, or ``"Z"``
respectively) which embeds the rotation axis in the class constructor and
will work correctly in QPY.
13 changes: 13 additions & 0 deletions test/python/circuit/test_circuit_load_from_qpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -941,3 +941,16 @@ def test_empty_tuple_param(self):
qpy_file.seek(0)
new_circuit = load(qpy_file)[0]
self.assertEqual(qc, new_circuit)

def test_ucr_gates(self):
"""Test qpy with UCRX, UCRY, and UCRZ gates."""
qc = QuantumCircuit(3)
qc.ucrz([0, 0, 0, -np.pi], [0, 1], 2)
qc.ucry([0, 0, 0, -np.pi], [0, 2], 1)
qc.ucrx([0, 0, 0, -np.pi], [2, 1], 0)
qc.measure_all()
qpy_file = io.BytesIO()
dump(qc, qpy_file)
qpy_file.seek(0)
new_circuit = load(qpy_file)[0]
self.assertEqual(qc.decompose().decompose(), new_circuit.decompose().decompose())

0 comments on commit 2f182f6

Please sign in to comment.