Coverage for geometric_kernels/spaces/base.py: 74%
57 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-16 21:43 +0000
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-16 21:43 +0000
1"""
2Abstract base classes for all spaces (input domains) in the library.
3"""
5import abc
7import lab as B
8from beartype.typing import List, Optional
10from geometric_kernels.spaces.eigenfunctions import Eigenfunctions
13class Space(abc.ABC):
14 """
15 A space (input domain) on which a geometric kernel can be defined.
16 """
18 @abc.abstractproperty
19 def dimension(self) -> int:
20 """
21 Geometric dimension of the space.
23 Examples:
25 * :class:`~.spaces.Graph`: 0-dimensional.
26 * :class:`~.spaces.Circle`: 1-dimensional.
27 * :class:`~.spaces.Hypersphere`: d-dimensional, with d >= 2.
28 * :class:`~.spaces.Hyperbolic`: d-dimensional, with d >= 2.
29 """
30 raise NotImplementedError
32 @abc.abstractproperty
33 def element_shape(self) -> List[int]:
34 """
35 Shape of an element.
37 Examples:
38 * :class:`~.spaces.Hypersphere`: [D + 1, ]
39 * :class:`~.spaces.Mesh`: [1, ]
40 * :class:`~.spaces.CompactMatrixLieGroup`: [n, n]
41 """
42 raise NotImplementedError
44 @abc.abstractproperty
45 def element_dtype(self) -> B.DType:
46 """
47 Abstract DType of an element.
49 Examples:
50 * :class:`~.spaces.Hypersphere`: B.Float
51 * :class:`~.spaces.Mesh`: B.Int
52 * :class:`~.spaces.SpecialUnitary`: B.Complex
53 """
54 raise NotImplementedError
57class DiscreteSpectrumSpace(Space):
58 r"""
59 A Space with discrete spectrum (of the Laplacian operator).
61 This includes, for instance, compact Riemannian manifolds, graphs & meshes.
63 Subclasses implement routines for computing the eigenvalues and
64 eigenfunctions of the Laplacian operator, or certain combinations thereof.
65 Since there is often an infinite or a prohibitively large number of those,
66 they only compute a finite subset, consisting of the ones that are most
67 important for approximating Matérn kernel best.
69 .. note::
70 See a brief introduction into the theory behind the geometric
71 kernels on discrete spectrum spaces on the documentation pages devoted
72 to :doc:`compact Riemannian manifolds </theory/compact>` (also
73 :doc:`this </theory/addition_theorem>`), :doc:`graphs
74 </theory/graphs>` and :doc:`meshes </theory/meshes>`.
76 .. note::
77 Typically used with :class:`~.kernels.MaternKarhunenLoeveKernel`.
79 """
81 @abc.abstractproperty
82 def dimension(self) -> int:
83 """
84 Geometric dimension of the space.
86 Examples:
88 * :class:`~.spaces.Graph`: 0-dimensional.
89 * :class:`~.spaces.Circle`: 1-dimensional.
90 * :class:`~.spaces.Hypersphere`: d-dimensional, with d >= 2.
91 """
92 raise NotImplementedError
94 @abc.abstractmethod
95 def get_eigenfunctions(self, num: int) -> Eigenfunctions:
96 """
97 Returns the :class:`~.Eigenfunctions` object with `num` levels.
99 :param num:
100 Number of levels.
102 .. note::
103 The notion of *levels* is discussed in the documentation of the
104 :class:`~.kernels.MaternKarhunenLoeveKernel`.
105 """
106 raise NotImplementedError
108 @abc.abstractmethod
109 def get_eigenvalues(self, num: int) -> B.Numeric:
110 """
111 Eigenvalues of the Laplacian corresponding to the first `num` levels.
113 :param num:
114 Number of levels.
115 :return:
116 (num, 1)-shaped array containing the eigenvalues.
118 .. note::
119 The notion of *levels* is discussed in the documentation of the
120 :class:`~.kernels.MaternKarhunenLoeveKernel`.
121 """
122 raise NotImplementedError
124 @abc.abstractmethod
125 def get_repeated_eigenvalues(self, num: int) -> B.Numeric:
126 """
127 Eigenvalues of the Laplacian corresponding to the first `num` levels,
128 repeated according to their multiplicity within levels.
130 :param num:
131 Number of levels.
133 :return:
134 (J, 1)-shaped array containing the repeated eigenvalues, J is
135 the resulting number of the repeated eigenvalues.
137 .. note::
138 The notion of *levels* is discussed in the documentation of the
139 :class:`~.kernels.MaternKarhunenLoeveKernel`.
140 """
141 raise NotImplementedError
143 @abc.abstractmethod
144 def random(self, key: B.RandomState, number: int) -> B.Numeric:
145 """
146 Sample uniformly random points in the space.
148 :param key:
149 Either `np.random.RandomState`, `tf.random.Generator`,
150 `torch.Generator` or `jax.tensor` (representing random state).
151 :param number:
152 Number of samples to draw.
154 :return:
155 An array of `number` uniformly random samples on the space.
156 """
157 raise NotImplementedError
160class HodgeDiscreteSpectrumSpace(DiscreteSpectrumSpace):
161 r"""
162 A Space with discrete spectrum (of the Laplacian) and Hodge decomposition.
164 Separates eigenpairs according to the Hodge decomposition, into the curl
165 type (divergence-free), the gradient type (curl-free), and the harmonic
166 type (both divergence- and curl-free).
168 Examples of such spaces are the edge space of a graph, or tangent bundles
169 of compact Riemannian manifolds.
171 .. note::
172 Hodge decomposition is briefly discussed on :doc:`this </theory/graphs>`
173 documentation page.
175 .. note::
176 Typically used with :class:`~.kernels.MaternHodgeCompositionalKernel`.
177 """
179 @abc.abstractmethod
180 def get_eigenfunctions(
181 self, num: int, type: Optional[str] = None
182 ) -> Eigenfunctions:
183 """
184 Returns the :class:`~.Eigenfunctions` object with `num` levels.
185 If `type` is specified, returns only the eigenfunctions of that type.
187 .. warning::
188 If `type` is specified, the returned :class:`~.Eigenfunctions`
189 object does not have to have `num` levels. It can have fewer but can
190 never have more.
192 :param num:
193 Number of levels.
195 :param type:
196 Type of the eigenfunctions to return. Can be one of "harmonic",
197 "curl" or "gradient".
199 .. note::
200 The notion of *levels* is discussed in the documentation of the
201 :class:`~.kernels.MaternKarhunenLoeveKernel`.
202 """
203 raise NotImplementedError
205 @abc.abstractmethod
206 def get_eigenvalues(self, num: int, type: Optional[str] = None) -> B.Numeric:
207 """
208 Eigenvalues of the Laplacian corresponding to the first `num` levels.
209 If `type` is specified, returns only the eigenvalues corresponding to
210 the eigenfunctions of that type.
212 .. warning::
213 If `type` is specified, the array can have fewer than `num` elements.
215 :param num:
216 Number of levels.
218 :return:
219 (n, 1)-shaped array containing the eigenvalues. n <= num.
221 .. note::
222 The notion of *levels* is discussed in the documentation of the
223 :class:`~.kernels.MaternKarhunenLoeveKernel`.
224 """
225 raise NotImplementedError
227 @abc.abstractmethod
228 def get_repeated_eigenvalues(
229 self, num: int, type: Optional[str] = None
230 ) -> B.Numeric:
231 """
232 Eigenvalues of the Laplacian corresponding to the first `num` levels,
233 repeated according to their multiplicity within levels. If `type` is
234 specified, returns only the eigenvalues corresponding to the
235 eigenfunctions of that type.
237 :param num:
238 Number of levels.
240 :param type:
241 Type of the eigenvalues to return. Can be one of "harmonic",
242 "curl" or "gradient".
244 :return:
245 (J, 1)-shaped array containing the repeated eigenvalues, J is
246 the resulting number of the repeated eigenvalues (of the specified
247 type, if `type` is given).
249 .. note::
250 The notion of *levels* is discussed in the documentation of the
251 :class:`~.kernels.MaternKarhunenLoeveKernel`.
252 """
253 raise NotImplementedError
256class NoncompactSymmetricSpace(Space):
257 """
258 Non-compact symmetric space.
260 This includes, for instance, hyperbolic spaces and manifolds of symmetric
261 positive definite matrices (endowed with the affine-invariant metric).
263 .. note::
264 See a brief introduction into the theory behind the geometric
265 kernels on non-compact symmetric spaces on the
266 :doc:`respective documentation page </theory/symmetric>`.
268 .. note::
269 Typically used with :class:`~.kernels.MaternFeatureMapKernel` that
270 builds on a space-specific feature map like the
271 :class:`~.feature_maps.RejectionSamplingFeatureMapHyperbolic` and the
272 :class:`~.feature_maps.RejectionSamplingFeatureMapSPD`, or, in the
273 absence of a space-specific feature map, on the general (typically less
274 effective) map :class:`~.feature_maps.RandomPhaseFeatureMapNoncompact`.
276 .. note:: .. _quotient note:
278 Mathematically, any non-compact symmetric space can be represented as
279 a quotient $G/H$ of a Lie group of symmetries $G$ and its compact
280 isotropy subgroup $H$. We sometimes refer to these $G$ and $H$ in
281 the documentation. See mathematical details in :cite:t:`azangulov2024b`.
282 """
284 @abc.abstractproperty
285 def dimension(self) -> int:
286 """
287 Geometric dimension of the space.
289 Examples:
291 * :class:`~.spaces.Hyperbolic`: d-dimensional, with d >= 2.
292 * :class:`~.spaces.SymmetricPositiveDefiniteMatrices`: $n(n+1)/2$-dimensional,
293 with n >= 2.
294 """
295 raise NotImplementedError
297 @abc.abstractmethod
298 def inv_harish_chandra(self, lam: B.Numeric) -> B.Numeric:
299 r"""
300 Implements $c^{-1}(\lambda)$, where $c$ is the Harish-Chandra's $c$
301 function.
303 This is one of the computational primitives required to (approximately)
304 compute the :class:`~.feature_maps.RandomPhaseFeatureMapNoncompact`
305 feature map and :class:`~.kernels.MaternFeatureMapKernel` on top of it.
307 :param lam:
308 A batch of frequencies, vectors of dimension equal to the rank of
309 symmetric space.
311 :return:
312 $c^{-1}(\lambda)$ evaluated at every $\lambda$ in the batch `lam`.
313 """
314 raise NotImplementedError
316 @abc.abstractmethod
317 def power_function(self, lam: B.Numeric, g: B.Numeric, h: B.Numeric) -> B.Numeric:
318 r"""
319 Implements the *power function* $p^{\lambda}(g, h)$, the integrand
320 appearing in the definition of the zonal spherical function
322 .. math:: \pi^{\lambda}(g) = \int_{H} \underbrace{p^{\lambda}(g, h)}_{= e^{(i \lambda + \rho) a(h \cdot g)}} d h,
324 where $\lambda \in i \cdot \mathbb{R}^r$, with $r$ denoting the rank of
325 the symmetric space and $i$ the imaginary unit, is a sort of frequency,
326 $g$ is an element of the group of symmetries $G$, $h$ is an element
327 of its isotropy subgroup $H$ ($G$ and $H$ are defined :ref:`here
328 <quotient note>`), $\rho \in \mathbb{R}^r$ is as in :meth:`rho`, and
329 the function $a$ is a certain space-dependent algebraic operation.
331 This is one of the computational primitives required to (approximately)
332 compute the :class:`~.feature_maps.RandomPhaseFeatureMapNoncompact`
333 feature map and :class:`~.kernels.MaternFeatureMapKernel` on top of it.
335 :param lam:
336 A batch of L vectors of dimension `rank`, the rank of the
337 symmetric space, representing the "sort of frequencies".
339 Typically of shape [1, L, rank].
340 :param g:
341 A batch of N elements of the space (these can always be thought of
342 as elements of the group of symmetries $G$ since the symmetric
343 space $G/H$ can be trivially embedded into the group $G$).
345 Typically of shape [N, 1, <axes>], where <axes> is the shape of
346 the elements of the space.
347 :param h:
348 A batch of L elements of the isotropy subgroup $H$.
350 Typically of shape [1, L, <axes_p>], where <axes_p> is the shape of
351 arrays representing the elements of the isotropy subgroup $H$.
353 :return:
354 An array of shape [N, L] with complex number entries, representing
355 the value of the values of $p^{\lambda_l}(g_n, h_l)$ for all
356 $1 \leq n \leq N$ and $1 \leq l \leq L$.
358 .. note::
359 Actually, $a$ may be a more appropriate primitive than the power
360 function $p^{\lambda}$: everything but $a$ in the definition of
361 the latter is either standard or available as other primitives.
362 Us using $p^{\lambda}$ as a primitive is quite arbitrary.
363 """
364 raise NotImplementedError
366 @abc.abstractproperty
367 def rho(self):
368 r"""
369 `rho` vector of dimension equal to the rank of the symmetric space.
371 Algebraically, weighted sum of *roots*, depends only on the space.
373 This is one of the computational primitives required to (approximately)
374 compute the :class:`~.feature_maps.RandomPhaseFeatureMapNoncompact`
375 feature map and :class:`~.kernels.MaternFeatureMapKernel` on top of it.
376 """
377 raise NotImplementedError
379 @abc.abstractmethod
380 def random_phases(self, key: B.RandomState, num: int) -> B.Numeric:
381 r"""
382 Sample uniformly random points on the isotropy subgroup $H$ (defined
383 :ref:`here <quotient note>`).
385 This is one of the computational primitives required to (approximately)
386 compute the :class:`~.feature_maps.RandomPhaseFeatureMapNoncompact`
387 feature map and :class:`~.kernels.MaternFeatureMapKernel` on top of it.
389 :param key:
390 Either `np.random.RandomState`, `tf.random.Generator`,
391 `torch.Generator` or `jax.tensor` (representing random state).
392 :param num:
393 Number of samples to draw.
395 :return:
396 An array of `num` uniformly random samples in the isotropy
397 subgroup $H$.
399 .. warning::
400 This does not sample random points on the space itself. Since the
401 space itself is non-compact, uniform sampling on it is in principle
402 impossible. However, the isotropy subgroup $H$ is always
403 compact and thus allows uniform sampling needed to approximate the
404 zonal spherical functions $\pi^{\lambda}(\cdot)$ via Monte Carlo.
405 """
407 @abc.abstractproperty
408 def num_axes(self):
409 """
410 Number of axes in an array representing a point in the space.
412 Usually 1 for vectors or 2 for matrices.
413 """