Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

globalphase decomposes to nothing #4855

Merged
merged 8 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@
* Simplified the logic for re-arranging states before returning.
[(#4817)](https://github.com/PennyLaneAI/pennylane/pull/4817)

* `GlobalPhase` now decomposes to nothing, in case devices do not support global phases.
[(#4855)](https://github.com/PennyLaneAI/pennylane/pull/4855)

<h3>Breaking changes 💔</h3>

* Moved `qml.cond` and the `Conditional` operation from the `transforms` folder to the `ops/op_math` folder.
Expand Down
32 changes: 32 additions & 0 deletions pennylane/ops/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,38 @@ def compute_diagonalizing_gates(
"""
return []

@staticmethod
def compute_decomposition(phi, wires=None): # pylint:disable=arguments-differ,unused-argument
r"""Representation of the operator as a product of other operators (static method).
timmysilv marked this conversation as resolved.
Show resolved Hide resolved

.. note::

The ``GlobalPhase`` operation decomposes to an empty list of operations.
Support for global phase
was added in v0.33 and was ignored in earlier versions of PennyLane. Setting
global phase to decompose to nothing allows existing devices to maintain
current support for operations which now have ``GlobalPhase`` in the
decomposition pipeline.

.. math:: O = O_1 O_2 \dots O_n.

.. seealso:: :meth:`~.GlobalPhase.decomposition`.

Args:
phi (TensorLike): the global phase
wires (Iterable[Any] or Any): unused argument - the operator is applied to all wires

Returns:
list[Operator]: decomposition into lower level operations

**Example:**

>>> qml.GlobalPhase.compute_decomposition(1.23)
[]

"""
return []
timmysilv marked this conversation as resolved.
Show resolved Hide resolved

def matrix(self, wire_order=None):
n_wires = len(wire_order) if wire_order else len(self.wires)
return self.compute_matrix(self.data[0], n_wires=n_wires)
Expand Down
7 changes: 7 additions & 0 deletions pennylane/ops/op_math/controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,13 @@ def _decompose_no_control_values(op: "operation.Operator") -> List["operation.Op
return None

base_decomp = op.base.decomposition()
if len(base_decomp) == 0 and isinstance(op.base, qml.GlobalPhase):
warnings.warn(
"Controlled-GlobalPhase currently decomposes to nothing, and this will likely "
"produce incorrect results. Consider implementing your circuit with a different set "
"of operations, or use a device that natively supports GlobalPhase.",
UserWarning,
)

return [Controlled(newop, op.control_wires, work_wires=op.work_wires) for newop in base_decomp]

Expand Down
8 changes: 8 additions & 0 deletions tests/ops/op_math/test_controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,14 @@ def test_differentiable_one_qubit_special_unitary(self):
decomp_mat = qml.matrix(op.decomposition, wire_order=op.wires)()
assert qml.math.allclose(op.matrix(), decomp_mat)

def test_global_phase_decomp_raises_warning(self):
"""Test that ctrl(GlobalPhase).decomposition() raises a warning."""
op = qml.ctrl(qml.GlobalPhase(1.23), control=[0])
with pytest.warns(
UserWarning, match="Controlled-GlobalPhase currently decomposes to nothing"
):
assert op.decomposition() == []


@pytest.mark.parametrize("test_expand", (False, True))
class TestDecomposition:
Expand Down
7 changes: 7 additions & 0 deletions tests/ops/qubit/test_parametric_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -4522,6 +4522,13 @@ def test_global_phase_compute_sparse_matrix(phi, n_wires):
assert np.allclose(sparse_matrix.todense(), expected.todense())


def test_decomposition():
"""Test the decomposition of the GlobalPhase operation."""

assert qml.GlobalPhase.compute_decomposition(1.23) == []
assert qml.GlobalPhase(1.23).decomposition() == []


control_data = [
(qml.Rot(1, 2, 3, wires=0), Wires([])),
(qml.RX(1.23, wires=0), Wires([])),
Expand Down
Loading