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
« 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
4from pycommons.types import type_error
6from moptipy.api.encoding import Encoding, check_encoding
7from moptipy.api.space import Space
8from moptipy.tests.component import validate_component
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.
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)
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.")
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)
56 y1 = solution_space.create()
57 if y1 is None:
58 raise ValueError("Provided solution space created None?")
60 if not (hasattr(encoding, "decode") and callable(getattr(
61 encoding, "decode"))):
62 raise ValueError("encoding must have method decode.")
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")
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}!")
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?")
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)
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")
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}!")