Skip to content

Commit

Permalink
Use lazy-importing of qnn module and remove Python 3.6 (#1228)
Browse files Browse the repository at this point in the history
* Revert "Add deprecation warning to qnn module (#1170)"

This reverts commit 816885a.

* Remove Python 3.6 and add 3.9

* Add lazy loading

* Add tests

* Add to changelog

* Mention 3.9

* Update CI

* Add to docs

* Fix

* Fix note

* Allow importing of module

* Change order

* Change back

* Update test

* Fix

* full stop

* black

* Apply suggestions from code review

Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com>

Co-authored-by: Josh Izaac <josh146@gmail.com>
  • Loading branch information
trbromley and josh146 committed May 6, 2021
1 parent 6e8efa8 commit 9f01932
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 18 deletions.
3 changes: 3 additions & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)

<h3>Breaking changes</h3>

* Removes support for Python 3.6 and begin testing for Python 3.9.
[(#1228)](https://github.com/XanaduAI/pennylane/pull/1228)

<h3>Bug fixes</h3>

<h3>Documentation</h3>
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
strategy:
matrix:
config:
- {python-version: 3.6, interfaces: ['tf']}
- {python-version: 3.7, interfaces: ['tf']}
- {python-version: 3.7, interfaces: ['torch']}
- {python-version: 3.8, interfaces: ['tf', 'torch', 'jax']}
- {python-version: 3.8, interfaces: []}
- {python-version: 3.9, interfaces: []}

steps:
- name: Cancel Previous Runs
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ formats:

# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.6
version: 3.8
install:
- requirements: doc/requirements.txt
- requirements: qchem/requirements.txt
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@

## Installation

PennyLane requires Python version 3.6 and above. Installation of PennyLane, as well as all
PennyLane requires Python version 3.7 and above. Installation of PennyLane, as well as all
dependencies, can be done using pip:

```console
Expand Down
90 changes: 90 additions & 0 deletions doc/_templates/autosummary/class_no_inherited.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{{ fullname | replace("pennylane", "qml") }}
{{ underline }}

.. autoclass:: {{ fullname }}
:show-inheritance:

{% if '__init__' in methods %}
{% set caught_result = methods.remove('__init__') %}
{% endif %}

{% block attributes_documentation %}
{% if attributes %}

.. raw:: html

<a class="attr-details-header collapse-header" data-toggle="collapse" href="#attrDetails" aria-expanded="false" aria-controls="attrDetails">
<h2 style="font-size: 24px;">
<i class="fas fa-angle-down rotate" style="float: right;"></i> Attributes
</h2>
</a>
<div class="collapse" id="attrDetails">

{% block attributes_summary %}
{% if attributes %}

.. autosummary::
:nosignatures:
{% for item in attributes %}
~{{ name }}.{{ item }}
{%- endfor %}

{% endif %}
{% endblock %}

{% for item in attributes %}
{%- if item not in inherited_members %}
.. autoattribute:: {{ item }}
{%- endif %}
{%- endfor %}

.. raw:: html

</div>

{% endif %}
{% endblock %}

{% block methods_documentation %}
{% if methods %}

.. raw:: html

<a class="meth-details-header collapse-header" data-toggle="collapse" href="#methDetails" aria-expanded="false" aria-controls="methDetails">
<h2 style="font-size: 24px;">
<i class="fas fa-angle-down rotate" style="float: right;"></i> Methods
</h2>
</a>
<div class="collapse" id="methDetails">

{% block methods_summary %}
{% if methods %}

.. autosummary::
{% for item in methods %}
~{{ name }}.{{ item }}
{%- endfor %}

{% endif %}
{% endblock %}

{% for item in methods %}
{%- if item not in inherited_members %}
.. automethod:: {{ item }}
{%- endif %}
{%- endfor %}

.. raw:: html

</div>

{% endif %}
{% endblock %}

.. raw:: html

<script type="text/javascript">
$(".collapse-header").click(function () {
$(this).children('h2').eq(0).children('i').eq(0).toggleClass("up");
})
</script>
5 changes: 1 addition & 4 deletions doc/code/qml_qnn.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,4 @@ qml.qnn

.. currentmodule:: pennylane.qnn

.. automodapi:: pennylane.qnn
:no-heading:
:no-inheritance-diagram:
:no-inherited-members:
.. automodule:: pennylane.qnn
2 changes: 1 addition & 1 deletion doc/development/guide/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Dependencies

PennyLane requires the following libraries be installed:

* `Python <http://python.org/>`_ >= 3.6
* `Python <http://python.org/>`_ >= 3.7

as well as the following Python packages:

Expand Down
39 changes: 35 additions & 4 deletions pennylane/qnn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,40 @@
# 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.
"""This module contains classes and functions for constructing quantum neural networks from QNodes."""
"""
This module contains functionality for converting PennyLane QNodes into layers that are compatible
with Keras and PyTorch.
import pennylane.qnn.cost
.. note::
from .keras import KerasLayer
from .torch import TorchLayer
Check out our :doc:`Keras <demos/tutorial_qnn_module_tf>` and
:doc:`Torch <demos/tutorial_qnn_module_torch>` tutorials for further details.
.. rubric:: Classes
.. autosummary::
:toctree: api
:nosignatures:
:template: autosummary/class_no_inherited.rst
~KerasLayer
~TorchLayer
"""
import importlib

from . import cost

class_map = {"KerasLayer": "keras", "TorchLayer": "torch"}
mods = ("keras", "torch")


def __getattr__(name):
"""Allow for lazy-loading of KerasLayer and TorchLayer so that TensorFlow and PyTorch are not
automatically loaded with PennyLane"""
if name in class_map:
mod = importlib.import_module("." + class_map[name], __name__)
return getattr(mod, name)
if name in mods:
return importlib.import_module("." + name, __name__)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
5 changes: 3 additions & 2 deletions pennylane/qnn/keras.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@


class KerasLayer(Layer):
"""Converts a :func:`~.QNode` to a Keras
"""KerasLayer(qnode, weight_shapes: dict, output_dim, weight_specs: Optional[dict] = None, **kwargs)
Converts a :func:`~.QNode` to a Keras
`Layer <https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer>`__.
The result can be used within the Keras
Expand All @@ -49,7 +50,7 @@ class KerasLayer(Layer):
specifications for weights used in the QNode, such as the method of parameter
initialization. This specification is provided as a dictionary with keys given by the
arguments of the `add_weight()
<https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#add_weight>`__.
<https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#add_weight>`__
method and values being the corresponding specification.
**kwargs: additional keyword arguments passed to the Layer_ base class
Expand Down
2 changes: 1 addition & 1 deletion qchem/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Scientific/Engineering :: Physics",
]
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3 :: Only',
"Topic :: Scientific/Engineering :: Physics"
]
Expand Down
9 changes: 8 additions & 1 deletion tests/qnn/test_keras.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
import pytest

import pennylane as qml
from pennylane.qnn.keras import KerasLayer

KerasLayer = qml.qnn.keras.KerasLayer

tf = pytest.importorskip("tensorflow", minversion="2")

Expand Down Expand Up @@ -609,3 +610,9 @@ def test_model_save_weights_dm(self, model_dm, n_qubits, tmpdir):
assert np.allclose(prediction, prediction_loaded)
for i, w in enumerate(weights):
assert np.allclose(w, weights_loaded[i])


def test_no_attribute():
"""Test that the qnn module raises an AttributeError if accessing an unavailable attribute"""
with pytest.raises(AttributeError, match="module 'pennylane.qnn' has no attribute 'random'"):
qml.qnn.random

0 comments on commit 9f01932

Please sign in to comment.