From 58c302380b8a566e5e75350b3397f9573d357999 Mon Sep 17 00:00:00 2001 From: Maren Mahsereci <42842079+mmahsereci@users.noreply.github.com> Date: Wed, 19 Jan 2022 20:15:53 +0100 Subject: [PATCH] pylint cleanup quad (#610) --- src/probnum/quad/_bayesquad.py | 27 ++++---- .../quad/kernel_embeddings/_expquad_gauss.py | 11 ++-- .../kernel_embeddings/_expquad_lebesgue.py | 11 ++-- .../kernel_embeddings/_kernel_embedding.py | 31 ++++++--- .../quad/solvers/bayesian_quadrature.py | 63 ++++++++++++------- .../solvers/belief_updates/_belief_update.py | 5 +- src/probnum/quad/solvers/bq_state.py | 7 ++- src/probnum/quad/solvers/policies/_policy.py | 3 +- .../_bq_stopping_criterion.py | 3 +- .../stopping_criteria/_rel_mean_change.py | 11 ++-- tox.ini | 4 +- 11 files changed, 112 insertions(+), 64 deletions(-) diff --git a/src/probnum/quad/_bayesquad.py b/src/probnum/quad/_bayesquad.py index 27b227ced..2af278162 100644 --- a/src/probnum/quad/_bayesquad.py +++ b/src/probnum/quad/_bayesquad.py @@ -8,10 +8,11 @@ """ import warnings -from typing import Callable, Dict, Optional, Tuple, Union +from typing import Callable, Optional, Tuple, Union import numpy as np +from probnum.quad.solvers.bq_state import BQInfo from probnum.randprocs.kernels import Kernel from probnum.randvars import Normal from probnum.typing import FloatLike, IntLike @@ -20,7 +21,6 @@ from .solvers import BayesianQuadrature -# pylint: disable=too-many-arguments, no-else-raise def bayesquad( fun: Callable, input_dim: int, @@ -35,8 +35,9 @@ def bayesquad( rel_tol: Optional[FloatLike] = None, batch_size: Optional[IntLike] = 1, rng: Optional[np.random.Generator] = np.random.default_rng(), -) -> Tuple[Normal, Dict]: - r"""Infer the solution of the uni- or multivariate integral :math:`\int_\Omega f(x) d \mu(x)` +) -> Tuple[Normal, BQInfo]: + r"""Infer the solution of the uni- or multivariate integral + :math:`\int_\Omega f(x) d \mu(x)` on a hyper-rectangle :math:`\Omega = [a_1, b_1] \times \cdots \times [a_D, b_D]`. Bayesian quadrature (BQ) infers integrals of the form @@ -47,12 +48,12 @@ def bayesquad( :math:`\Omega \subset \mathbb{R}^D` against a measure :math:`\mu: \mathbb{R}^D \mapsto \mathbb{R}`. - Bayesian quadrature methods return a probability distribution over the solution :math:`F` with - uncertainty arising from finite computation (here a finite number of function evaluations). - They start out with a random process encoding the prior belief about the function :math:`f` - to be integrated. Conditioned on either existing or acquired function evaluations according to a - policy, they update the belief on :math:`f`, which is translated into a posterior measure over - the integral :math:`F`. + Bayesian quadrature methods return a probability distribution over the solution + :math:`F` with uncertainty arising from finite computation (here a finite number + of function evaluations). They start out with a random process encoding the prior + belief about the function :math:`f` to be integrated. Conditioned on either existing + or acquired function evaluations according to a policy, they update the belief on + :math:`f`, which is translated into a posterior measure over the integral :math:`F`. See Briol et al. [1]_ for a review on Bayesian quadrature. Parameters @@ -132,7 +133,7 @@ def bayesquad( if domain is not None: if isinstance(measure, GaussianMeasure): raise ValueError("GaussianMeasure cannot be used with finite bounds.") - elif isinstance(measure, LebesgueMeasure): + if isinstance(measure, LebesgueMeasure): warnings.warn( "Both domain and a LebesgueMeasure are specified. The domain " "information will be ignored." @@ -165,7 +166,7 @@ def bayesquad_from_data( Tuple[Union[np.ndarray, FloatLike], Union[np.ndarray, FloatLike]] ] = None, measure: Optional[IntegrationMeasure] = None, -) -> Tuple[Normal, Dict]: +) -> Tuple[Normal, BQInfo]: r"""Infer the value of an integral from a given set of nodes and function evaluations. @@ -219,7 +220,7 @@ def bayesquad_from_data( if domain is not None: if isinstance(measure, GaussianMeasure): raise ValueError("GaussianMeasure cannot be used with finite bounds.") - elif isinstance(measure, LebesgueMeasure): + if isinstance(measure, LebesgueMeasure): warnings.warn( "Both domain and a LebesgueMeasure are specified. The domain " "information will be ignored." diff --git a/src/probnum/quad/kernel_embeddings/_expquad_gauss.py b/src/probnum/quad/kernel_embeddings/_expquad_gauss.py index da2d46525..5c626b9c9 100644 --- a/src/probnum/quad/kernel_embeddings/_expquad_gauss.py +++ b/src/probnum/quad/kernel_embeddings/_expquad_gauss.py @@ -8,8 +8,6 @@ from probnum.quad._integration_measures import GaussianMeasure from probnum.randprocs.kernels import ExpQuad -# pylint: disable=invalid-name - def _kernel_mean_expquad_gauss( x: np.ndarray, kernel: ExpQuad, measure: GaussianMeasure @@ -20,7 +18,8 @@ def _kernel_mean_expquad_gauss( Parameters ---------- x : - *shape=(n_eval, input_dim)* -- n_eval locations where to evaluate the kernel mean. + *shape=(n_eval, input_dim)* -- n_eval locations where to evaluate the kernel + mean. kernel : Instance of an ExpQuad kernel. measure : @@ -28,9 +27,9 @@ def _kernel_mean_expquad_gauss( Returns ------- - k_mean : + kernel_mean : *shape (n_eval,)* -- The kernel integrated w.r.t. its first argument, - evaluated at locations x. + evaluated at locations ``x``. """ input_dim = kernel.input_dim @@ -66,7 +65,7 @@ def _kernel_variance_expquad_gauss(kernel: ExpQuad, measure: GaussianMeasure) -> Returns ------- - k_var : + kernel_variance : The kernel integrated w.r.t. both arguments. """ input_dim = kernel.input_dim diff --git a/src/probnum/quad/kernel_embeddings/_expquad_lebesgue.py b/src/probnum/quad/kernel_embeddings/_expquad_lebesgue.py index 5e0006f1c..78ae40447 100644 --- a/src/probnum/quad/kernel_embeddings/_expquad_lebesgue.py +++ b/src/probnum/quad/kernel_embeddings/_expquad_lebesgue.py @@ -1,7 +1,7 @@ """Kernel embedding of exponentiated quadratic kernel with Lebesgue integration measure.""" -# pylint: disable=no-name-in-module, invalid-name +# pylint: disable=no-name-in-module import numpy as np from scipy.special import erf @@ -19,7 +19,8 @@ def _kernel_mean_expquad_lebesgue( Parameters ---------- x : - *shape (n_eval, input_dim)* -- n_eval locations where to evaluate the kernel mean. + *shape (n_eval, input_dim)* -- n_eval locations where to evaluate the kernel + mean. kernel : Instance of an ExpQuad kernel. measure : @@ -27,9 +28,9 @@ def _kernel_mean_expquad_lebesgue( Returns ------- - k_mean : + kernel_mean : *shape=(n_eval,)* -- The kernel integrated w.r.t. its first argument, - evaluated at locations x. + evaluated at locations ``x``. """ input_dim = kernel.input_dim @@ -59,7 +60,7 @@ def _kernel_variance_expquad_lebesgue( Returns ------- - k_var : + kernel_variance : The kernel integrated w.r.t. both arguments. """ diff --git a/src/probnum/quad/kernel_embeddings/_kernel_embedding.py b/src/probnum/quad/kernel_embeddings/_kernel_embedding.py index 621d71d8f..6c3b6d9c1 100644 --- a/src/probnum/quad/kernel_embeddings/_kernel_embedding.py +++ b/src/probnum/quad/kernel_embeddings/_kernel_embedding.py @@ -27,6 +27,12 @@ class KernelEmbedding: Instance of a kernel. measure: Instance of an integration measure. + + Raises + ------ + ValueError + If the input dimension of the kernel does not match the input dimension of the + measure. """ def __init__(self, kernel: Kernel, measure: IntegrationMeasure) -> None: @@ -45,20 +51,20 @@ def __init__(self, kernel: Kernel, measure: IntegrationMeasure) -> None: kernel=self.kernel, measure=self.measure ) - # pylint: disable=invalid-name def kernel_mean(self, x: np.ndarray) -> np.ndarray: """Kernel mean w.r.t. its first argument against the integration measure. Parameters ---------- x : - *shape=(n_eval, input_dim)* -- n_eval locations where to evaluate the kernel mean. + *shape=(n_eval, input_dim)* -- n_eval locations where to evaluate the + kernel mean. Returns ------- - k_mean : + kernel_mean : *shape=(n_eval,)* -- The kernel integrated w.r.t. its first argument, - evaluated at locations x. + evaluated at locations ``x``. """ return self._kmean(x=x, kernel=self.kernel, measure=self.measure) @@ -67,7 +73,7 @@ def kernel_variance(self) -> float: Returns ------- - k_var : + kernel_variance : The kernel integrated w.r.t. both arguments. """ return self._kvar(kernel=self.kernel, measure=self.measure) @@ -87,15 +93,24 @@ def _get_kernel_embedding( Returns ------- - An instance of _KernelEmbedding. + kernel_mean : + The kernel mean function. + kernel_variance : + The kernel variance function. + + Raises + ------ + NotImplementedError + If the given kernel is unknown. + NotImplementedError + If the kernel embedding of the kernel-measure pair is unknown. """ # Exponentiated quadratic kernel if isinstance(kernel, ExpQuad): - # pylint: disable=no-else-return if isinstance(measure, GaussianMeasure): return _kernel_mean_expquad_gauss, _kernel_variance_expquad_gauss - elif isinstance(measure, LebesgueMeasure): + if isinstance(measure, LebesgueMeasure): return _kernel_mean_expquad_lebesgue, _kernel_variance_expquad_lebesgue raise NotImplementedError diff --git a/src/probnum/quad/solvers/bayesian_quadrature.py b/src/probnum/quad/solvers/bayesian_quadrature.py index 9729ccc6c..26e228dd0 100644 --- a/src/probnum/quad/solvers/bayesian_quadrature.py +++ b/src/probnum/quad/solvers/bayesian_quadrature.py @@ -98,6 +98,19 @@ def from_problem( Batch size used in node acquisition. rng : The random number generator. + + Returns + ------- + BayesianQuadrature + An instance of this class. + + Raises + ------ + ValueError + If Bayesian Monte Carlo ('bmc') is selected as ``policy`` and no random + number generator (``rng``) is given. + NotImplementedError + If an unknown ``policy`` is given. """ # Set up integration measure if measure is None: @@ -125,8 +138,8 @@ def from_problem( "Policies other than random sampling are not available at the moment." ) - # Set stopping criteria - # If multiple stopping criteria are given, BQ stops once the first criterion is fulfilled. + # Set stopping criteria: If multiple stopping criteria are given, BQ stops + # once the first criterion is fulfilled. def _stopcrit_or(sc1, sc2): if sc1 is None: return sc2 @@ -147,7 +160,8 @@ def _stopcrit_or(sc1, sc2): _stopping_criterion, RelativeMeanChange(rel_tol) ) - # If no stopping criteria are given, use some default values (these are arbitrary values) + # If no stopping criteria are given, use some default values + # (these are arbitrary values) if _stopping_criterion is None: _stopping_criterion = IntegralVarianceTolerance(var_tol=1e-6) | MaxNevals( max_nevals=input_dim * 25 @@ -167,13 +181,13 @@ def has_converged(self, bq_state: BQState) -> bool: Parameters ---------- bq_state: - State of the Bayesian quadrature methods. Contains all necessary information about the - problem and the computation. + State of the Bayesian quadrature methods. Contains all necessary + information about the problem and the computation. Returns ------- - has_converged: - Whether or not the solver has converged. + has_converged : + Whether the solver has converged. """ _has_converged = self.stopping_criterion(bq_state) @@ -192,7 +206,8 @@ def bq_iterator( ) -> Tuple[Normal, np.ndarray, np.ndarray, BQState]: """Generator that implements the iteration of the BQ method. - This function exposes the state of the BQ method one step at a time while running the loop. + This function exposes the state of the BQ method one step at a time while + running the loop. Parameters ---------- @@ -208,23 +223,22 @@ def bq_iterator( integral_belief: Current belief about the integral. bq_state: - State of the Bayesian quadrature methods. Contains all necessary information about the - problem and the computation. + State of the Bayesian quadrature methods. Contains all necessary information + about the problem and the computation. - Returns - ------- - integral_belief: + Yields + ------ + new_integral_belief : Updated belief about the integral. - new_nodes: + new_nodes : *shape=(n_new_eval, input_dim)* -- The new location(s) at which ``new_fun_evals`` are available found during the iteration. - new_fun_evals: + new_fun_evals : *shape=(n_new_eval,)* -- The function evaluations at the new locations ``new_nodes``. - bq_state: + new_bq_state : Updated state of the Bayesian quadrature methods. """ - # pylint: disable=missing-yield-doc # Setup if bq_state is None: @@ -293,8 +307,9 @@ def integrate( ) -> Tuple[Normal, BQState]: """Integrate the function ``fun``. - ``fun`` may be analytically given, or numerically in terms of ``fun_evals`` at fixed nodes. - This function calls the generator ``bq_iterator`` until the first stopping criterion is met. + ``fun`` may be analytically given, or numerically in terms of ``fun_evals`` at + fixed nodes. This function calls the generator ``bq_iterator`` until the first + stopping criterion is met. Parameters ---------- @@ -310,10 +325,16 @@ def integrate( Returns ------- - integral_belief: + integral_belief : Posterior belief about the integral. - bq_state: + bq_state : Final state of the Bayesian quadrature method. + + Raises + ------ + ValueError + If neither the integrand function (``fun``) nor integrand evaluations + (``fun_evals``) are given. """ if fun is None and fun_evals is None: raise ValueError("You need to provide a function to be integrated!") diff --git a/src/probnum/quad/solvers/belief_updates/_belief_update.py b/src/probnum/quad/solvers/belief_updates/_belief_update.py index f6cd0e0d3..26023d9a6 100644 --- a/src/probnum/quad/solvers/belief_updates/_belief_update.py +++ b/src/probnum/quad/solvers/belief_updates/_belief_update.py @@ -45,7 +45,8 @@ def __call__( Returns ------- updated_belief : - Gaussian integral belief after conditioning on the new nodes and evaluations. + Gaussian integral belief after conditioning on the new nodes and + evaluations. updated_state : Updated version of ``bq_state`` that contains all updated quantities. """ @@ -110,7 +111,7 @@ def _solve_gram(gram: np.ndarray, rhs: np.ndarray) -> np.ndarray: Returns ------- - x: + x : The solution to the linear system :math:`K x = b` """ jitter = 1.0e-6 diff --git a/src/probnum/quad/solvers/bq_state.py b/src/probnum/quad/solvers/bq_state.py index 68b6e51a7..a70998fc7 100644 --- a/src/probnum/quad/solvers/bq_state.py +++ b/src/probnum/quad/solvers/bq_state.py @@ -9,7 +9,7 @@ from probnum.randprocs.kernels import Kernel from probnum.randvars import Normal -# pylint: disable=too-few-public-methods, too-many-instance-attributes, too-many-arguments +# pylint: disable=too-few-public-methods,too-many-instance-attributes,too-many-arguments class BQInfo: @@ -128,6 +128,11 @@ def from_new_data( The Gram matrix of the given nodes. kernel_means : The kernel means at the given nodes. + + Returns + ------- + bq_state : + An instance of this class. """ return cls( measure=prev_state.measure, diff --git a/src/probnum/quad/solvers/policies/_policy.py b/src/probnum/quad/solvers/policies/_policy.py index 4cc9d7b86..8ea43de2c 100644 --- a/src/probnum/quad/solvers/policies/_policy.py +++ b/src/probnum/quad/solvers/policies/_policy.py @@ -45,7 +45,8 @@ class RandomPolicy(Policy): ---------- sample_func : The sample function. Needs to have the following interface: - `sample_func(batch_size: int, rng: np.random.Generator)` and return an array of shape (batch_size, n_dim). + `sample_func(batch_size: int, rng: np.random.Generator)` and return an array of + shape (batch_size, n_dim). batch_size : Size of batch of nodes when calling the policy once. """ diff --git a/src/probnum/quad/solvers/stopping_criteria/_bq_stopping_criterion.py b/src/probnum/quad/solvers/stopping_criteria/_bq_stopping_criterion.py index 57052a571..57c6e65c6 100644 --- a/src/probnum/quad/solvers/stopping_criteria/_bq_stopping_criterion.py +++ b/src/probnum/quad/solvers/stopping_criteria/_bq_stopping_criterion.py @@ -10,7 +10,8 @@ class BQStoppingCriterion(StoppingCriterion): r"""Stopping criterion of a Bayesian quadrature method. - Checks whether quantities tracked by the :class:`~probnum.quad.solvers.BQState` meet a desired terminal condition. + Checks whether quantities tracked by the :class:`~probnum.quad.solvers.BQState` + meet a desired terminal condition. See Also -------- diff --git a/src/probnum/quad/solvers/stopping_criteria/_rel_mean_change.py b/src/probnum/quad/solvers/stopping_criteria/_rel_mean_change.py index cb32b89d3..6e923fca6 100644 --- a/src/probnum/quad/solvers/stopping_criteria/_rel_mean_change.py +++ b/src/probnum/quad/solvers/stopping_criteria/_rel_mean_change.py @@ -1,4 +1,5 @@ -"""Stopping criterion based on the relative change of the successive integral estimators.""" +"""Stopping criterion based on the relative change of the successive integral +estimators.""" import numpy as np @@ -13,9 +14,11 @@ class RelativeMeanChange(BQStoppingCriterion): """Stop once the relative change of consecutive integral estimates are smaller than a tolerance. - The stopping criterion is: :math:`|\\hat{F}_{c} - \\hat{F}_{p}|/ |\\hat{F}_{c}| \\leq r` - where :math:`\\hat{F}_{c}` and :math:`\\hat{F}_{p}` are the integral estimates of the current and previous iteration - respectively, and :math:`r` is the relative tolerance. + The stopping criterion is: + :math:`|\\hat{F}_{c} - \\hat{F}_{p}|/ |\\hat{F}_{c}| \\leq r` where + :math:`\\hat{F}_{c}` and :math:`\\hat{F}_{p}` are the integral estimates of the + current and previous iteration respectively, and :math:`r` is the relative + tolerance. Parameters ---------- diff --git a/tox.ini b/tox.ini index 164f66e4c..03d6996ef 100644 --- a/tox.ini +++ b/tox.ini @@ -62,14 +62,14 @@ deps = pylint == 2.9.* ignore_errors = true commands = # Global Linting Pass - pylint src/probnum --disable="no-member,abstract-method,arguments-differ,arguments-renamed,function-redefined,redefined-builtin,redefined-outer-name,too-many-instance-attributes,too-many-arguments,too-many-locals,too-many-lines,too-many-statements,too-many-branches,too-complex,too-few-public-methods,protected-access,unnecessary-pass,unused-variable,unused-argument,attribute-defined-outside-init,no-else-return,no-else-raise,no-self-use,else-if-used,consider-using-from-import,duplicate-code,line-too-long,missing-module-docstring,missing-class-docstring,missing-function-docstring,missing-param-doc,missing-type-doc,missing-raises-doc,useless-param-doc,useless-type-doc,missing-return-doc,missing-return-type-doc" --jobs=0 + pylint src/probnum --disable="no-member,abstract-method,arguments-differ,arguments-renamed,redefined-builtin,redefined-outer-name,too-many-instance-attributes,too-many-arguments,too-many-locals,too-many-lines,too-many-statements,too-many-branches,too-complex,too-few-public-methods,protected-access,unnecessary-pass,unused-variable,unused-argument,attribute-defined-outside-init,no-else-return,no-else-raise,no-self-use,else-if-used,consider-using-from-import,duplicate-code,line-too-long,missing-module-docstring,missing-class-docstring,missing-function-docstring,missing-param-doc,missing-type-doc,missing-raises-doc,useless-param-doc,useless-type-doc,missing-return-doc,missing-return-type-doc,missing-yield-doc" --jobs=0 # Per-package Linting Passes pylint src/probnum/diffeq --disable="redefined-outer-name,too-many-instance-attributes,too-many-arguments,too-many-locals,too-few-public-methods,protected-access,unnecessary-pass,unused-variable,unused-argument,no-else-return,no-else-raise,no-self-use,duplicate-code,line-too-long,missing-function-docstring,missing-param-doc,missing-type-doc,missing-raises-doc,missing-return-doc,missing-return-type-doc" --jobs=0 pylint src/probnum/filtsmooth --disable="no-member,arguments-differ,arguments-renamed,too-many-arguments,too-many-locals,too-few-public-methods,protected-access,unused-variable,unused-argument,no-else-return,no-self-use,duplicate-code,line-too-long,missing-module-docstring,missing-class-docstring,missing-function-docstring,missing-param-doc,missing-type-doc,missing-raises-doc,useless-param-doc,useless-type-doc,missing-return-doc,missing-return-type-doc" --jobs=0 pylint src/probnum/linalg --disable="no-member,abstract-method,arguments-differ,redefined-builtin,too-many-instance-attributes,too-many-arguments,too-many-locals,too-many-lines,too-many-statements,too-many-branches,too-complex,too-few-public-methods,protected-access,unused-argument,attribute-defined-outside-init,no-else-return,no-else-raise,no-self-use,else-if-used,duplicate-code,line-too-long,missing-module-docstring,missing-param-doc,missing-type-doc,missing-raises-doc,missing-return-doc,missing-return-type-doc" --jobs=0 pylint src/probnum/linops --disable="too-many-instance-attributes,too-many-arguments,too-many-locals,protected-access,no-else-return,no-else-raise,else-if-used,line-too-long,missing-class-docstring,missing-function-docstring,missing-raises-doc,missing-return-doc,duplicate-code" --jobs=0 pylint src/probnum/problems --disable="too-many-arguments,too-many-locals,unused-variable,unused-argument,else-if-used,consider-using-from-import,duplicate-code,line-too-long,missing-module-docstring,missing-function-docstring,missing-param-doc,missing-type-doc,missing-raises-doc,missing-return-doc" --jobs=0 - pylint src/probnum/quad --disable="function-redefined,too-many-arguments,else-if-used,line-too-long,missing-module-docstring,missing-function-docstring,missing-raises-doc,missing-return-doc" --jobs=0 + pylint src/probnum/quad --disable="too-many-arguments,missing-module-docstring,missing-return-doc,missing-yield-doc" --jobs=0 pylint src/probnum/randprocs --disable="arguments-differ,arguments-renamed,too-many-instance-attributes,too-many-arguments,too-many-locals,protected-access,unused-argument,no-else-return,duplicate-code,line-too-long,missing-module-docstring,missing-function-docstring,missing-type-doc,missing-raises-doc,useless-param-doc,useless-type-doc,missing-return-doc,missing-return-type-doc" --jobs=0 pylint src/probnum/randprocs/kernels --jobs=0 pylint src/probnum/randvars --disable="too-many-arguments,too-many-locals,too-many-branches,too-few-public-methods,protected-access,unused-argument,no-else-return,duplicate-code,line-too-long,missing-function-docstring,missing-raises-doc,missing-return-doc" --jobs=0