Coverage for tests / spaces / test_hypercube_graph.py: 100%
31 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-22 15:49 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-22 15:49 +0000
1import lab as B
2import numpy as np
3import pytest
5from geometric_kernels.kernels import MaternGeometricKernel
6from geometric_kernels.spaces import HypercubeGraph
7from geometric_kernels.utils.kernel_formulas import hypercube_graph_heat_kernel
9from ..helper import check_function_with_backend
12@pytest.fixture(params=[1, 2, 3, 5, 10])
13def inputs(request) -> tuple[B.Numeric]:
14 """
15 Returns a tuple (space, eigenfunctions, X, X2) where:
16 - space is a HypercubeGraph object with dimension equal to request.param,
17 - eigenfunctions is the respective Eigenfunctions object with at most 5 levels,
18 - X is a random sample of random size from the space,
19 - X2 is another random sample of random size from the space,
20 - weights is an array of positive numbers of shape (eigenfunctions.num_levels, 1).
21 """
22 d = request.param
23 space = HypercubeGraph(d)
24 eigenfunctions = space.get_eigenfunctions(min(space.dim + 1, 5))
26 key = np.random.RandomState(0)
27 N, N2 = key.randint(low=1, high=min(2**d, 10) + 1, size=2)
28 key, X = space.random(key, N)
29 key, X2 = space.random(key, N2)
31 # These weights are used for testing the weighted outerproduct, they
32 # should be positive.
33 weights = np.random.rand(eigenfunctions.num_levels, 1) ** 2 + 1e-5
35 return space, eigenfunctions, X, X2, weights
38def test_numbers_of_eigenfunctions(inputs):
39 space, eigenfunctions, _, _, _ = inputs
40 num_levels = eigenfunctions.num_levels
42 # If the number of levels is maximal, check that the number of
43 # eigenfunctions is equal to the number of binary vectors of size `space.dim`.
44 if num_levels == space.dim + 1:
45 assert eigenfunctions.num_eigenfunctions == 2**space.dim
48@pytest.mark.parametrize("lengthscale", [1.0, 5.0, 10.0])
49@pytest.mark.parametrize("backend", ["numpy", "tensorflow", "torch", "jax"])
50def test_against_analytic_heat_kernel(inputs, lengthscale, backend):
51 space, _, X, X2, _ = inputs
52 lengthscale = np.array([lengthscale])
53 result = hypercube_graph_heat_kernel(lengthscale, X, X2)
55 kernel = MaternGeometricKernel(space)
57 # Check that MaternGeometricKernel on HypercubeGraph with nu=infinity
58 # coincides with the closed form expression for the heat kernel on the
59 # hypercube graph.
60 check_function_with_backend(
61 backend,
62 result,
63 kernel.K,
64 {"nu": np.array([np.inf]), "lengthscale": lengthscale},
65 X,
66 X2,
67 atol=1e-2,
68 )