From 9f019322adcd36dac642c72cf232bc77e9a9357e Mon Sep 17 00:00:00 2001 From: Tom Bromley <49409390+trbromley@users.noreply.github.com> Date: Thu, 6 May 2021 00:41:45 -0400 Subject: [PATCH] Use lazy-importing of qnn module and remove Python 3.6 (#1228) * Revert "Add deprecation warning to qnn module (#1170)" This reverts commit 816885aaf5e0e723861142348b3b8479536c0d4b. * 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 --- .github/CHANGELOG.md | 3 + .github/workflows/tests.yml | 4 +- .readthedocs.yml | 2 +- README.md | 2 +- .../autosummary/class_no_inherited.rst | 90 +++++++++++++++++++ doc/code/qml_qnn.rst | 5 +- doc/development/guide/installation.rst | 2 +- pennylane/qnn/__init__.py | 39 +++++++- pennylane/qnn/keras.py | 5 +- qchem/setup.py | 2 +- setup.py | 2 +- tests/qnn/test_keras.py | 9 +- 12 files changed, 147 insertions(+), 18 deletions(-) create mode 100644 doc/_templates/autosummary/class_no_inherited.rst diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 4fc4862f7cd..0a96ba0d4a5 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -117,6 +117,9 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)

Breaking changes

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

Bug fixes

Documentation

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 68a0e7a0f33..5c7e9009bdd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -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 diff --git a/.readthedocs.yml b/.readthedocs.yml index be07007e0ae..6b342476cd6 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -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 diff --git a/README.md b/README.md index 277f91cde1b..65451bb89fa 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/doc/_templates/autosummary/class_no_inherited.rst b/doc/_templates/autosummary/class_no_inherited.rst new file mode 100644 index 00000000000..6811b54bdc3 --- /dev/null +++ b/doc/_templates/autosummary/class_no_inherited.rst @@ -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 + + +
+ + {% 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 + +
+ + {% endif %} + {% endblock %} + + {% block methods_documentation %} + {% if methods %} + + .. raw:: html + + +
+ + {% 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 + +
+ + {% endif %} + {% endblock %} + + .. raw:: html + + diff --git a/doc/code/qml_qnn.rst b/doc/code/qml_qnn.rst index 72b15dbb892..668b8194e8a 100644 --- a/doc/code/qml_qnn.rst +++ b/doc/code/qml_qnn.rst @@ -3,7 +3,4 @@ qml.qnn .. currentmodule:: pennylane.qnn -.. automodapi:: pennylane.qnn - :no-heading: - :no-inheritance-diagram: - :no-inherited-members: +.. automodule:: pennylane.qnn diff --git a/doc/development/guide/installation.rst b/doc/development/guide/installation.rst index ffc3b8a5ca4..d7c0c43bdc3 100644 --- a/doc/development/guide/installation.rst +++ b/doc/development/guide/installation.rst @@ -6,7 +6,7 @@ Dependencies PennyLane requires the following libraries be installed: -* `Python `_ >= 3.6 +* `Python `_ >= 3.7 as well as the following Python packages: diff --git a/pennylane/qnn/__init__.py b/pennylane/qnn/__init__.py index 56c20a600eb..77a0567e7cf 100644 --- a/pennylane/qnn/__init__.py +++ b/pennylane/qnn/__init__.py @@ -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 ` and + :doc:`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}") diff --git a/pennylane/qnn/keras.py b/pennylane/qnn/keras.py index f7b6f108614..5a15a4f21a2 100644 --- a/pennylane/qnn/keras.py +++ b/pennylane/qnn/keras.py @@ -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 `__. The result can be used within the Keras @@ -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() - `__. + `__ method and values being the corresponding specification. **kwargs: additional keyword arguments passed to the Layer_ base class diff --git a/qchem/setup.py b/qchem/setup.py index 18618fbacf8..6c54a2270d6 100644 --- a/qchem/setup.py +++ b/qchem/setup.py @@ -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", ] diff --git a/setup.py b/setup.py index d614980e685..7e4d660fb75 100644 --- a/setup.py +++ b/setup.py @@ -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" ] diff --git a/tests/qnn/test_keras.py b/tests/qnn/test_keras.py index e0f0cc7b520..227941e53f7 100644 --- a/tests/qnn/test_keras.py +++ b/tests/qnn/test_keras.py @@ -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") @@ -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