Repository: PennyLaneAI/pennylane
Pull request #1342 (2021-05-20 02:52:59)

 [unitaryhack] Add decomposition for qml.CSWAP #1306 

I am Alberto Maldonado and I added the definition of CSWAP components from three Toffoli gates.

codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#1342](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (d309ec5) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/98a787643f4928b6078fede6d4ecb7adab3e1800?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (98a7876) will **decrease** coverage by `50.54%`.
> The diff coverage is `50.00%`.

[![Impacted file tree graph](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/graphs/tree.svg?width=650&height=150&src=pr&token=9S3YzlUgGk&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)

```diff
@@             Coverage Diff             @@
##           master    #1342       +/-   ##
===========================================
- Coverage   98.15%   47.61%   -50.55%     
===========================================
  Files         145      145               
  Lines       11079    11083        +4     
===========================================
- Hits        10875     5277     -5598     
- Misses        204     5806     +5602     
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/ops/qubit.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC5weQ==) | `71.77% <50.00%> (-26.77%)` | :arrow_down: |
| [pennylane/beta/\_\_init\_\_.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2JldGEvX19pbml0X18ucHk=) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pennylane/devices/tf\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2RldmljZXMvdGZfb3BzLnB5) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pennylane/devices/jax\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2RldmljZXMvamF4X29wcy5weQ==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pennylane/interfaces/torch.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2ludGVyZmFjZXMvdG9yY2gucHk=) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pennylane/beta/devices/\_\_init\_\_.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2JldGEvZGV2aWNlcy9fX2luaXRfXy5weQ==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pennylane/beta/devices/numpy\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2JldGEvZGV2aWNlcy9udW1weV9vcHMucHk=) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pennylane/templates/utils.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RlbXBsYXRlcy91dGlscy5weQ==) | `0.00% <0.00%> (-98.25%)` | :arrow_down: |
| [pennylane/interfaces/tf.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2ludGVyZmFjZXMvdGYucHk=) | `0.00% <0.00%> (-97.15%)` | :arrow_down: |
| [pennylane/qnn/keras.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3Fubi9rZXJhcy5weQ==) | `0.00% <0.00%> (-95.39%)` | :arrow_down: |
| ... and [109 more](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [98a7876...d309ec5](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1342?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).

josh146: Thanks @MaldoAlberto for this contribution!

I've noticed that a few of the checks are currently failing:

- Changelog: don't forget to add an entry to the changelog (`.github/CHANGELOG.md`) describing this change, as well as linking back to this PR. You can also add your name to the contributors section 🙂 

- Formatting: If you haven't already, install the `black` code formatter: `pip install black`. Then, before you commit changes, make sure to format the source code and tests: `black -l 100 pennylane tests`

- Tests: finally, it looks like the new test is not passing, resulting in the following error message:

  ```python
   Traceback (most recent call last):
   File "/home/runner/work/pennylane/pennylane/tests/ops/test_qubit_ops.py", line 744, in test_CSWAP_decomposition
      [[1, 0, 0, 0, 0, 0, 0, 0]
  TypeError: list indices must be integers or slices, not tuple
  ```

Let us know when you have addressed these, and someone from the team will be on hand to provide a review 🙂 In addition, feel free to ask us any questions!
MaldoAlberto: Hi @josh146  I have already made the pertinent changes but I got this in files that I did not modify
![Screenshot from 2021-05-20 11-34-57](https://user-images.githubusercontent.com/21325664/119016559-b125ac80-b95f-11eb-8b47-7154ac6d99bc.png)

josh146: Hi @MaldoAlberto, that's strange 🤔 Could you try updating your version of black,
```
pip install black --upgrade
```
and trying again?
MaldoAlberto:  @josh146 now works 
![Screenshot from 2021-05-20 13-24-59](https://user-images.githubusercontent.com/21325664/119029900-d968d780-b96e-11eb-9b1b-fa9374c7a605.png)


Patch:
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 10a5f0736..0f14dbf6d 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -118,9 +118,8 @@
   + (0.25) [Y5 X4 Y0]
   >>> mapping
   {0: (0, 1), 1: (0, 2), 2: (1, 0), 3: (1, 2), 4: (2, 0), 5: (2, 1)}
-  ```
-  
-  Additional functionality can be found in the `qml.qaoa.cycle` module.
+  ``` 
+ Additional functionality can be found in the `qml.qaoa.cycle` module.
 
 * Adds `QubitCarry` and `QubitSum` operations for basic arithmetic.
   [(#1169)](https://github.com/PennyLaneAI/pennylane/pull/1169)
@@ -174,6 +173,9 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)
 
 <h3>Improvements</h3>
 
+*  A decomposition has been added for the `qml.CSWAP` operation.
+  [(#1306)](https://github.com/PennyLaneAI/pennylane/issues/1306)
+
 * The `qml.inv()` function is now deprecated with a warning to use the more general `qml.adjoint()`.
   [(#1325)](https://github.com/PennyLaneAI/pennylane/pull/1325)
 
@@ -303,7 +305,7 @@ This release contains contributions from (in alphabetical order):
 
 Marius Aglitoiu, Vishnu Ajith, Thomas Bromley, Jack Ceroni, Miruna Daian, Olivia Di Matteo,
 Tanya Garg, Diego Guala, Anthony Hayes, Josh Izaac, Pavan Jayasinha, Ryan Levy, Nahum Sá,
-Brian Shi, Antal Száva, Vincent Wong.
+Brian Shi, Antal Száva, Vincent Wong, Alberto Maldonado.
 
 # Release 0.15.1 (current release)
 
diff --git a/pennylane/ops/qubit.py b/pennylane/ops/qubit.py
index 8d224fac8..be12bb78a 100644
--- a/pennylane/ops/qubit.py
+++ b/pennylane/ops/qubit.py
@@ -634,6 +634,15 @@ class CSWAP(Operation):
     def _matrix(cls, *params):
         return cls.matrix
 
+    @staticmethod
+    def decomposition(wires):
+        decomp_ops = [
+            qml.Toffoli(wires=[wires[0], wires[2], wires[1]]),
+            qml.Toffoli(wires=[wires[0], wires[1], wires[2]]),
+            qml.Toffoli(wires=[wires[0], wires[2], wires[1]]),
+        ]
+        return decomp_ops
+
     def adjoint(self):
         return CSWAP(wires=self.wires)
 


Test patch:
diff --git a/tests/ops/test_qubit_ops.py b/tests/ops/test_qubit_ops.py
index 2e3baf42b..dc6bfe843 100644
--- a/tests/ops/test_qubit_ops.py
+++ b/tests/ops/test_qubit_ops.py
@@ -784,6 +784,51 @@ class TestOperations:
 
         assert np.allclose(decomposed_matrix, op.matrix, atol=tol, rtol=0)
 
+    def test_CSWAP_decomposition(self, tol):
+        """Tests that the decomposition of the CSWAP gate is correct"""
+        op = qml.CSWAP(wires=[0, 1, 2])
+        res = op.decomposition(op.wires)
+
+        assert len(res) == 3
+
+        mats = []
+
+        for i in reversed(res):  # only use 3 toffoli gates
+            if i.wires == Wires([0, 2, 1]) and i.name == "Toffoli":
+                mats.append(
+                    np.array(
+                        [
+                            [1, 0, 0, 0, 0, 0, 0, 0],
+                            [0, 1, 0, 0, 0, 0, 0, 0],
+                            [0, 0, 1, 0, 0, 0, 0, 0],
+                            [0, 0, 0, 1, 0, 0, 0, 0],
+                            [0, 0, 0, 0, 1, 0, 0, 0],
+                            [0, 0, 0, 0, 0, 0, 0, 1],
+                            [0, 0, 0, 0, 0, 0, 1, 0],
+                            [0, 0, 0, 0, 0, 1, 0, 0],
+                        ]
+                    )
+                )
+            elif i.wires == Wires([0, 1, 2]) and i.name == "Toffoli":
+                mats.append(
+                    np.array(
+                        [
+                            [1, 0, 0, 0, 0, 0, 0, 0],
+                            [0, 1, 0, 0, 0, 0, 0, 0],
+                            [0, 0, 1, 0, 0, 0, 0, 0],
+                            [0, 0, 0, 1, 0, 0, 0, 0],
+                            [0, 0, 0, 0, 1, 0, 0, 0],
+                            [0, 0, 0, 0, 0, 1, 0, 0],
+                            [0, 0, 0, 0, 0, 0, 0, 1],
+                            [0, 0, 0, 0, 0, 0, 1, 0],
+                        ]
+                    )
+                )
+
+        decomposed_matrix = np.linalg.multi_dot(mats)
+
+        assert np.allclose(decomposed_matrix, op.matrix, atol=tol, rtol=0)
+
     def test_phase_shift(self, tol):
         """Test phase shift is correct"""