geometric_kernels.spaces.eigenfunctions ======================================= .. py:module:: geometric_kernels.spaces.eigenfunctions .. autoapi-nested-parse:: This module provides base classes for storing or evaluating eigenfunctions of the Laplacian, or certain combinations thereof (see the note below). .. note:: Sometimes, when relations analogous to the :doc:`addition theorem ` on the sphere are available, it is much more efficient to use certain sums of outer products of eigenfunctions instead of the eigenfunctions themselves. For this, we offer :class:`EigenfunctionsWithAdditionTheorem`. Importantly, it is permitted to _only_ provide the computational routines for these "certain sums", lacking the actual capability to compute the eigenfunctions themselves. This is important because for compact Lie groups, for example, computing eigenfunctions is more involved and less efficient than computing the "certain sums", called characters in this case. This is also relevant for hyperspheres of higher dimension: in this case, the eigenfunctions (spherical harmonics) are much more cumbersome than the "certain sums" (zonal spherical harmonics). Module Contents --------------- .. py:class:: Eigenfunctions Bases: :py:obj:`abc.ABC` Abstract base class providing an interface for working with eigenfunctions. We denote the basis of eigenfunctions represented by an instance of this class by $[f_j]_{j=0}^{J-1}$. We assume it to be partitioned into *levels* (see :class:`~.kernels.MaternKarhunenLoeveKernel` on how they are used). Specifically, we call the sets $[f_{l s}]_{s=1}^{d_l}$ *levels* if .. math:: [f_j]_{j=0}^{J-1} = \bigcup_{l=0}^{L-1}[f_{l s}]_{s=1}^{d_l} such that all the eigenfunctions $f_{l s}$ with the same index $l$ correspond to the same eigenvalue $\lambda_l$. Note, however, that $\lambda_l$ are not required to be unique: it is possible that for some $l,l'$, $\lambda_l = \lambda_{l'}$. .. note:: There is often more than one way to choose a partition into levels. Trivially, you can always correspond a level to each individual eigenfunction. Alternatively, you can partition $[f_j]_{j=0}^{J-1}$ into the maximal subsets corresponding to the same eigenvalue (into the *full eigenspaces*). There are also often plenty of possibilities in between these two extremes. Importantly, subclasses of this class do not necessarily have to allow computing the individual eigenfunctions (i.e. implement the method :meth:`__call__`). The only methods that subclasses *have to* implement are :meth:`phi_product` and its close relative :meth:`phi_product_diag`. These output the sums of outer products of eigenfunctions for all levels: .. math:: \sum_{s=1}^{d_l} f_{l s}(x_1) f_{l s}(x_2) for all $0 \leq l < L$, and all pairs $x_1$, $x_2$ provided as inputs. .. py:method:: __call__(X, **kwargs) :abstractmethod: Evaluate the individual eigenfunctions at a batch of input locations. :param X: Points to evaluate the eigenfunctions at, an array of shape [N, ], where N is the number of points and is the shape of the arrays that represent the points in a given space. :param ``**kwargs``: Any additional parameters. :return: An [N, J]-shaped array, where `J` is the number of eigenfunctions. .. py:method:: num_eigenfunctions_per_level() :abstractmethod: The number of eigenfunctions per level: list of $d_l$, $0 \leq l < L$. .. py:method:: phi_product(X, X2 = None, **kwargs) :abstractmethod: Computes the .. math:: \sum_{s=1}^{d_l} f_{l s}(x_1) f_{l s}(x_2) for all $x_1$ in `X`, all $x_2$ in `X2`, and $0 \leq l < L$. :param X: The first of the two batches of points to evaluate the phi product at. An array of shape [N, ], where N is the number of points and is the shape of the arrays that represent the points in a given space. :param X2: The second of the two batches of points to evaluate the phi product at. An array of shape [N2, ], where N2 is the number of points and is the shape of the arrays that represent the points in a given space. Defaults to None, in which case X is used for X2. :param ``**kwargs``: Any additional parameters. :return: An array of shape [N, N2, L]. .. py:method:: phi_product_diag(X, **kwargs) :abstractmethod: Computes the diagonals of the matrices ``phi_product(X, X, **kwargs)[:, :, l]``, $0 \leq l < L$. :param X: As in :meth:`phi_product`. :param ``**kwargs``: As in :meth:`phi_product`. :return: An array of shape [N, L]. .. py:method:: weighted_outerproduct(weights, X, X2 = None, **kwargs) Computes .. math:: \sum_{l=0}^{L-1} w_l \sum_{s=1}^{d_l} f_{l s}(x_1) f_{l s}(x_2). for all $x_1$ in `X` and all $x_2$ in `X2`, where $w_l$ are `weights`. :param weights: An array of shape [L, 1] where L is the number of levels. :param X: The first of the two batches of points to evaluate the weighted outer product at. An array of shape [N, ], where N is the number of points and is the shape of the arrays that represent the points in a given space. :param X2: The second of the two batches of points to evaluate the weighted outer product at. An array of shape [N2, ], where N2 is the number of points and is the shape of the arrays that represent the points in a given space. Defaults to None, in which case X is used for X2. :param ``**kwargs``: Any additional parameters. :return: An array of shape [N, N2]. .. py:method:: weighted_outerproduct_diag(weights, X, **kwargs) Computes the diagonal of the matrix ``weighted_outerproduct(weights, X, X, **kwargs)``. :param weights: As in :meth:`weighted_outerproduct`. :param X: As in :meth:`weighted_outerproduct`. :param ``**kwargs``: As in :meth:`weighted_outerproduct`. :return: An array of shape [N,]. .. py:property:: num_eigenfunctions :type: int The number J of eigenfunctions. .. py:property:: num_levels :type: int The number L of levels. .. py:class:: EigenfunctionsFromEigenvectors(eigenvectors) Bases: :py:obj:`Eigenfunctions` Turns an array of eigenvectors into an :class:`Eigenfunctions` instance. The resulting eigenfunctions' inputs are given by the indices. Each individual eigenfunction corresponds to a separate level. :param eigenvectors: Array of shape [D, J] containing J eigenvectors of dimension D. .. py:method:: __call__(X, **kwargs) Takes the values of the `J` stored eigenvectors `self.eigenvectors` that correspond to the indices in `X`. :param X: Indices, an array of shape [N, 1]. :param ``**kwargs``: Ignored. :return: An array of shape [N, J], whose element with index (n, j) corresponds to the X[n]-th element of the j-th eigenvector. .. py:method:: phi_product(X, X2 = None, **kwargs) Computes the .. math:: \sum_{s=1}^{d_l} f_{l s}(x_1) f_{l s}(x_2) for all $x_1$ in `X`, all $x_2$ in `X2`, and $0 \leq l < L$. :param X: The first of the two batches of points to evaluate the phi product at. An array of shape [N, ], where N is the number of points and is the shape of the arrays that represent the points in a given space. :param X2: The second of the two batches of points to evaluate the phi product at. An array of shape [N2, ], where N2 is the number of points and is the shape of the arrays that represent the points in a given space. Defaults to None, in which case X is used for X2. :param ``**kwargs``: Any additional parameters. :return: An array of shape [N, N2, L]. .. py:method:: phi_product_diag(X, **kwargs) Computes the diagonals of the matrices ``phi_product(X, X, **kwargs)[:, :, l]``, $0 \leq l < L$. :param X: As in :meth:`phi_product`. :param ``**kwargs``: As in :meth:`phi_product`. :return: An array of shape [N, L]. .. py:method:: weighted_outerproduct(weights, X, X2 = None, **kwargs) Computes .. math:: \sum_{l=0}^{L-1} w_l \sum_{s=1}^{d_l} f_{l s}(x_1) f_{l s}(x_2). for all $x_1$ in `X` and all $x_2$ in `X2`, where $w_l$ are `weights`. :param weights: An array of shape [L, 1] where L is the number of levels. :param X: The first of the two batches of points to evaluate the weighted outer product at. An array of shape [N, ], where N is the number of points and is the shape of the arrays that represent the points in a given space. :param X2: The second of the two batches of points to evaluate the weighted outer product at. An array of shape [N2, ], where N2 is the number of points and is the shape of the arrays that represent the points in a given space. Defaults to None, in which case X is used for X2. :param ``**kwargs``: Any additional parameters. :return: An array of shape [N, N2]. .. py:method:: weighted_outerproduct_diag(weights, X, **kwargs) Computes the diagonal of the matrix ``weighted_outerproduct(weights, X, X, **kwargs)``. :param weights: As in :meth:`weighted_outerproduct`. :param X: As in :meth:`weighted_outerproduct`. :param ``**kwargs``: As in :meth:`weighted_outerproduct`. :return: An array of shape [N,]. .. py:property:: num_eigenfunctions :type: int The number J of eigenfunctions. .. py:property:: num_eigenfunctions_per_level :type: beartype.typing.List[int] Number of eigenfunctions per level. Returns a list of J ones. .. py:property:: num_levels :type: int Number of levels. Returns J, same as :meth:`num_eigenfunctions`. .. py:class:: EigenfunctionsWithAdditionTheorem Bases: :py:obj:`Eigenfunctions` Eigenfunctions for which the sum of outer products over a level has a simpler expression. .. note:: See a brief introduction into the notion of addition theorems in the :doc:`respective documentation page `. .. py:method:: __call__(X, **kwargs) :abstractmethod: Evaluate the individual eigenfunctions at a batch of input locations. :param X: Points to evaluate the eigenfunctions at, an array of shape [N, ], where N is the number of points and is the shape of the arrays that represent the points in a given space. :param ``**kwargs``: Any additional parameters. :return: An [N, J]-shaped array, where `J` is the number of eigenfunctions. .. py:method:: phi_product(X, X2 = None, **kwargs) Computes the .. math:: \sum_{s=1}^{d_l} f_{l s}(x_1) f_{l s}(x_2) for all $x_1$ in `X`, all $x_2$ in `X2`, and $0 \leq l < L$. :param X: The first of the two batches of points to evaluate the phi product at. An array of shape [N, ], where N is the number of points and is the shape of the arrays that represent the points in a given space. :param X2: The second of the two batches of points to evaluate the phi product at. An array of shape [N2, ], where N2 is the number of points and is the shape of the arrays that represent the points in a given space. Defaults to None, in which case X is used for X2. :param ``**kwargs``: Any additional parameters. :return: An array of shape [N, N2, L]. .. py:method:: phi_product_diag(X, **kwargs) Computes the diagonals of the matrices ``phi_product(X, X, **kwargs)[:, :, l]``, $0 \leq l < L$. :param X: As in :meth:`phi_product`. :param ``**kwargs``: As in :meth:`phi_product`. :return: An array of shape [N, L].