Coverage for mlos_core/mlos_core/tests/spaces/adapters/space_adapter_factory_test.py: 97%

35 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-05 00:36 +0000

1# 

2# Copyright (c) Microsoft Corporation. 

3# Licensed under the MIT License. 

4# 

5""" 

6Tests for space adapter factory. 

7""" 

8 

9# pylint: disable=missing-function-docstring 

10 

11from typing import List, Optional, Type 

12 

13import pytest 

14 

15import ConfigSpace as CS 

16 

17from mlos_core.spaces.adapters import SpaceAdapterFactory, SpaceAdapterType, ConcreteSpaceAdapter 

18from mlos_core.spaces.adapters.adapter import BaseSpaceAdapter 

19from mlos_core.spaces.adapters.identity_adapter import IdentityAdapter 

20 

21from mlos_core.tests import get_all_concrete_subclasses 

22 

23 

24@pytest.mark.parametrize(('space_adapter_type'), [ 

25 # Enumerate all supported SpaceAdapters 

26 # *[member for member in SpaceAdapterType], 

27 *list(SpaceAdapterType), 

28]) 

29def test_concrete_optimizer_type(space_adapter_type: SpaceAdapterType) -> None: 

30 """ 

31 Test that all optimizer types are listed in the ConcreteOptimizer constraints. 

32 """ 

33 # pylint: disable=no-member 

34 assert space_adapter_type.value in ConcreteSpaceAdapter.__constraints__ # type: ignore[attr-defined] 

35 

36 

37@pytest.mark.parametrize(('space_adapter_type', 'kwargs'), [ 

38 # Default space adapter 

39 (None, {}), 

40 # Enumerate all supported Optimizers 

41 *[(member, {}) for member in SpaceAdapterType], 

42]) 

43def test_create_space_adapter_with_factory_method(space_adapter_type: Optional[SpaceAdapterType], kwargs: Optional[dict]) -> None: 

44 # Start defining a ConfigurationSpace for the Optimizer to search. 

45 input_space = CS.ConfigurationSpace(seed=1234) 

46 

47 # Add a single continuous input dimension between 0 and 1. 

48 input_space.add_hyperparameter(CS.UniformFloatHyperparameter(name='x', lower=0, upper=1)) 

49 # Add a single continuous input dimension between 0 and 1. 

50 input_space.add_hyperparameter(CS.UniformFloatHyperparameter(name='y', lower=0, upper=1)) 

51 

52 # Adjust some kwargs for specific space adapters 

53 if space_adapter_type is SpaceAdapterType.LLAMATUNE: 

54 if kwargs is None: 

55 kwargs = {} 

56 kwargs.setdefault('num_low_dims', 1) 

57 

58 space_adapter: BaseSpaceAdapter 

59 if space_adapter_type is None: 

60 space_adapter = SpaceAdapterFactory.create(parameter_space=input_space) 

61 else: 

62 space_adapter = SpaceAdapterFactory.create( 

63 parameter_space=input_space, 

64 space_adapter_type=space_adapter_type, 

65 space_adapter_kwargs=kwargs, 

66 ) 

67 

68 if space_adapter_type is None or space_adapter_type is SpaceAdapterType.IDENTITY: 

69 assert isinstance(space_adapter, IdentityAdapter) 

70 else: 

71 assert space_adapter is not None 

72 assert space_adapter.orig_parameter_space is not None 

73 myrepr = repr(space_adapter) 

74 assert myrepr.startswith(space_adapter_type.value.__name__), \ 

75 f"Expected {space_adapter_type.value.__name__} but got {myrepr}" 

76 

77 

78# Dynamically determine all of the optimizers we have implemented. 

79# Note: these must be sorted. 

80space_adapter_subclasses: List[Type[BaseSpaceAdapter]] = \ 

81 get_all_concrete_subclasses(BaseSpaceAdapter, pkg_name='mlos_core') # type: ignore[type-abstract] 

82assert space_adapter_subclasses 

83 

84 

85@pytest.mark.parametrize(('space_adapter_class'), space_adapter_subclasses) 

86def test_space_adapter_type_defs(space_adapter_class: Type[BaseSpaceAdapter]) -> None: 

87 """ 

88 Test that all space adapter classes are listed in the SpaceAdapterType enum. 

89 """ 

90 space_adapter_type_classes = {space_adapter_type.value for space_adapter_type in SpaceAdapterType} 

91 assert space_adapter_class in space_adapter_type_classes