Coverage for moptipy / tests / on_intspaces.py: 92%
53 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-15 11:18 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-15 11:18 +0000
1"""Test stuff on integer spaces."""
3from typing import Any, Callable, Iterable, cast
5import numpy as np
6from numpy.random import Generator, default_rng
7from pycommons.types import type_error
9from moptipy.api.operators import Op0, Op1, Op2
10from moptipy.spaces.intspace import IntSpace
11from moptipy.tests.op0 import validate_op0
12from moptipy.tests.op1 import validate_op1
13from moptipy.tests.op2 import validate_op2
16def intspaces_for_tests(
17 space_filter: Callable[[IntSpace], bool] | None = None)\
18 -> Iterable[IntSpace]:
19 """
20 Get a sequence of integer spaces for tests.
22 :param perm_filter: an optional filter to sort out permutations we cannot
23 use for testing
24 :returns: the sequence of SignedPermutations
25 """
26 r = default_rng()
27 pwrs: list[IntSpace] = [
28 IntSpace(1, 0, 1),
29 IntSpace(2, 0, 1),
30 IntSpace(9, 0, 1),
31 IntSpace(1, -1, 1),
32 IntSpace(2, -1, 1),
33 IntSpace(13, -1, 1),
34 IntSpace(1, -12, 17),
35 IntSpace(2, -11, 9),
36 IntSpace(16, -23, 25),
37 IntSpace(1, 0, 127),
38 IntSpace(2, -128, 127),
39 IntSpace(1, -128, 128),
40 IntSpace(1, -2**15, 2**15 - 1),
41 IntSpace(1, -2**15, 2**15),
42 IntSpace(*map(int, (
43 r.integers(1, 100), r.integers(0, 10), r.integers(10, 100)))),
44 IntSpace(*map(int, (
45 r.integers(1, 100), r.integers(-100, 0), r.integers(1, 100)))),
46 IntSpace(*map(int, (
47 r.integers(1, 100), r.integers(-100, -10),
48 r.integers(-9, 100))))]
49 if space_filter is not None:
50 if not callable(space_filter):
51 raise type_error(space_filter, "perm_filter", None, call=True)
52 pwrs = [p for p in pwrs if space_filter(p)]
53 r.shuffle(cast("list", pwrs))
54 return pwrs
57def make_ints_valid(space: IntSpace) -> \
58 Callable[[Generator, np.ndarray], np.ndarray]:
59 """
60 Create a function that can make an int vector valid.
62 :param space: the integer space
63 :returns: the function
64 """
65 def __make_valid(prnd: Generator, x: np.ndarray, ppp=space) -> np.ndarray:
66 np.copyto(x, prnd.integers(low=ppp.min_value, high=ppp.max_value,
67 size=ppp.dimension, endpoint=True))
68 return x
69 return __make_valid
72def validate_op0_on_1_intspace(
73 op0: Op0 | Callable[[IntSpace], Op0],
74 search_space: IntSpace,
75 number_of_samples: int | None = None,
76 min_unique_samples: int | Callable[[
77 int, IntSpace], int] | None = None) -> None:
78 """
79 Validate the nullary operator on one `IntSpace` instance.
81 :param op0: the operator or operator factory
82 :param search_space: the search space
83 :param number_of_samples: the optional number of samples
84 :param min_unique_samples: the optional unique samples
85 """
86 args: dict[str, Any] = {
87 "op0": op0(search_space) if callable(op0) else op0,
88 "search_space": search_space,
89 "make_search_space_element_valid":
90 make_ints_valid(search_space),
91 }
92 if number_of_samples is not None:
93 args["number_of_samples"] = number_of_samples
94 if min_unique_samples is not None:
95 args["min_unique_samples"] = min_unique_samples
96 validate_op0(**args)
99def validate_op0_on_intspaces(
100 op0: Op0 | Callable[[IntSpace], Op0],
101 number_of_samples: int | None = None,
102 min_unique_samples: int | Callable[[
103 int, IntSpace], int] | None = None,
104 space_filter: Callable[[IntSpace], bool] | None = None) \
105 -> None:
106 """
107 Validate the nullary operator on several `IntSpace` instances.
109 :param op0: the operator or operator factory
110 :param number_of_samples: the optional number of samples
111 :param min_unique_samples: the optional unique samples
112 :param space_filter: an optional filter to sort out permutations we cannot
113 use for testing
114 """
115 for pwr in intspaces_for_tests(space_filter):
116 validate_op0_on_1_intspace(
117 op0, pwr, number_of_samples, min_unique_samples)
120def validate_op1_on_1_intspace(
121 op1: Op1 | Callable[[IntSpace], Op1],
122 search_space: IntSpace,
123 number_of_samples: int | None = None,
124 min_unique_samples: int | Callable[[
125 int, IntSpace], int] | None = None) -> None:
126 """
127 Validate the unary operator on one `IntSpace` instance.
129 :param op1: the operator or operator factory
130 :param search_space: the search space
131 :param number_of_samples: the optional number of samples
132 :param min_unique_samples: the optional unique samples
133 """
134 args: dict[str, Any] = {
135 "op1": op1(search_space) if callable(op1) else op1,
136 "search_space": search_space,
137 "make_search_space_element_valid":
138 make_ints_valid(search_space),
139 }
140 if number_of_samples is not None:
141 args["number_of_samples"] = number_of_samples
142 if min_unique_samples is not None:
143 args["min_unique_samples"] = min_unique_samples
144 validate_op1(**args)
147def validate_op1_on_intspaces(
148 op1: Op1 | Callable[[IntSpace], Op1],
149 number_of_samples: int | None = None,
150 min_unique_samples: int | Callable[[
151 int, IntSpace], int] | None = None,
152 space_filter: Callable[[IntSpace], bool] | None = None) \
153 -> None:
154 """
155 Validate the unary operator on several `IntSpace` instances.
157 :param op1: the operator or operator factory
158 :param number_of_samples: the optional number of samples
159 :param min_unique_samples: the optional unique samples
160 :param space_filter: an optional filter to sort out permutations we cannot
161 use for testing
162 """
163 for pwr in intspaces_for_tests(space_filter):
164 validate_op1_on_1_intspace(
165 op1, pwr, number_of_samples, min_unique_samples)
168def validate_op2_on_1_intspace(
169 op2: Op2 | Callable[[IntSpace], Op2],
170 search_space: IntSpace,
171 number_of_samples: int | None = None,
172 min_unique_samples:
173 int | Callable[[int, IntSpace], int] | None
174 = None) -> None:
175 """
176 Validate the binary operator on one `IntSpace` instance.
178 :param op2: the operator or operator factory
179 :param search_space: the search space
180 :param number_of_samples: the optional number of samples
181 :param min_unique_samples: the optional unique samples
182 """
183 args: dict[str, Any] = {
184 "op2": op2(search_space) if callable(op2) else op2,
185 "search_space": search_space,
186 "make_search_space_element_valid": make_ints_valid(search_space),
187 }
188 if number_of_samples is not None:
189 args["number_of_samples"] = number_of_samples
190 if min_unique_samples is not None:
191 args["min_unique_samples"] = min_unique_samples
192 validate_op2(**args)
195def validate_op2_on_intspaces(
196 op2: Op2 | Callable[[IntSpace], Op2],
197 number_of_samples: int | None = None,
198 min_unique_samples:
199 int | Callable[[int, IntSpace], int] | None = None,
200 space_filter: Callable[[IntSpace], bool] | None = None) -> None:
201 """
202 Validate the binary operator on several `IntSpace` instances.
204 :param op2: the operator or operator factory
205 :param number_of_samples: the optional number of samples
206 :param min_unique_samples: the optional unique samples
207 :param space_filter: an optional filter to sort out permutations we cannot
208 use for testing
209 """
210 for bst in intspaces_for_tests(space_filter):
211 validate_op2_on_1_intspace(
212 op2, bst, number_of_samples, min_unique_samples)