Repository: PennyLaneAI/pennylane (python)

Issue:
[unitaryhack] Add the CPhase operation
*This issue has been tagged for contributions during [unitaryHACK](https://unitaryfund.github.io/unitaryhack/participating-projects.html)*

**Context**
We would like to define a new diagonal operation called `CPhase`, see [further details here](https://qiskit.org/documentation/stubs/qiskit.circuit.library.CPhaseGate.html).

**Steps to take**

This would involve the following steps to be completed:

*A. Adding the operation*

1. Adding the `CPhase` class and its attributes to `pennylane/ops/qubit.py`. This class would inherit from `DiagonalOperation`. Complete its docstring in a similar fashion as for other operations. Make sure the class is accessible through `qml.CPhase`.
2. Add its decomposition: a definition for how the operation could be decomposed into elementary operations,
3. Add its matrix, eigenvalues, adjoint and generator,
4. *Test:* include tests for the operation in the `tests/ops/test_qubit_ops.py` file,

In these steps, having a look at how `class PhaseShift` is defined can help. Also, see [the operation as defined in the `PennyLane-Cirq` plugin](https://github.com/PennyLaneAI/pennylane-cirq/blob/e121db9e1e314b290811256f83722de29cc292f3/pennylane_cirq/ops.py#L142) as a basis.

*B. Adding `default.qubit` support*

5. Add support for the operation in the `default.qubit` device,
6. *Test:* test the operation with `default.qubit` in the `tests/devices/test_default_qubit.py` file.

*Bonus:* Add support to the interface-specific `default.qubit` devices too: `default.qubit.autograd` and `default.qubit.tf`. This will require the operation to be defined in a framework-specific way. These devices inherit the supported operations from `default.qubit`, so if this step is not tackled, the `CPHASE` can be removed from the `operations` dictionary for `default.qubit.autograd` and `default.qubit.tf`.

Pull request description:
[unitaryHACK] Add the CPhase operation
**Context:** Add a new diagonal operator, `CPhase`.

**Description of the Change:** Adds  the `CPhase` operator *as an alias for the `ControlledPhaseShift` operator*.

**Benefits:** Adds the `CPhase` diagonal operator.

**Possible Drawbacks:** ~It has the same structure as `ControlledPhaseShift`, maybe adds duplicated code that could be solved by using `CPhase` as an alias for the `ControlledPhaseShift`.~

**Related GitHub Issues:** closes #1147


Patch:
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 3aafaae7c..d457c9037 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -1,6 +1,8 @@
 # Release 0.16.0-dev (development release)
 
 <h3>New features since last release</h3>
+* Added CPhase operation as an alias for ControlledPhaseShift operation
+  [(#1319)](https://github.com/PennyLaneAI/pennylane/pull/1319).
 
 * The `qml.Toffoli` operation now has a decomposition over elementary gates. 
   [(#1320)](https://github.com/PennyLaneAI/pennylane/pull/1320)
@@ -258,7 +260,8 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)
 
 This release contains contributions from (in alphabetical order):
 
-Vishnu Ajith, Thomas Bromley, Olivia Di Matteo, Tanya Garg, Diego Guala, Anthony Hayes, Josh Izaac, Brian Shi, Antal Száva, Pavan Jayasinha
+Vishnu Ajith, Thomas Bromley, Olivia Di Matteo, Tanya Garg, Diego Guala,
+Anthony Hayes, Josh Izaac, Pavan Jayasinha, Nahum Sá, Brian Shi, Antal Száva
 
 # Release 0.15.1 (current release)
 
diff --git a/pennylane/devices/default_qubit.py b/pennylane/devices/default_qubit.py
index e5add1007..111630f70 100644
--- a/pennylane/devices/default_qubit.py
+++ b/pennylane/devices/default_qubit.py
@@ -112,6 +112,7 @@ class DefaultQubit(QubitDevice):
         "CZ",
         "PhaseShift",
         "ControlledPhaseShift",
+        "CPhase",
         "RX",
         "RY",
         "RZ",
diff --git a/pennylane/devices/default_qubit_autograd.py b/pennylane/devices/default_qubit_autograd.py
index 6476b66de..8571b8634 100644
--- a/pennylane/devices/default_qubit_autograd.py
+++ b/pennylane/devices/default_qubit_autograd.py
@@ -84,6 +84,7 @@ class DefaultQubitAutograd(DefaultQubit):
     parametric_ops = {
         "PhaseShift": autograd_ops.PhaseShift,
         "ControlledPhaseShift": autograd_ops.ControlledPhaseShift,
+        "CPhase": autograd_ops.ControlledPhaseShift,
         "RX": autograd_ops.RX,
         "RY": autograd_ops.RY,
         "RZ": autograd_ops.RZ,
diff --git a/pennylane/devices/default_qubit_jax.py b/pennylane/devices/default_qubit_jax.py
index e50997381..3d99a1928 100644
--- a/pennylane/devices/default_qubit_jax.py
+++ b/pennylane/devices/default_qubit_jax.py
@@ -137,6 +137,7 @@ class DefaultQubitJax(DefaultQubit):
     parametric_ops = {
         "PhaseShift": jax_ops.PhaseShift,
         "ControlledPhaseShift": jax_ops.ControlledPhaseShift,
+        "CPhase": jax_ops.ControlledPhaseShift,
         "RX": jax_ops.RX,
         "RY": jax_ops.RY,
         "RZ": jax_ops.RZ,
diff --git a/pennylane/devices/default_qubit_tf.py b/pennylane/devices/default_qubit_tf.py
index 694a8b953..b60281d7f 100644
--- a/pennylane/devices/default_qubit_tf.py
+++ b/pennylane/devices/default_qubit_tf.py
@@ -131,6 +131,7 @@ class DefaultQubitTF(DefaultQubit):
     parametric_ops = {
         "PhaseShift": tf_ops.PhaseShift,
         "ControlledPhaseShift": tf_ops.ControlledPhaseShift,
+        "CPhase": tf_ops.ControlledPhaseShift,
         "RX": tf_ops.RX,
         "RY": tf_ops.RY,
         "RZ": tf_ops.RZ,
diff --git a/pennylane/ops/qubit.py b/pennylane/ops/qubit.py
index f770a9f79..5b2fff147 100644
--- a/pennylane/ops/qubit.py
+++ b/pennylane/ops/qubit.py
@@ -941,6 +941,9 @@ class ControlledPhaseShift(DiagonalOperation):
         return ControlledPhaseShift(-self.data[0], wires=self.wires)
 
 
+CPhase = ControlledPhaseShift
+
+
 class Rot(Operation):
     r"""Rot(phi, theta, omega, wires)
     Arbitrary single qubit rotation
@@ -3067,6 +3070,7 @@ ops = {
     "RZ",
     "PhaseShift",
     "ControlledPhaseShift",
+    "CPhase",
     "Rot",
     "CRX",
     "CRY",


Test patch:
diff --git a/tests/ops/test_qubit_ops.py b/tests/ops/test_qubit_ops.py
index a9f38626e..cac70dfd4 100644
--- a/tests/ops/test_qubit_ops.py
+++ b/tests/ops/test_qubit_ops.py
@@ -376,6 +376,7 @@ class TestOperations:
             qml.Toffoli(wires=[0, 1, 2]),
             qml.PhaseShift(2.133, wires=0),
             qml.ControlledPhaseShift(1.777, wires=[0, 2]),
+            qml.CPhase(1.777, wires=[0, 2]),
             qml.MultiRZ(0.112, wires=[1, 2, 3]),
             qml.CRX(0.836, wires=[2, 3]),
             qml.CRY(0.721, wires=[2, 3]),
@@ -980,10 +981,11 @@ class TestOperations:
         assert np.allclose(decomposed_matrix, opr.matrix)
 
     @pytest.mark.parametrize("phi", [-0.1, 0.2, 0.5])
-    def test_controlled_phase_shift_matrix_and_eigvals(self, phi):
-        """Tests that the ControlledPhaseShift operation calculates the correct matrix and
+    @pytest.mark.parametrize("cphase_op", [qml.ControlledPhaseShift, qml.CPhase])
+    def test_controlled_phase_shift_matrix_and_eigvals(self, phi, cphase_op):
+        """Tests that the ControlledPhaseShift and CPhase operation calculates the correct matrix and
         eigenvalues"""
-        op = qml.ControlledPhaseShift(phi, wires=[0, 1])
+        op = cphase_op(phi, wires=[0, 1])
         res = op.matrix
         exp = ControlledPhaseShift(phi)
         assert np.allclose(res, exp)
@@ -992,9 +994,10 @@ class TestOperations:
         assert np.allclose(res, np.diag(exp))
 
     @pytest.mark.parametrize("phi", [-0.1, 0.2, 0.5])
-    def test_controlled_phase_shift_decomp(self, phi):
-        """Tests that the ControlledPhaseShift operation calculates the correct decomposition"""
-        op = qml.ControlledPhaseShift(phi, wires=[0, 1])
+    @pytest.mark.parametrize("cphase_op", [qml.ControlledPhaseShift, qml.CPhase])
+    def test_controlled_phase_shift_decomp(self, phi, cphase_op):
+        """Tests that the ControlledPhaseShift and CPhase operation calculates the correct decomposition"""
+        op = cphase_op(phi, wires=[0, 1])
         decomp = op.decomposition(phi, wires=[0, 1])
 
         mats = []
diff --git a/tests/tape/test_reversible.py b/tests/tape/test_reversible.py
index a004e968a..6731a74ea 100644
--- a/tests/tape/test_reversible.py
+++ b/tests/tape/test_reversible.py
@@ -282,6 +282,7 @@ class TestGradients:
         qml.CRot,
         qml.PhaseShift,
         qml.ControlledPhaseShift,
+        qml.CPhase,
         qml.PauliRot,
         qml.MultiRZ,
         qml.U1,