Coverage for moptipy / tests / encoding.py: 74%

76 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-24 08:49 +0000

1"""Functions that can be used to test encodings.""" 

2from typing import Any, Callable 

3 

4from pycommons.types import type_error 

5 

6from moptipy.api.encoding import Encoding, check_encoding 

7from moptipy.api.space import Space 

8from moptipy.tests.component import validate_component 

9 

10 

11def validate_encoding(encoding: Encoding, 

12 search_space: Space | None = None, 

13 solution_space: Space | None = None, 

14 make_search_space_element_valid: 

15 Callable[[Any], Any] | None = lambda x: x, 

16 is_deterministic: bool = True) -> None: 

17 """ 

18 Check whether an object is a proper moptipy encoding. 

19 

20 :param encoding: the encoding to test 

21 :param search_space: the search space 

22 :param make_search_space_element_valid: a method that can turn a point 

23 from the space into a valid point 

24 :param solution_space: the solution space 

25 :param is_deterministic: is the mapping deterministic? 

26 :raises ValueError: if `encoding` is not a valid 

27 :class:`~moptipy.api.encoding.Encoding` 

28 :raises TypeError: if `encoding` is of the wrong type or a wrong type is 

29 encountered 

30 """ 

31 if not isinstance(encoding, Encoding): 

32 raise type_error(encoding, "encoding", Encoding) 

33 check_encoding(encoding) 

34 validate_component(encoding) 

35 

36 count: int = 0 

37 if search_space is not None: 

38 count += 1 

39 if make_search_space_element_valid is not None: 

40 count += 1 

41 if solution_space is not None: 

42 count += 1 

43 if count <= 0: 

44 return 

45 if count < 3: 

46 raise ValueError( 

47 "either provide all of search_space, " 

48 "make_search_space_element_valid, and solution_space or none.") 

49 

50 x1 = search_space.create() 

51 if x1 is None: 

52 raise ValueError("Provided search space created None?") 

53 x1 = make_search_space_element_valid(x1) 

54 search_space.validate(x1) 

55 

56 y1 = solution_space.create() 

57 if y1 is None: 

58 raise ValueError("Provided solution space created None?") 

59 

60 if not (hasattr(encoding, "decode") and callable(getattr( 

61 encoding, "decode"))): 

62 raise ValueError("encoding must have method decode.") 

63 

64 encoding.decode(x1, y1) 

65 solution_space.validate(y1) 

66 s1: str = solution_space.to_str(y1) 

67 if s1 is None: 

68 raise ValueError("to_str() returned None!") 

69 if len(s1) <= 0: 

70 raise ValueError("to_str() return empty string") 

71 

72 y2 = solution_space.create() 

73 if y2 is None: 

74 raise ValueError("Provided solution space created None?") 

75 if y1 is y2: 

76 raise ValueError("Provided solution space created " 

77 "identical points?") 

78 encoding.decode(x1, y2) 

79 solution_space.validate(y2) 

80 s2: str = solution_space.to_str(y2) 

81 if s2 is None: 

82 raise ValueError("to_str() returned None!") 

83 if len(s2) <= 0: 

84 raise ValueError("to_str() return empty string") 

85 if is_deterministic: 

86 if not solution_space.is_equal(y1, y2): 

87 raise ValueError("Encoding must be deterministic and decode " 

88 "identical points to same result.") 

89 if s1 != s2: 

90 raise ValueError(f"to_str(y1)={s1!r} but to_str(y2)={s2!r}!") 

91 

92 x2 = search_space.create() 

93 if x2 is None: 

94 raise ValueError("Provided search space created None?") 

95 if x1 is x2: 

96 raise ValueError("Provided search space created " 

97 "identical points?") 

98 

99 search_space.copy(x2, x1) 

100 if not search_space.is_equal(x1, x2): 

101 raise ValueError("Copy method of search space did not result in " 

102 "is_equal becoming true?") 

103 search_space.validate(x2) 

104 

105 encoding.decode(x2, y2) 

106 solution_space.validate(y2) 

107 s2 = solution_space.to_str(y2) 

108 if s2 is None: 

109 raise ValueError("to_str() returned None!") 

110 if len(s2) <= 0: 

111 raise ValueError("to_str() return empty string") 

112 

113 if is_deterministic: 

114 if not solution_space.is_equal(y1, y2): 

115 raise ValueError("Encoding must be deterministic and decode " 

116 "equal points to same result.") 

117 if s1 != s2: 

118 raise ValueError(f"to_str(y1)={s1!r} but to_str(y2)={s2!r}!")