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

1import lab as B 

2import numpy as np 

3import pytest 

4 

5from geometric_kernels.kernels import MaternGeometricKernel 

6from geometric_kernels.spaces import HypercubeGraph 

7from geometric_kernels.utils.kernel_formulas import hypercube_graph_heat_kernel 

8 

9from ..helper import check_function_with_backend 

10 

11 

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)) 

25 

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) 

30 

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 

34 

35 return space, eigenfunctions, X, X2, weights 

36 

37 

38def test_numbers_of_eigenfunctions(inputs): 

39 space, eigenfunctions, _, _, _ = inputs 

40 num_levels = eigenfunctions.num_levels 

41 

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 

46 

47 

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) 

54 

55 kernel = MaternGeometricKernel(space) 

56 

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 )