Repository: PennyLaneAI/pennylane
Pull request #1662 (2021-09-16 18:03:54)

Adjust Torch and TF backprop docstrings

github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [.github/CHANGELOG.md](/PennyLaneAI/pennylane/blob/master/.github/CHANGELOG.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1662?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> :exclamation: No coverage uploaded for pull request base (`v0.18.0-rc0@0e9cbdb`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#section-missing-base-commit).
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1662/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/1662?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)

```diff
@@              Coverage Diff               @@
##             v0.18.0-rc0    #1662   +/-   ##
==============================================
  Coverage               ?   99.14%           
==============================================
  Files                  ?      197           
  Lines                  ?    14431           
  Branches               ?        0           
==============================================
  Hits                   ?    14307           
  Misses                 ?      124           
  Partials               ?        0           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1662?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/1662?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [0e9cbdb...5f4501f](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1662?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).


Patch:
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 4592155d8..0884159da 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -2,6 +2,46 @@
 
 <h3>New features since last release</h3>
 
+<h4>PennyLane now comes packaged with <code>lightning.qubit</code></h4>
+
+* The C++-based [lightning.qubit](https://pennylane-lightning.readthedocs.io/en/stable/) device
+  is now included with installations of PennyLane. The `lightning.qubit` device is a fast
+  state-vector simulator equipped with the efficient
+  [adjoint method](https://arxiv.org/abs/2009.02823) for differentiating quantum circuits,
+  check out the plugin
+  [release notes](https://github.com/PennyLaneAI/pennylane-lightning/blob/v0.18.0/.github/CHANGELOG.md#new-features-since-last-release) for more details! The device can be accessed in the following way:
+  
+  ```python
+  import pennylane as qml
+
+  wires = 3
+  layers = 2
+  dev = qml.device("lightning.qubit", wires=wires)
+
+  @qml.qnode(dev, diff_method="adjoint")
+  def circuit(weights):
+      qml.templates.StronglyEntanglingLayers(weights, wires=range(wires))
+      return qml.expval(qml.PauliZ(0))
+
+  weights = qml.init.strong_ent_layers_normal(layers, wires, seed=1967)
+  ```
+  
+  Evaluating circuits and their gradients on the device can be achieved using the standard approach:
+  
+  ```pycon
+  >>> print(f"Circuit evaluated: {circuit(weights)}")
+  Circuit evaluated: 0.9801286266677633
+  >>> print(f"Circuit gradient:\n{qml.grad(circuit)(weights)}")
+  Circuit gradient:
+  [[[-9.35301749e-17 -1.63051504e-01 -4.14810501e-04]
+    [-7.88816484e-17 -1.50136528e-04 -1.77922957e-04]
+    [-5.20670796e-17 -3.92874550e-02  8.14523075e-05]]
+
+   [[-1.14472273e-04  3.85963953e-02 -9.39190132e-18]
+    [-5.76791765e-05 -9.78478343e-02  0.00000000e+00]
+    [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]]] 
+  ```
+
 * Custom gradient transforms can now be created using the new
   `@qml.gradients.gradient_transform` decorator on a batch-tape transform.
   [(#1589)](https://github.com/PennyLaneAI/pennylane/pull/1589)
@@ -461,6 +501,9 @@ and requirements-ci.txt (unpinned). This latter would be used by the CI.
 
 <h3>Bug fixes</h3>
 
+* Fix bug with shot vectors and `Device` base class.
+  [(#1666)](https://github.com/PennyLaneAI/pennylane/pull/1666)
+
 * Fix bug with norm and Jax tracers (jit) when using `QubiStateVector`.
   [(#1649)](https://github.com/PennyLaneAI/pennylane/pull/1649)
   
diff --git a/pennylane/_device.py b/pennylane/_device.py
index f6c74ee67..3824d2a51 100644
--- a/pennylane/_device.py
+++ b/pennylane/_device.py
@@ -89,7 +89,7 @@ def _process_shot_sequence(shot_list):
     else:
         raise ValueError(f"Unknown shot sequence format {shot_list}")
 
-    total_shots = np.sum(np.prod(shot_vector, axis=1))
+    total_shots = int(np.sum(np.prod(shot_vector, axis=1)))
     return total_shots, shot_vector
 
 
diff --git a/pennylane/circuit_drawer/mpldrawer.py b/pennylane/circuit_drawer/mpldrawer.py
index 58ba86653..2993363df 100644
--- a/pennylane/circuit_drawer/mpldrawer.py
+++ b/pennylane/circuit_drawer/mpldrawer.py
@@ -16,14 +16,12 @@ This module contains the MPLDrawer class for creating circuit diagrams with matp
 """
 from collections.abc import Iterable
 
+has_mpl = True
 try:
     import matplotlib.pyplot as plt
     from matplotlib import patches
 except (ModuleNotFoundError, ImportError) as e:
-    raise ImportError(
-        "Module matplotlib is required for ``MPLDrawer`` class. "
-        "You can install matplotlib via \n\n   pip install matplotlib"
-    ) from e
+    has_mpl = False
 
 
 def _to_tuple(a):
@@ -217,6 +215,12 @@ class MPLDrawer:
 
     def __init__(self, n_layers, n_wires, wire_options=None, figsize=None):
 
+        if not has_mpl:
+            raise ImportError(
+                "Module matplotlib is required for ``MPLDrawer`` class. "
+                "You can install matplotlib via \n\n   pip install matplotlib"
+            )
+
         self.n_layers = n_layers
         self.n_wires = n_wires
 
diff --git a/pennylane/devices/default_qubit_tf.py b/pennylane/devices/default_qubit_tf.py
index 2dc774e73..83ecbe066 100644
--- a/pennylane/devices/default_qubit_tf.py
+++ b/pennylane/devices/default_qubit_tf.py
@@ -103,9 +103,10 @@ class DefaultQubitTF(DefaultQubit):
     * You must use the ``"tf"`` interface for classical backpropagation, as TensorFlow is
       used as the device backend.
 
-    * Only exact expectation values, variances, and probabilities are differentiable.
-      When instantiating the device with ``analytic=False``, differentiating QNode
-      outputs will result in ``None``.
+    * Only exact expectation values, variances, and probabilities are
+      differentiable. Creation of a backpropagation QNode with finite shots
+      raises an error. If you do try and take a derivative with finite shots on
+      this device, the gradient will be ``None``.
 
 
     If you wish to use a different machine-learning interface, or prefer to calculate quantum
diff --git a/pennylane/devices/default_qubit_torch.py b/pennylane/devices/default_qubit_torch.py
index 711331ba7..a2e3007a0 100644
--- a/pennylane/devices/default_qubit_torch.py
+++ b/pennylane/devices/default_qubit_torch.py
@@ -111,7 +111,7 @@ class DefaultQubitTorch(DefaultQubit):
 
     * Only exact expectation values, variances, and probabilities are differentiable.
       When instantiating the device with ``shots!=None``, differentiating QNode
-      outputs will result in ``None``.
+      outputs will result in an error.
 
     If you wish to use a different machine-learning interface, or prefer to calculate quantum
     gradients using the ``parameter-shift`` or ``finite-diff`` differentiation methods,
diff --git a/pennylane/math/__init__.py b/pennylane/math/__init__.py
index 2b32ab82c..969273142 100644
--- a/pennylane/math/__init__.py
+++ b/pennylane/math/__init__.py
@@ -88,5 +88,6 @@ __all__ = [
     "cov_matrix",
     "marginal_prob",
     "unwrap",
+    "frobenius_inner_product",
     "get_trainable_indices",
 ]
diff --git a/pennylane/ops/qubit/hamiltonian.py b/pennylane/ops/qubit/hamiltonian.py
index 2c85d4734..c81abe29c 100644
--- a/pennylane/ops/qubit/hamiltonian.py
+++ b/pennylane/ops/qubit/hamiltonian.py
@@ -368,8 +368,8 @@ class Hamiltonian(Observable):
 
         >>> H = qml.Hamiltonian([1, 1], [qml.PauliX(0) @ qml.PauliX(1), qml.PauliZ(0)])
         >>> print(H._obs_data())
-        {(1, frozenset({('PauliZ', <Wires = [1]>, ())})),
-        (1, frozenset({('PauliX', <Wires = [1]>, ()), ('PauliX', <Wires = [0]>, ())}))}
+        {(1, frozenset({('PauliX', <Wires = [1]>, ()), ('PauliX', <Wires = [0]>, ())})),
+         (1, frozenset({('PauliZ', <Wires = [0]>, ())}))}
         """
         data = set()
 
diff --git a/setup.py b/setup.py
index 6cd0d0fdf..e6963555c 100644
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,8 @@ requirements = [
     "appdirs",
     "semantic_version==2.6",
     "autoray",
-    "cachetools"
+    "cachetools",
+    "pennylane-lightning>=0.18",
 ]
 
 info = {


Test patch:
diff --git a/tests/devices/test_lightning_qubit.py b/tests/devices/test_lightning_qubit.py
new file mode 100644
index 000000000..0bcc99dde
--- /dev/null
+++ b/tests/devices/test_lightning_qubit.py
@@ -0,0 +1,38 @@
+# Copyright 2021 Xanadu Quantum Technologies Inc.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+Tests for the accessibility of the Lightning-Qubit device
+"""
+import pennylane as qml
+import numpy as np
+
+
+def test_integration():
+    """Test that the execution of lightning.qubit is possible and agrees with default.qubit"""
+    wires = 2
+    layers = 2
+    dev_l = qml.device("lightning.qubit", wires=wires)
+    dev_d = qml.device("default.qubit", wires=wires)
+
+    def circuit(weights):
+        qml.templates.StronglyEntanglingLayers(weights, wires=range(wires))
+        return qml.expval(qml.PauliZ(0))
+
+    weights = qml.init.strong_ent_layers_normal(layers, wires, seed=1967)
+
+    qn_l = qml.QNode(circuit, dev_l)
+    qn_d = qml.QNode(circuit, dev_d)
+
+    assert np.allclose(qn_l(weights), qn_d(weights))
+    assert np.allclose(qml.grad(qn_l)(weights), qml.grad(qn_d)(weights))
diff --git a/tests/test_device.py b/tests/test_device.py
index 85518f218..4771ad21e 100644
--- a/tests/test_device.py
+++ b/tests/test_device.py
@@ -166,18 +166,41 @@ def mock_device(monkeypatch):
         yield get_device
 
 
-def test_shot_vector_property():
-    dev = qml.device("default.qubit", wires=1, shots=[1, 3, 3, 4, 4, 4, 3])
-    shot_vector = dev.shot_vector
-    assert len(shot_vector) == 4
-    assert shot_vector[0].shots == 1
-    assert shot_vector[0].copies == 1
-    assert shot_vector[1].shots == 3
-    assert shot_vector[1].copies == 2
-    assert shot_vector[2].shots == 4
-    assert shot_vector[2].copies == 3
-    assert shot_vector[3].shots == 3
-    assert shot_vector[3].copies == 1
+class TestShotVectors:
+    """Tests passing shot vectors, their validation, and processing."""
+
+    def test_shot_vector_property(self):
+        dev = qml.device("default.qubit", wires=1, shots=[1, 3, 3, 4, 4, 4, 3])
+        shot_vector = dev.shot_vector
+        assert len(shot_vector) == 4
+        assert shot_vector[0].shots == 1
+        assert shot_vector[0].copies == 1
+        assert shot_vector[1].shots == 3
+        assert shot_vector[1].copies == 2
+        assert shot_vector[2].shots == 4
+        assert shot_vector[2].copies == 3
+        assert shot_vector[3].shots == 3
+        assert shot_vector[3].copies == 1
+
+        assert dev.shots == 22
+
+    def test_process_shot_sequence(self):
+        """Tests that the helper `_process_shot_sequence` works as expected."""
+        shot_list = [1, 1, 3]
+        total_shots, shot_vector = qml._device._process_shot_sequence(shot_list)
+
+        assert total_shots == 5
+        assert isinstance(total_shots, int)
+
+        assert len(shot_vector) == 2
+
+        for tup in shot_vector:
+            assert isinstance(tup, qml._device.ShotTuple)
+
+        assert shot_vector[0].shots == 1
+        assert shot_vector[0].copies == 2
+        assert shot_vector[1].shots == 3
+        assert shot_vector[1].copies == 1
 
 
 class TestDeviceSupportedLogic: