From e761e1842b6aec18a57452c1052b5dabc6d819ec Mon Sep 17 00:00:00 2001 From: kenya-sk <30319295+kenya-sk@users.noreply.github.com> Date: Fri, 12 Apr 2024 06:16:13 +0900 Subject: [PATCH] add type hint for unimplemented operator function (#5490) ### Before submitting Please complete the following checklist when submitting a PR: - [x] All new features must include a unit test. If you've fixed a bug or added code that should be tested, add a test to the test directory! - [x] All new functions and code must be clearly commented and documented. If you do make documentation changes, make sure that the docs build and render correctly by running `make docs`. - [x] Ensure that the test suite passes, by running `make test`. - [x] Add a new entry to the `doc/releases/changelog-dev.md` file, summarizing the change, and including a link back to the PR. - [x] The PennyLane source code conforms to [PEP8 standards](https://www.python.org/dev/peps/pep-0008/). We check all of our code against [Pylint](https://www.pylint.org/). To lint modified files, simply `pip install pylint`, and then run `pylint pennylane/path/to/file.py`. When all the above are checked, delete everything above the dashed line and fill in the pull request template. ------------------------------------------------------------------------------------------------------------ **Context:** The abstract class Operator defines several methods that need to be implemented in subclasses. While these methods are defined to raise errors before implementation in the abstract class, this leads to linting errors. Therefore, appropriate type hints were added after implementation. **Description of the Change:** Add type hints to the following methods. - `compute_matrix` - `matrix` - `compute_sparse_matrix` - `sparse_matrix` - `compute_eigvals` - `decomposition` - `compute_decomposition` - `compute_diagonalizing_gates` - `single_qubit_rot_angles` - `compute_kraus_matrices` **Benefits:** Improve the interpretability of the linter **Possible Drawbacks:** **Related GitHub Issues:** Add type hints to pennylane.operation.Operator #5398 --------- Co-authored-by: Christina Lee --- doc/releases/changelog-dev.md | 4 ++++ pennylane/operation.py | 28 ++++++++++++++++------------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 0adbb3bca7a..2713c21fc81 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -238,6 +238,9 @@ [(#5256)](https://github.com/PennyLaneAI/pennylane/pull/5256) [(#5395)](https://github.com/PennyLaneAI/pennylane/pull/5395) +* Add type hints for unimplemented methods of the abstract class `Operator`. + [(#5490)](https://github.com/PennyLaneAI/pennylane/pull/5490) + * A clear error message is added in `KerasLayer` when using the newest version of TensorFlow with Keras 3 (which is not currently compatible with `KerasLayer`), linking to instructions to enable Keras 2. [(#5488)](https://github.com/PennyLaneAI/pennylane/pull/5488) @@ -411,6 +414,7 @@ Korbinian Kottmann, Christina Lee, Vincent Michaud-Rioux, Mudit Pandey, +Kenya Sakka, Jay Soni, Matthew Silverman, David Wierichs. diff --git a/pennylane/operation.py b/pennylane/operation.py index 7ed697f8635..4a3fe4c726b 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -248,12 +248,12 @@ import itertools import warnings from enum import IntEnum -from typing import List +from typing import List, Tuple from contextlib import contextmanager import numpy as np from numpy.linalg import multi_dot -from scipy.sparse import coo_matrix, eye, kron +from scipy.sparse import coo_matrix, csr_matrix, eye, kron import pennylane as qml from pennylane.math import expand_matrix @@ -748,7 +748,7 @@ def __hash__(self): return self.hash @staticmethod - def compute_matrix(*params, **hyperparams): # pylint:disable=unused-argument + def compute_matrix(*params, **hyperparams) -> TensorLike: # pylint:disable=unused-argument r"""Representation of the operator as a canonical matrix in the computational basis (static method). The canonical matrix is the textbook matrix representation that does not consider wires. @@ -774,7 +774,7 @@ def has_matrix(cls): """ return cls.compute_matrix != Operator.compute_matrix or cls.matrix != Operator.matrix - def matrix(self, wire_order=None): + def matrix(self, wire_order=None) -> TensorLike: r"""Representation of the operator as a matrix in the computational basis. If ``wire_order`` is provided, the numerical representation considers the position of the @@ -809,7 +809,9 @@ def matrix(self, wire_order=None): return expand_matrix(canonical_matrix, wires=self.wires, wire_order=wire_order) @staticmethod - def compute_sparse_matrix(*params, **hyperparams): # pylint:disable=unused-argument + def compute_sparse_matrix( + *params, **hyperparams + ) -> csr_matrix: # pylint:disable=unused-argument r"""Representation of the operator as a sparse matrix in the computational basis (static method). The canonical matrix is the textbook matrix representation that does not consider wires. @@ -827,7 +829,7 @@ def compute_sparse_matrix(*params, **hyperparams): # pylint:disable=unused-argu """ raise SparseMatrixUndefinedError - def sparse_matrix(self, wire_order=None): + def sparse_matrix(self, wire_order=None) -> csr_matrix: r"""Representation of the operator as a sparse matrix in the computational basis. If ``wire_order`` is provided, the numerical representation considers the position of the @@ -852,7 +854,7 @@ def sparse_matrix(self, wire_order=None): return expand_matrix(canonical_sparse_matrix, wires=self.wires, wire_order=wire_order) @staticmethod - def compute_eigvals(*params, **hyperparams): + def compute_eigvals(*params, **hyperparams) -> TensorLike: r"""Eigenvalues of the operator in the computational basis (static method). If :attr:`diagonalizing_gates` are specified and implement a unitary :math:`U^{\dagger}`, @@ -1268,7 +1270,7 @@ def has_decomposition(cls): or cls.decomposition != Operator.decomposition ) - def decomposition(self): + def decomposition(self) -> List["Operator"]: r"""Representation of the operator as a product of other operators. .. math:: O = O_1 O_2 \dots O_n @@ -1285,7 +1287,7 @@ def decomposition(self): ) @staticmethod - def compute_decomposition(*params, wires=None, **hyperparameters): + def compute_decomposition(*params, wires=None, **hyperparameters) -> List["Operator"]: r"""Representation of the operator as a product of other operators (static method). .. math:: O = O_1 O_2 \dots O_n. @@ -1324,7 +1326,7 @@ def has_diagonalizing_gates(cls): @staticmethod def compute_diagonalizing_gates( *params, wires, **hyperparams - ): # pylint: disable=unused-argument + ) -> List["Operator"]: # pylint: disable=unused-argument r"""Sequence of gates that diagonalize the operator in the computational basis (static method). Given the eigendecomposition :math:`O = U \Sigma U^{\dagger}` where @@ -1719,7 +1721,7 @@ def control_wires(self): # pragma: no cover """ return Wires([]) - def single_qubit_rot_angles(self): + def single_qubit_rot_angles(self) -> Tuple[float, float, float]: r"""The parameters required to implement a single-qubit gate as an equivalent ``Rot`` gate, up to a global phase. @@ -1814,7 +1816,9 @@ class Channel(Operation, abc.ABC): @staticmethod @abc.abstractmethod - def compute_kraus_matrices(*params, **hyperparams): # pylint:disable=unused-argument + def compute_kraus_matrices( + *params, **hyperparams + ) -> List[np.ndarray]: # pylint:disable=unused-argument """Kraus matrices representing a quantum channel, specified in the computational basis.